Compare commits
139 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
a7de149fd7 | ||
|
|
ae38be36f5 | ||
|
|
a20e989211 | ||
|
|
579f47ba0d | ||
|
|
24cad87954 | ||
|
|
84d72cd110 | ||
|
|
c0cd46a5aa | ||
|
|
98613c43ca | ||
|
|
555960e210 | ||
|
|
a18ae5582b | ||
|
|
6d6894591c | ||
|
|
984b97fc14 | ||
|
|
a7f35d4495 | ||
|
|
add92cfa7c | ||
|
|
6079e76be5 | ||
|
|
166c7cb2f5 | ||
|
|
dbd3ca44c2 | ||
|
|
ae495dde54 | ||
|
|
4ae25b2f34 | ||
|
|
cdfb621c59 | ||
|
|
29e8df7d2e | ||
|
|
72ff947d95 | ||
|
|
3edaac5739 | ||
|
|
5777a97119 | ||
|
|
aeddbc1dcc | ||
|
|
2f3e409487 | ||
|
|
aa133bb50b | ||
|
|
3bc79a4ba1 | ||
|
|
064a04fbad | ||
|
|
39ed13cf8a | ||
|
|
a1edacb196 | ||
|
|
c9f79e4b47 | ||
|
|
40c1498226 | ||
|
|
390061f9bd | ||
|
|
42324a2c9e | ||
|
|
b9b4ca6360 | ||
|
|
565697bc0b | ||
|
|
2e6c82c851 | ||
|
|
ee75dd37af | ||
|
|
4859dcda08 | ||
|
|
2e962e555d | ||
|
|
ab73e5acb2 | ||
|
|
4e3e5ce130 | ||
|
|
bb8eef3bf5 | ||
|
|
eee87ded29 | ||
|
|
e0f005bd96 | ||
|
|
2cacc372ad | ||
|
|
0b1b681655 | ||
|
|
deafd73306 | ||
|
|
317a5da120 | ||
|
|
071cefc511 | ||
|
|
32a5cc8aa3 | ||
|
|
c41378a085 | ||
|
|
6910e03ef4 | ||
|
|
5060a358db | ||
|
|
b3e9a957c4 | ||
|
|
f6dbfc2dac | ||
|
|
2966a34e63 | ||
|
|
50959951ae | ||
|
|
c2e1cf7bdb | ||
|
|
51ac7cc8be | ||
|
|
3144f1d1c2 | ||
|
|
a176e7b912 | ||
|
|
1198ec0f74 | ||
|
|
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 |
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
7
.github/ISSUE_TEMPLATE/01_bug_report.yml
vendored
7
.github/ISSUE_TEMPLATE/01_bug_report.yml
vendored
@@ -3,6 +3,13 @@ description: 在提出问题前请先自行排除服务器端问题和升级到
|
|||||||
title: "[Bug]: "
|
title: "[Bug]: "
|
||||||
labels: ["bug"]
|
labels: ["bug"]
|
||||||
body:
|
body:
|
||||||
|
- type: input
|
||||||
|
id: "os-version"
|
||||||
|
attributes:
|
||||||
|
label: "操作系统和版本"
|
||||||
|
description: "操作系统和版本"
|
||||||
|
validations:
|
||||||
|
required: true
|
||||||
- type: input
|
- type: input
|
||||||
id: "expectation"
|
id: "expectation"
|
||||||
attributes:
|
attributes:
|
||||||
|
|||||||
9
.github/dependabot.yml
vendored
9
.github/dependabot.yml
vendored
@@ -1,10 +1,11 @@
|
|||||||
# Set update schedule for GitHub Actions
|
|
||||||
|
|
||||||
version: 2
|
version: 2
|
||||||
updates:
|
updates:
|
||||||
|
|
||||||
- package-ecosystem: "github-actions"
|
- package-ecosystem: "github-actions"
|
||||||
directory: "/"
|
directory: "/"
|
||||||
schedule:
|
schedule:
|
||||||
# Check for updates to GitHub Actions every daily
|
interval: "daily"
|
||||||
|
|
||||||
|
- package-ecosystem: "nuget"
|
||||||
|
directory: "/"
|
||||||
|
schedule:
|
||||||
interval: "daily"
|
interval: "daily"
|
||||||
|
|||||||
69
.github/workflows/build-all.yml
vendored
Normal file
69
.github/workflows/build-all.yml
vendored
Normal file
@@ -0,0 +1,69 @@
|
|||||||
|
name: release all platforms
|
||||||
|
|
||||||
|
on:
|
||||||
|
workflow_dispatch:
|
||||||
|
inputs:
|
||||||
|
release_tag:
|
||||||
|
required: false
|
||||||
|
type: string
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
update:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
|
||||||
|
- name: Trigger build windows
|
||||||
|
if: github.event.inputs.release_tag != ''
|
||||||
|
run: |
|
||||||
|
curl -X POST \
|
||||||
|
-H "Accept: application/vnd.github.v3+json" \
|
||||||
|
-H "Authorization: token ${{ secrets.GITHUB_TOKEN }}" \
|
||||||
|
https://api.github.com/repos/${{ github.repository }}/actions/workflows/build-windows.yml/dispatches \
|
||||||
|
-d "{
|
||||||
|
\"ref\": \"master\",
|
||||||
|
\"inputs\": {
|
||||||
|
\"release_tag\": \"${{ github.event.inputs.release_tag }}\"
|
||||||
|
}
|
||||||
|
}"
|
||||||
|
|
||||||
|
- name: Trigger build linux
|
||||||
|
if: github.event.inputs.release_tag != ''
|
||||||
|
run: |
|
||||||
|
curl -X POST \
|
||||||
|
-H "Accept: application/vnd.github.v3+json" \
|
||||||
|
-H "Authorization: token ${{ secrets.GITHUB_TOKEN }}" \
|
||||||
|
https://api.github.com/repos/${{ github.repository }}/actions/workflows/build-linux.yml/dispatches \
|
||||||
|
-d "{
|
||||||
|
\"ref\": \"master\",
|
||||||
|
\"inputs\": {
|
||||||
|
\"release_tag\": \"${{ github.event.inputs.release_tag }}\"
|
||||||
|
}
|
||||||
|
}"
|
||||||
|
|
||||||
|
- name: Trigger build osx
|
||||||
|
if: github.event.inputs.release_tag != ''
|
||||||
|
run: |
|
||||||
|
curl -X POST \
|
||||||
|
-H "Accept: application/vnd.github.v3+json" \
|
||||||
|
-H "Authorization: token ${{ secrets.GITHUB_TOKEN }}" \
|
||||||
|
https://api.github.com/repos/${{ github.repository }}/actions/workflows/build-osx.yml/dispatches \
|
||||||
|
-d "{
|
||||||
|
\"ref\": \"master\",
|
||||||
|
\"inputs\": {
|
||||||
|
\"release_tag\": \"${{ github.event.inputs.release_tag }}\"
|
||||||
|
}
|
||||||
|
}"
|
||||||
|
|
||||||
|
- name: Trigger build windows desktop
|
||||||
|
if: github.event.inputs.release_tag != ''
|
||||||
|
run: |
|
||||||
|
curl -X POST \
|
||||||
|
-H "Accept: application/vnd.github.v3+json" \
|
||||||
|
-H "Authorization: token ${{ secrets.GITHUB_TOKEN }}" \
|
||||||
|
https://api.github.com/repos/${{ github.repository }}/actions/workflows/build-windows-desktop.yml/dispatches \
|
||||||
|
-d "{
|
||||||
|
\"ref\": \"master\",
|
||||||
|
\"inputs\": {
|
||||||
|
\"release_tag\": \"${{ github.event.inputs.release_tag }}\"
|
||||||
|
}
|
||||||
|
}"
|
||||||
38
.github/workflows/build-linux.yml
vendored
38
.github/workflows/build-linux.yml
vendored
@@ -22,22 +22,30 @@ jobs:
|
|||||||
matrix:
|
matrix:
|
||||||
configuration: [Release]
|
configuration: [Release]
|
||||||
|
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-22.04
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout
|
- name: Checkout
|
||||||
uses: actions/checkout@v4
|
uses: actions/checkout@v4.2.2
|
||||||
|
with:
|
||||||
|
submodules: 'recursive'
|
||||||
|
fetch-depth: '0'
|
||||||
|
|
||||||
|
- name: Setup
|
||||||
|
uses: actions/setup-dotnet@v4.3.0
|
||||||
|
with:
|
||||||
|
dotnet-version: '8.0.x'
|
||||||
|
|
||||||
- name: Build
|
- name: Build
|
||||||
run: |
|
run: |
|
||||||
cd v2rayN
|
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-x64 --self-contained=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 ./v2rayN.Desktop/v2rayN.Desktop.csproj -c Release -r linux-arm64 --self-contained=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-x64 --self-contained=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 ./AmazTool/AmazTool.csproj -c Release -r linux-arm64 --self-contained=true -p:PublishTrimmed=true -o $OutputPathArm64
|
||||||
|
|
||||||
- name: Upload build artifacts
|
- name: Upload build artifacts
|
||||||
uses: actions/upload-artifact@v4
|
uses: actions/upload-artifact@v4.6.1
|
||||||
with:
|
with:
|
||||||
name: v2rayN-linux
|
name: v2rayN-linux
|
||||||
path: |
|
path: |
|
||||||
@@ -58,6 +66,22 @@ jobs:
|
|||||||
file: ${{ github.workspace }}/v2rayN*.deb
|
file: ${{ github.workspace }}/v2rayN*.deb
|
||||||
tag: ${{ github.event.inputs.release_tag }}
|
tag: ${{ github.event.inputs.release_tag }}
|
||||||
file_glob: true
|
file_glob: true
|
||||||
|
prerelease: true
|
||||||
|
|
||||||
|
- name: Package AppImage
|
||||||
|
if: github.event.inputs.release_tag != ''
|
||||||
|
run: |
|
||||||
|
chmod a+x package-appimage.sh
|
||||||
|
./package-appimage.sh
|
||||||
|
|
||||||
|
- 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
|
# release zip archive
|
||||||
- name: Package release zip archive
|
- name: Package release zip archive
|
||||||
|
|||||||
21
.github/workflows/build-osx.yml
vendored
21
.github/workflows/build-osx.yml
vendored
@@ -26,18 +26,26 @@ jobs:
|
|||||||
|
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout
|
- name: Checkout
|
||||||
uses: actions/checkout@v4
|
uses: actions/checkout@v4.2.2
|
||||||
|
with:
|
||||||
|
submodules: 'recursive'
|
||||||
|
fetch-depth: '0'
|
||||||
|
|
||||||
|
- name: Setup
|
||||||
|
uses: actions/setup-dotnet@v4.3.0
|
||||||
|
with:
|
||||||
|
dotnet-version: '8.0.x'
|
||||||
|
|
||||||
- name: Build
|
- name: Build
|
||||||
run: |
|
run: |
|
||||||
cd v2rayN
|
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-x64 --self-contained=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 ./v2rayN.Desktop/v2rayN.Desktop.csproj -c Release -r osx-arm64 --self-contained=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-x64 --self-contained=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 ./AmazTool/AmazTool.csproj -c Release -r osx-arm64 --self-contained=true -p:PublishTrimmed=true -o $OutputPathArm64
|
||||||
|
|
||||||
- name: Upload build artifacts
|
- name: Upload build artifacts
|
||||||
uses: actions/upload-artifact@v4
|
uses: actions/upload-artifact@v4.6.1
|
||||||
with:
|
with:
|
||||||
name: v2rayN-macos
|
name: v2rayN-macos
|
||||||
path: |
|
path: |
|
||||||
@@ -59,6 +67,7 @@ jobs:
|
|||||||
file: ${{ github.workspace }}/v2rayN*.dmg
|
file: ${{ github.workspace }}/v2rayN*.dmg
|
||||||
tag: ${{ github.event.inputs.release_tag }}
|
tag: ${{ github.event.inputs.release_tag }}
|
||||||
file_glob: true
|
file_glob: true
|
||||||
|
prerelease: true
|
||||||
|
|
||||||
# release zip archive
|
# release zip archive
|
||||||
- name: Package release zip archive
|
- name: Package release zip archive
|
||||||
|
|||||||
71
.github/workflows/build-windows-desktop.yml
vendored
Normal file
71
.github/workflows/build-windows-desktop.yml
vendored
Normal file
@@ -0,0 +1,71 @@
|
|||||||
|
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
|
||||||
|
with:
|
||||||
|
submodules: 'recursive'
|
||||||
|
fetch-depth: '0'
|
||||||
|
|
||||||
|
- 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:EnableWindowsTargeting=true -o $OutputPath64
|
||||||
|
dotnet publish ./v2rayN.Desktop/v2rayN.Desktop.csproj -c Release -r win-arm64 --self-contained=true -p:EnableWindowsTargeting=true -o $OutputPathArm64
|
||||||
|
dotnet publish ./AmazTool/AmazTool.csproj -c Release -r win-x64 --self-contained=true -p:EnableWindowsTargeting=true -p:PublishTrimmed=true -o $OutputPath64
|
||||||
|
dotnet publish ./AmazTool/AmazTool.csproj -c Release -r win-arm64 --self-contained=true -p:EnableWindowsTargeting=true -p:PublishTrimmed=true -o $OutputPathArm64
|
||||||
|
|
||||||
|
- name: Upload build artifacts
|
||||||
|
uses: actions/upload-artifact@v4.6.1
|
||||||
|
with:
|
||||||
|
name: v2rayN-windows-desktop
|
||||||
|
path: |
|
||||||
|
${{ github.workspace }}/v2rayN/Release/windows*
|
||||||
|
|
||||||
|
# release zip archive
|
||||||
|
- name: Package release zip archive
|
||||||
|
if: github.event.inputs.release_tag != ''
|
||||||
|
run: |
|
||||||
|
chmod 755 package-release-zip.sh
|
||||||
|
./package-release-zip.sh $OutputArch $OutputPath64
|
||||||
|
mv "v2rayN-${OutputArch}.zip" "v2rayN-${OutputArch}-desktop.zip"
|
||||||
|
./package-release-zip.sh $OutputArchArm $OutputPathArm64
|
||||||
|
mv "v2rayN-${OutputArchArm}.zip" "v2rayN-${OutputArchArm}-desktop.zip"
|
||||||
|
|
||||||
|
- name: Upload zip archive to release
|
||||||
|
uses: svenstaro/upload-release-action@v2
|
||||||
|
if: github.event.inputs.release_tag != ''
|
||||||
|
with:
|
||||||
|
file: ${{ github.workspace }}/v2rayN*.zip
|
||||||
|
tag: ${{ github.event.inputs.release_tag }}
|
||||||
|
file_glob: true
|
||||||
|
prerelease: true
|
||||||
20
.github/workflows/build-windows.yml
vendored
20
.github/workflows/build-windows.yml
vendored
@@ -27,26 +27,26 @@ jobs:
|
|||||||
|
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout
|
- name: Checkout
|
||||||
uses: actions/checkout@v4
|
uses: actions/checkout@v4.2.2
|
||||||
|
|
||||||
- name: Setup
|
- name: Setup
|
||||||
uses: actions/setup-dotnet@v4
|
uses: actions/setup-dotnet@v4.3.0
|
||||||
with:
|
with:
|
||||||
dotnet-version: '8.0.x'
|
dotnet-version: '8.0.x'
|
||||||
|
|
||||||
- name: Build
|
- name: Build
|
||||||
run: |
|
run: |
|
||||||
cd v2rayN
|
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-x64 --self-contained=false -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-arm64 --self-contained=false -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 ./v2rayN/v2rayN.csproj -c Release -r win-x64 --self-contained=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-x64 --self-contained=false -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-arm64 --self-contained=false -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 ./AmazTool/AmazTool.csproj -c Release -r win-x64 --self-contained=true -p:EnableWindowsTargeting=true -p:PublishTrimmed=true -o $OutputPath64Sc
|
||||||
|
|
||||||
|
|
||||||
- name: Upload build artifacts
|
- name: Upload build artifacts
|
||||||
uses: actions/upload-artifact@v4
|
uses: actions/upload-artifact@v4.6.1
|
||||||
with:
|
with:
|
||||||
name: v2rayN-windows
|
name: v2rayN-windows
|
||||||
path: |
|
path: |
|
||||||
@@ -58,10 +58,8 @@ jobs:
|
|||||||
run: |
|
run: |
|
||||||
chmod 755 package-release-zip.sh
|
chmod 755 package-release-zip.sh
|
||||||
./package-release-zip.sh $OutputArch $OutputPath64
|
./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 $OutputArchArm $OutputPathArm64
|
||||||
./package-release-zip.sh "windows-64-SelfContained" $OutputPath64Sc
|
./package-release-zip.sh "windows-64-SelfContained" $OutputPath64Sc
|
||||||
./package-release-zip.sh "windows-64-SelfContained-With-Core" $OutputPath64Sc
|
|
||||||
|
|
||||||
- name: Upload zip archive to release
|
- name: Upload zip archive to release
|
||||||
uses: svenstaro/upload-release-action@v2
|
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"
|
$github = Invoke-RestMethod -uri "https://api.github.com/repos/2dust/v2rayN/releases"
|
||||||
|
|
||||||
$targetRelease = $github | Where-Object -Property prerelease -match 'False' | Select -First 1
|
$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
|
$ver = $targetRelease.tag_name
|
||||||
|
|
||||||
|
|||||||
415
.gitignore
vendored
415
.gitignore
vendored
@@ -1,19 +1,400 @@
|
|||||||
################################################################################
|
## Ignore Visual Studio temporary files, build results, and
|
||||||
# 此 .gitignore 文件已由 Microsoft(R) Visual Studio 自动创建。
|
## files generated by popular Visual Studio add-ons.
|
||||||
################################################################################
|
##
|
||||||
|
## Get latest from https://github.com/github/gitignore/blob/main/VisualStudio.gitignore
|
||||||
|
|
||||||
/v2rayN/.vs/
|
# User-specific files
|
||||||
/v2rayN/v2rayN/bin/Debug/app.publish
|
*.rsuser
|
||||||
/v2rayN/v2rayN/bin/Debug
|
*.suo
|
||||||
/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
|
*.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
|
||||||
3
.gitmodules
vendored
Normal file
3
.gitmodules
vendored
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
[submodule "v2rayN/GlobalHotKeys"]
|
||||||
|
path = v2rayN/GlobalHotKeys
|
||||||
|
url = https://github.com/2dust/GlobalHotKeys
|
||||||
22
README.md
22
README.md
@@ -1,5 +1,5 @@
|
|||||||
# v2rayN
|
# 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)
|
[](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
|
## 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 11+
|
|
||||||
```
|
|
||||||
|
|
||||||
## 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
|
## Telegram Channel
|
||||||
[github_2dust](https://t.me/github_2dust)
|
[github_2dust](https://t.me/github_2dust)
|
||||||
|
|||||||
14
package-appimage.sh
Normal file
14
package-appimage.sh
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
sudo apt update -y
|
||||||
|
sudo apt install -y libfuse2
|
||||||
|
wget -O pkg2appimage https://github.com/AppImageCommunity/pkg2appimage/releases/download/continuous/pkg2appimage-1eceb30-x86_64.AppImage
|
||||||
|
chmod a+x pkg2appimage
|
||||||
|
export AppImageOutputArch=$OutputArch
|
||||||
|
export OutputPath=$OutputPath64
|
||||||
|
./pkg2appimage ./pkg2appimage.yml
|
||||||
|
mv out/*.AppImage v2rayN-${AppImageOutputArch}.AppImage
|
||||||
|
export AppImageOutputArch=$OutputArchArm
|
||||||
|
export OutputPath=$OutputPathArm64
|
||||||
|
./pkg2appimage ./pkg2appimage.yml
|
||||||
|
mv out/*.AppImage v2rayN-${AppImageOutputArch}.AppImage
|
||||||
@@ -4,6 +4,11 @@ Arch="$1"
|
|||||||
OutputPath="$2"
|
OutputPath="$2"
|
||||||
Version="$3"
|
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}"
|
PackagePath="v2rayN-Package-${Arch}"
|
||||||
mkdir -p "${PackagePath}/DEBIAN"
|
mkdir -p "${PackagePath}/DEBIAN"
|
||||||
mkdir -p "${PackagePath}/opt"
|
mkdir -p "${PackagePath}/opt"
|
||||||
|
|||||||
@@ -4,6 +4,11 @@ Arch="$1"
|
|||||||
OutputPath="$2"
|
OutputPath="$2"
|
||||||
Version="$3"
|
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}"
|
PackagePath="v2rayN-Package-${Arch}"
|
||||||
mkdir -p "$PackagePath/v2rayN.app/Contents/Resources"
|
mkdir -p "$PackagePath/v2rayN.app/Contents/Resources"
|
||||||
cp -rf "$OutputPath" "$PackagePath/v2rayN.app/Contents/MacOS"
|
cp -rf "$OutputPath" "$PackagePath/v2rayN.app/Contents/MacOS"
|
||||||
|
|||||||
37
pkg2appimage.yml
Normal file
37
pkg2appimage.yml
Normal file
@@ -0,0 +1,37 @@
|
|||||||
|
app: v2rayN
|
||||||
|
binpatch: true
|
||||||
|
|
||||||
|
ingredients:
|
||||||
|
script:
|
||||||
|
- export FileName="v2rayN-${AppImageOutputArch}.zip"
|
||||||
|
- wget -nv -O $FileName "https://github.com/2dust/v2rayN-core-bin/raw/refs/heads/master/${FileName}"
|
||||||
|
- 7z x $FileName -aoa
|
||||||
|
- cp -rf v2rayN-${AppImageOutputArch}/* $OutputPath
|
||||||
|
|
||||||
|
script:
|
||||||
|
- mkdir -p usr/bin usr/lib
|
||||||
|
- cp -rf $OutputPath usr/lib/v2rayN
|
||||||
|
- echo "When this file exists, app will not store configs under this folder" > usr/lib/v2rayN/NotStoreConfigHere.txt
|
||||||
|
- ln -sf usr/lib/v2rayN/v2rayN usr/bin/v2rayN
|
||||||
|
- chmod a+x usr/lib/v2rayN/v2rayN
|
||||||
|
- find usr -type f -exec sh -c 'file "{}" | grep -qi "executable" && chmod +x "{}"' \;
|
||||||
|
- install -Dm644 usr/lib/v2rayN/v2rayN.png v2rayN.png
|
||||||
|
- install -Dm644 usr/lib/v2rayN/v2rayN.png usr/share/pixmaps/v2rayN.png
|
||||||
|
- cat > 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
|
||||||
|
- install -Dm644 v2rayN.desktop usr/share/applications/v2rayN.desktop
|
||||||
|
- cat > AppRun <<\EOF
|
||||||
|
- #!/bin/sh
|
||||||
|
- HERE="$(dirname "$(readlink -f "${0}")")"
|
||||||
|
- cd ${HERE}/usr/lib/v2rayN
|
||||||
|
- exec ${HERE}/usr/lib/v2rayN/v2rayN $@
|
||||||
|
- EOF
|
||||||
|
- chmod a+x AppRun
|
||||||
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
|
|
||||||
@@ -2,14 +2,14 @@
|
|||||||
|
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<OutputType>Exe</OutputType>
|
<OutputType>Exe</OutputType>
|
||||||
<TargetFramework>net8.0</TargetFramework>
|
|
||||||
<ImplicitUsings>enable</ImplicitUsings>
|
|
||||||
<Nullable>enable</Nullable>
|
|
||||||
<Copyright>Copyright © 2017-2025 (GPLv3)</Copyright>
|
|
||||||
<FileVersion>1.3.1</FileVersion>
|
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
<EmbeddedResource Update="Resx\Resource.resx">
|
||||||
|
<Generator>ResXFileCodeGenerator</Generator>
|
||||||
|
<LastGenOutput>Resource.Designer.cs</LastGenOutput>
|
||||||
|
</EmbeddedResource>
|
||||||
|
|
||||||
<Compile Update="Resx\Resource.Designer.cs">
|
<Compile Update="Resx\Resource.Designer.cs">
|
||||||
<DesignTime>True</DesignTime>
|
<DesignTime>True</DesignTime>
|
||||||
<AutoGen>True</AutoGen>
|
<AutoGen>True</AutoGen>
|
||||||
@@ -17,11 +17,4 @@
|
|||||||
</Compile>
|
</Compile>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
|
||||||
<EmbeddedResource Update="Resx\Resource.resx">
|
|
||||||
<Generator>ResXFileCodeGenerator</Generator>
|
|
||||||
<LastGenOutput>Resource.Designer.cs</LastGenOutput>
|
|
||||||
</EmbeddedResource>
|
|
||||||
</ItemGroup>
|
|
||||||
|
|
||||||
</Project>
|
</Project>
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
using System.Diagnostics;
|
using System.Diagnostics;
|
||||||
using System.IO.Compression;
|
using System.IO.Compression;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
|
|
||||||
@@ -10,7 +10,7 @@ namespace AmazTool
|
|||||||
{
|
{
|
||||||
Console.WriteLine($"{Resx.Resource.StartUnzipping}\n{fileName}");
|
Console.WriteLine($"{Resx.Resource.StartUnzipping}\n{fileName}");
|
||||||
|
|
||||||
Waiting(5);
|
Utils.Waiting(5);
|
||||||
|
|
||||||
if (!File.Exists(fileName))
|
if (!File.Exists(fileName))
|
||||||
{
|
{
|
||||||
@@ -42,12 +42,12 @@ namespace AmazTool
|
|||||||
StringBuilder sb = new();
|
StringBuilder sb = new();
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
string thisAppOldFile = $"{Utils.GetExePath()}.tmp";
|
var thisAppOldFile = $"{Utils.GetExePath()}.tmp";
|
||||||
File.Delete(thisAppOldFile);
|
File.Delete(thisAppOldFile);
|
||||||
string splitKey = "/";
|
var splitKey = "/";
|
||||||
|
|
||||||
using ZipArchive archive = ZipFile.OpenRead(fileName);
|
using var archive = ZipFile.OpenRead(fileName);
|
||||||
foreach (ZipArchiveEntry entry in archive.Entries)
|
foreach (var entry in archive.Entries)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
@@ -59,16 +59,22 @@ namespace AmazTool
|
|||||||
Console.WriteLine(entry.FullName);
|
Console.WriteLine(entry.FullName);
|
||||||
|
|
||||||
var lst = entry.FullName.Split(splitKey);
|
var lst = entry.FullName.Split(splitKey);
|
||||||
if (lst.Length == 1) continue;
|
if (lst.Length == 1)
|
||||||
string fullName = string.Join(splitKey, lst[1..lst.Length]);
|
continue;
|
||||||
|
var fullName = string.Join(splitKey, lst[1..lst.Length]);
|
||||||
|
|
||||||
if (string.Equals(Utils.GetExePath(), Utils.GetPath(fullName), StringComparison.OrdinalIgnoreCase))
|
if (string.Equals(Utils.GetExePath(), Utils.GetPath(fullName), StringComparison.OrdinalIgnoreCase))
|
||||||
{
|
{
|
||||||
File.Move(Utils.GetExePath(), thisAppOldFile);
|
File.Move(Utils.GetExePath(), thisAppOldFile);
|
||||||
}
|
}
|
||||||
|
|
||||||
string entryOutputPath = Utils.GetPath(fullName);
|
var entryOutputPath = Utils.GetPath(fullName);
|
||||||
Directory.CreateDirectory(Path.GetDirectoryName(entryOutputPath)!);
|
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);
|
entry.ExtractToFile(entryOutputPath, true);
|
||||||
|
|
||||||
Console.WriteLine(entryOutputPath);
|
Console.WriteLine(entryOutputPath);
|
||||||
@@ -91,18 +97,9 @@ namespace AmazTool
|
|||||||
}
|
}
|
||||||
|
|
||||||
Console.WriteLine(Resx.Resource.Restartv2rayN);
|
Console.WriteLine(Resx.Resource.Restartv2rayN);
|
||||||
Waiting(2);
|
Utils.Waiting(2);
|
||||||
|
|
||||||
Utils.StartV2RayN();
|
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();
|
process.Start();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static void Waiting(int second)
|
||||||
|
{
|
||||||
|
for (var i = second; i > 0; i--)
|
||||||
|
{
|
||||||
|
Console.WriteLine(i);
|
||||||
|
Thread.Sleep(1000);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
33
v2rayN/Directory.Build.props
Normal file
33
v2rayN/Directory.Build.props
Normal file
@@ -0,0 +1,33 @@
|
|||||||
|
<Project>
|
||||||
|
|
||||||
|
<PropertyGroup>
|
||||||
|
<Version>7.10.0</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>
|
||||||
|
<PublishReadyToRun>false</PublishReadyToRun>
|
||||||
|
</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.4" />
|
||||||
|
<PackageVersion Include="Avalonia.Desktop" Version="11.2.4" />
|
||||||
|
<PackageVersion Include="Avalonia.Diagnostics" Version="11.2.4" />
|
||||||
|
<PackageVersion Include="Avalonia.ReactiveUI" Version="11.2.4" />
|
||||||
|
<PackageVersion Include="CliWrap" Version="3.8.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.12.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
v2rayN/GlobalHotKeys
Submodule
1
v2rayN/GlobalHotKeys
Submodule
Submodule v2rayN/GlobalHotKeys added at 35901e2eaa
@@ -1,5 +1,5 @@
|
|||||||
using Downloader;
|
|
||||||
using System.Net;
|
using System.Net;
|
||||||
|
using Downloader;
|
||||||
|
|
||||||
namespace ServiceLib.Common
|
namespace ServiceLib.Common
|
||||||
{
|
{
|
||||||
|
|||||||
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;
|
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
|
// Get information about the source directory
|
||||||
var dir = new DirectoryInfo(sourceDir);
|
var dir = new DirectoryInfo(sourceDir);
|
||||||
@@ -183,7 +183,11 @@ namespace ServiceLib.Common
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
var targetFilePath = Path.Combine(destinationDir, file.Name);
|
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
|
// If recursive and copying subdirectories, recursively call this method
|
||||||
@@ -192,7 +196,7 @@ namespace ServiceLib.Common
|
|||||||
foreach (var subDir in dirs)
|
foreach (var subDir in dirs)
|
||||||
{
|
{
|
||||||
var newDestinationDir = Path.Combine(destinationDir, subDir.Name);
|
var newDestinationDir = Path.Combine(destinationDir, subDir.Name);
|
||||||
CopyDirectory(subDir.FullName, newDestinationDir, true, ignoredName);
|
CopyDirectory(subDir.FullName, newDestinationDir, true, overwrite, ignoredName);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -38,13 +38,15 @@ namespace ServiceLib.Common
|
|||||||
|
|
||||||
public async Task<string?> GetAsync(string url)
|
public async Task<string?> GetAsync(string url)
|
||||||
{
|
{
|
||||||
if (Utils.IsNullOrEmpty(url)) return null;
|
if (Utils.IsNullOrEmpty(url))
|
||||||
|
return null;
|
||||||
return await httpClient.GetStringAsync(url);
|
return await httpClient.GetStringAsync(url);
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task<string?> GetAsync(HttpClient client, string url, CancellationToken token = default)
|
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);
|
return await client.GetStringAsync(url, token);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -75,11 +77,13 @@ namespace ServiceLib.Common
|
|||||||
{
|
{
|
||||||
ArgumentNullException.ThrowIfNull(url);
|
ArgumentNullException.ThrowIfNull(url);
|
||||||
ArgumentNullException.ThrowIfNull(fileName);
|
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);
|
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 total = response.Content.Headers.ContentLength ?? -1L;
|
||||||
var canReportProgress = total != -1 && progress != null;
|
var canReportProgress = total != -1 && progress != null;
|
||||||
@@ -97,7 +101,8 @@ namespace ServiceLib.Common
|
|||||||
var read = await stream.ReadAsync(buffer, token);
|
var read = await stream.ReadAsync(buffer, token);
|
||||||
totalRead += read;
|
totalRead += read;
|
||||||
|
|
||||||
if (read == 0) break;
|
if (read == 0)
|
||||||
|
break;
|
||||||
await file.WriteAsync(buffer.AsMemory(0, read), token);
|
await file.WriteAsync(buffer.AsMemory(0, read), token);
|
||||||
|
|
||||||
if (canReportProgress)
|
if (canReportProgress)
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
using System.Diagnostics;
|
using System.Diagnostics;
|
||||||
using System.Runtime.InteropServices;
|
using System.Runtime.InteropServices;
|
||||||
|
|
||||||
namespace ServiceLib.Common
|
namespace ServiceLib.Common
|
||||||
@@ -75,7 +75,8 @@ namespace ServiceLib.Common
|
|||||||
|
|
||||||
private void Dispose(bool disposing)
|
private void Dispose(bool disposing)
|
||||||
{
|
{
|
||||||
if (disposed) return;
|
if (disposed)
|
||||||
|
return;
|
||||||
disposed = true;
|
disposed = true;
|
||||||
|
|
||||||
if (disposing)
|
if (disposing)
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
using NLog;
|
using NLog;
|
||||||
using NLog.Config;
|
using NLog.Config;
|
||||||
using NLog.Targets;
|
using NLog.Targets;
|
||||||
|
|
||||||
@@ -27,14 +27,16 @@ namespace ServiceLib.Common
|
|||||||
|
|
||||||
public static void SaveLog(string strContent)
|
public static void SaveLog(string strContent)
|
||||||
{
|
{
|
||||||
if (!LogManager.IsLoggingEnabled()) return;
|
if (!LogManager.IsLoggingEnabled())
|
||||||
|
return;
|
||||||
|
|
||||||
LogManager.GetLogger("Log1").Info(strContent);
|
LogManager.GetLogger("Log1").Info(strContent);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void SaveLog(string strTitle, Exception ex)
|
public static void SaveLog(string strTitle, Exception ex)
|
||||||
{
|
{
|
||||||
if (!LogManager.IsLoggingEnabled()) return;
|
if (!LogManager.IsLoggingEnabled())
|
||||||
|
return;
|
||||||
|
|
||||||
var logger = LogManager.GetLogger("Log2");
|
var logger = LogManager.GetLogger("Log2");
|
||||||
logger.Debug($"{strTitle},{ex.Message}");
|
logger.Debug($"{strTitle},{ex.Message}");
|
||||||
|
|||||||
@@ -19,21 +19,27 @@ public static class ProcUtils
|
|||||||
}
|
}
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
if (fileName.Contains(' ')) fileName = fileName.AppendQuotes();
|
if (fileName.Contains(' '))
|
||||||
if (arguments.Contains(' ')) arguments = arguments.AppendQuotes();
|
{
|
||||||
|
fileName = fileName.AppendQuotes();
|
||||||
|
}
|
||||||
|
if (arguments.Contains(' '))
|
||||||
|
{
|
||||||
|
arguments = arguments.AppendQuotes();
|
||||||
|
}
|
||||||
|
|
||||||
Process process = new()
|
Process proc = new()
|
||||||
{
|
{
|
||||||
StartInfo = new ProcessStartInfo
|
StartInfo = new ProcessStartInfo
|
||||||
{
|
{
|
||||||
UseShellExecute = true,
|
UseShellExecute = true,
|
||||||
FileName = fileName,
|
FileName = fileName,
|
||||||
Arguments = arguments,
|
Arguments = arguments,
|
||||||
WorkingDirectory = dir
|
WorkingDirectory = dir ?? string.Empty
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
process.Start();
|
proc.Start();
|
||||||
return process.Id;
|
return dir is null ? null : proc.Id;
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
@@ -83,10 +89,44 @@ public static class ProcUtils
|
|||||||
|
|
||||||
GetProcessKeyInfo(proc, review, out var procId, out var fileName, out var processName);
|
GetProcessKeyInfo(proc, review, out var procId, out var fileName, out var processName);
|
||||||
|
|
||||||
try { proc?.Kill(true); } catch (Exception ex) { Logging.SaveLog(_tag, ex); }
|
try
|
||||||
try { proc?.Kill(); } catch (Exception ex) { Logging.SaveLog(_tag, ex); }
|
{
|
||||||
try { proc?.Close(); } catch (Exception ex) { Logging.SaveLog(_tag, ex); }
|
if (Utils.IsNonWindows())
|
||||||
try { proc?.Dispose(); } catch (Exception ex) { Logging.SaveLog(_tag, ex); }
|
{
|
||||||
|
proc?.Kill(true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
Logging.SaveLog(_tag, ex);
|
||||||
|
}
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
proc?.Kill();
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
Logging.SaveLog(_tag, ex);
|
||||||
|
}
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
proc?.Close();
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
Logging.SaveLog(_tag, ex);
|
||||||
|
}
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
proc?.Dispose();
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
Logging.SaveLog(_tag, ex);
|
||||||
|
}
|
||||||
|
|
||||||
await Task.Delay(300);
|
await Task.Delay(300);
|
||||||
await ProcessKillByKeyInfo(review, procId, fileName, processName);
|
await ProcessKillByKeyInfo(review, procId, fileName, processName);
|
||||||
@@ -97,7 +137,8 @@ public static class ProcUtils
|
|||||||
procId = null;
|
procId = null;
|
||||||
fileName = null;
|
fileName = null;
|
||||||
processName = null;
|
processName = null;
|
||||||
if (!review) return;
|
if (!review)
|
||||||
|
return;
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
procId = proc?.Id;
|
procId = proc?.Id;
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
using SQLite;
|
|
||||||
using System.Collections;
|
using System.Collections;
|
||||||
|
using SQLite;
|
||||||
|
|
||||||
namespace ServiceLib.Common
|
namespace ServiceLib.Common
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
using System.Diagnostics.CodeAnalysis;
|
using System.Diagnostics.CodeAnalysis;
|
||||||
|
|
||||||
namespace ServiceLib.Common
|
namespace ServiceLib.Common
|
||||||
{
|
{
|
||||||
@@ -21,7 +21,8 @@ namespace ServiceLib.Common
|
|||||||
|
|
||||||
public static bool BeginWithAny(this string s, IEnumerable<char> chars)
|
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());
|
return chars.Contains(s.First());
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -34,7 +35,8 @@ namespace ServiceLib.Common
|
|||||||
{
|
{
|
||||||
while (reader.ReadLine() is { } line)
|
while (reader.ReadLine() is { } line)
|
||||||
{
|
{
|
||||||
if (line.IsWhiteSpace()) continue;
|
if (line.IsWhiteSpace())
|
||||||
|
continue;
|
||||||
yield return line;
|
yield return line;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,3 @@
|
|||||||
using CliWrap;
|
|
||||||
using CliWrap.Buffered;
|
|
||||||
using System.Collections.Specialized;
|
using System.Collections.Specialized;
|
||||||
using System.Diagnostics;
|
using System.Diagnostics;
|
||||||
using System.Net;
|
using System.Net;
|
||||||
@@ -10,6 +8,8 @@ using System.Runtime.InteropServices;
|
|||||||
using System.Security.Cryptography;
|
using System.Security.Cryptography;
|
||||||
using System.Security.Principal;
|
using System.Security.Principal;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
|
using CliWrap;
|
||||||
|
using CliWrap.Buffered;
|
||||||
|
|
||||||
namespace ServiceLib.Common
|
namespace ServiceLib.Common
|
||||||
{
|
{
|
||||||
@@ -17,56 +17,6 @@ namespace ServiceLib.Common
|
|||||||
{
|
{
|
||||||
private static readonly string _tag = "Utils";
|
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 转换函数
|
#region 转换函数
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -176,7 +126,8 @@ namespace ServiceLib.Common
|
|||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
if (plainText.IsNullOrEmpty()) return "";
|
if (plainText.IsNullOrEmpty())
|
||||||
|
return "";
|
||||||
plainText = plainText.Trim()
|
plainText = plainText.Trim()
|
||||||
.Replace(Environment.NewLine, "")
|
.Replace(Environment.NewLine, "")
|
||||||
.Replace("\n", "")
|
.Replace("\n", "")
|
||||||
@@ -372,7 +323,8 @@ namespace ServiceLib.Common
|
|||||||
|
|
||||||
public static bool IsBase64String(string? plainText)
|
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]);
|
var buffer = new Span<byte>(new byte[plainText.Length]);
|
||||||
return Convert.TryFromBase64String(plainText, buffer, out var _);
|
return Convert.TryFromBase64String(plainText, buffer, out var _);
|
||||||
}
|
}
|
||||||
@@ -462,9 +414,12 @@ namespace ServiceLib.Common
|
|||||||
if (IPAddress.TryParse(ip, out var address))
|
if (IPAddress.TryParse(ip, out var address))
|
||||||
{
|
{
|
||||||
var ipBytes = address.GetAddressBytes();
|
var ipBytes = address.GetAddressBytes();
|
||||||
if (ipBytes[0] == 10) return true;
|
if (ipBytes[0] == 10)
|
||||||
if (ipBytes[0] == 172 && ipBytes[1] >= 16 && ipBytes[1] <= 31) return true;
|
return true;
|
||||||
if (ipBytes[0] == 192 && ipBytes[1] == 168) 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;
|
return false;
|
||||||
@@ -478,10 +433,22 @@ namespace ServiceLib.Common
|
|||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
var ipProperties = IPGlobalProperties.GetIPGlobalProperties();
|
List<IPEndPoint> lstIpEndPoints = new();
|
||||||
var ipEndPoints = ipProperties.GetActiveTcpListeners();
|
List<TcpConnectionInformation> lstTcpConns = new();
|
||||||
//var lstIpEndPoints = new List<IPEndPoint>(IPGlobalProperties.GetIPGlobalProperties().GetActiveTcpListeners());
|
|
||||||
return ipEndPoints.Any(endPoint => endPoint.Port == port);
|
lstIpEndPoints.AddRange(IPGlobalProperties.GetIPGlobalProperties().GetActiveTcpListeners());
|
||||||
|
lstIpEndPoints.AddRange(IPGlobalProperties.GetIPGlobalProperties().GetActiveUdpListeners());
|
||||||
|
lstTcpConns.AddRange(IPGlobalProperties.GetIPGlobalProperties().GetActiveTcpConnections());
|
||||||
|
|
||||||
|
if (lstIpEndPoints?.FindIndex(it => it.Port == port) >= 0)
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (lstTcpConns?.FindIndex(it => it.LocalEndPoint.Port == port) >= 0)
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
@@ -519,7 +486,7 @@ namespace ServiceLib.Common
|
|||||||
|
|
||||||
public static bool UpgradeAppExists(out string upgradeFileName)
|
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);
|
return File.Exists(upgradeFileName);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -604,9 +571,11 @@ namespace ServiceLib.Common
|
|||||||
|
|
||||||
foreach (var host in hostsList)
|
foreach (var host in hostsList)
|
||||||
{
|
{
|
||||||
if (host.StartsWith("#")) continue;
|
if (host.StartsWith("#"))
|
||||||
|
continue;
|
||||||
var hostItem = host.Split(new[] { ' ', '\t' }, StringSplitOptions.RemoveEmptyEntries);
|
var hostItem = host.Split(new[] { ' ', '\t' }, StringSplitOptions.RemoveEmptyEntries);
|
||||||
if (hostItem.Length != 2) continue;
|
if (hostItem.Length != 2)
|
||||||
|
continue;
|
||||||
systemHosts.Add(hostItem.Last(), hostItem.First());
|
systemHosts.Add(hostItem.Last(), hostItem.First());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -666,12 +635,12 @@ namespace ServiceLib.Common
|
|||||||
try
|
try
|
||||||
{
|
{
|
||||||
//When this file exists, it is equivalent to having no permission to read and write
|
//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;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
var tempPath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "guiTemps");
|
var tempPath = Path.Combine(GetBaseDirectory(), "guiTemps");
|
||||||
if (!Directory.Exists(tempPath))
|
if (!Directory.Exists(tempPath))
|
||||||
{
|
{
|
||||||
Directory.CreateDirectory(tempPath);
|
Directory.CreateDirectory(tempPath);
|
||||||
@@ -699,6 +668,11 @@ namespace ServiceLib.Common
|
|||||||
return Path.Combine(startupPath, fileName);
|
return Path.Combine(startupPath, fileName);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static string GetBaseDirectory(string fileName = "")
|
||||||
|
{
|
||||||
|
return Path.Combine(AppDomain.CurrentDomain.BaseDirectory, fileName);
|
||||||
|
}
|
||||||
|
|
||||||
public static string GetExePath()
|
public static string GetExePath()
|
||||||
{
|
{
|
||||||
return Environment.ProcessPath ?? Process.GetCurrentProcess().MainModule?.FileName ?? string.Empty;
|
return Environment.ProcessPath ?? Process.GetCurrentProcess().MainModule?.FileName ?? string.Empty;
|
||||||
@@ -706,12 +680,12 @@ namespace ServiceLib.Common
|
|||||||
|
|
||||||
public static string StartupPath()
|
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 Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData), "v2rayN");
|
||||||
}
|
}
|
||||||
|
|
||||||
return AppDomain.CurrentDomain.BaseDirectory;
|
return GetBaseDirectory();
|
||||||
}
|
}
|
||||||
|
|
||||||
public static string GetTempPath(string filename = "")
|
public static string GetTempPath(string filename = "")
|
||||||
@@ -824,6 +798,24 @@ namespace ServiceLib.Common
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static string GetBinConfigPath(string filename = "")
|
||||||
|
{
|
||||||
|
var tempPath = Path.Combine(StartupPath(), "binConfigs");
|
||||||
|
if (!Directory.Exists(tempPath))
|
||||||
|
{
|
||||||
|
Directory.CreateDirectory(tempPath);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Utils.IsNullOrEmpty(filename))
|
||||||
|
{
|
||||||
|
return tempPath;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return Path.Combine(tempPath, filename);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#endregion TempPath
|
#endregion TempPath
|
||||||
|
|
||||||
#region Platform
|
#region Platform
|
||||||
@@ -865,23 +857,25 @@ namespace ServiceLib.Common
|
|||||||
private static async Task<string?> GetLinuxUserId()
|
private static async Task<string?> GetLinuxUserId()
|
||||||
{
|
{
|
||||||
var arg = new List<string>() { "-c", "id -u" };
|
var arg = new List<string>() { "-c", "id -u" };
|
||||||
return await GetCliWrapOutput("/bin/bash", arg);
|
return await GetCliWrapOutput(Global.LinuxBash, arg);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static async Task<string?> SetLinuxChmod(string? fileName)
|
public static async Task<string?> SetLinuxChmod(string? fileName)
|
||||||
{
|
{
|
||||||
if (fileName.IsNullOrEmpty()) return null;
|
if (fileName.IsNullOrEmpty())
|
||||||
if (fileName.Contains(' ')) fileName = fileName.AppendQuotes();
|
return null;
|
||||||
|
if (fileName.Contains(' '))
|
||||||
|
fileName = fileName.AppendQuotes();
|
||||||
//File.SetUnixFileMode(fileName, UnixFileMode.UserRead | UnixFileMode.UserWrite | UnixFileMode.UserExecute);
|
//File.SetUnixFileMode(fileName, UnixFileMode.UserRead | UnixFileMode.UserWrite | UnixFileMode.UserExecute);
|
||||||
var arg = new List<string>() { "-c", $"chmod +x {fileName}" };
|
var arg = new List<string>() { "-c", $"chmod +x {fileName}" };
|
||||||
return await GetCliWrapOutput("/bin/bash", arg);
|
return await GetCliWrapOutput(Global.LinuxBash, arg);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static async Task<string?> GetLinuxFontFamily(string lang)
|
public static async Task<string?> GetLinuxFontFamily(string lang)
|
||||||
{
|
{
|
||||||
// var arg = new List<string>() { "-c", $"fc-list :lang={lang} family" };
|
// var arg = new List<string>() { "-c", $"fc-list :lang={lang} family" };
|
||||||
var arg = new List<string>() { "-c", $"fc-list : family" };
|
var arg = new List<string>() { "-c", $"fc-list : family" };
|
||||||
return await GetCliWrapOutput("/bin/bash", arg);
|
return await GetCliWrapOutput(Global.LinuxBash, arg);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static string? GetHomePath()
|
public static string? GetHomePath()
|
||||||
@@ -891,12 +885,6 @@ namespace ServiceLib.Common
|
|||||||
: Environment.GetEnvironmentVariable("HOME");
|
: Environment.GetEnvironmentVariable("HOME");
|
||||||
}
|
}
|
||||||
|
|
||||||
public static async Task<string?> GetListNetworkServices()
|
|
||||||
{
|
|
||||||
var arg = new List<string>() { "-c", $"networksetup -listallnetworkservices" };
|
|
||||||
return await GetCliWrapOutput("/bin/bash", arg);
|
|
||||||
}
|
|
||||||
|
|
||||||
#endregion Platform
|
#endregion Platform
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,4 +1,6 @@
|
|||||||
using Microsoft.Win32;
|
using System.Security.Cryptography;
|
||||||
|
using System.Text;
|
||||||
|
using Microsoft.Win32;
|
||||||
|
|
||||||
namespace ServiceLib.Common
|
namespace ServiceLib.Common
|
||||||
{
|
{
|
||||||
@@ -50,5 +52,23 @@ namespace ServiceLib.Common
|
|||||||
regKey?.Close();
|
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
|
public enum ECoreType
|
||||||
{
|
{
|
||||||
@@ -12,6 +12,8 @@
|
|||||||
sing_box = 24,
|
sing_box = 24,
|
||||||
juicity = 25,
|
juicity = 25,
|
||||||
hysteria2 = 26,
|
hysteria2 = 26,
|
||||||
|
brook = 27,
|
||||||
|
overtls = 28,
|
||||||
v2rayN = 99
|
v2rayN = 99
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
namespace ServiceLib.Enums
|
namespace ServiceLib.Enums
|
||||||
{
|
{
|
||||||
public enum EMsgCommand
|
public enum EMsgCommand
|
||||||
{
|
{
|
||||||
@@ -6,7 +6,6 @@
|
|||||||
SendMsgView,
|
SendMsgView,
|
||||||
SendSnackMsg,
|
SendSnackMsg,
|
||||||
RefreshProfiles,
|
RefreshProfiles,
|
||||||
StopSpeedtest,
|
|
||||||
AppExit
|
AppExit
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
namespace ServiceLib
|
namespace ServiceLib
|
||||||
{
|
{
|
||||||
public class Global
|
public class Global
|
||||||
{
|
{
|
||||||
@@ -7,18 +7,8 @@
|
|||||||
public const string AppName = "v2rayN";
|
public const string AppName = "v2rayN";
|
||||||
public const string GithubUrl = "https://github.com";
|
public const string GithubUrl = "https://github.com";
|
||||||
public const string GithubApiUrl = "https://api.github.com/repos";
|
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 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 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 SingboxRulesetUrl = @"https://raw.githubusercontent.com/2dust/sing-box-rules/rule-set-{0}/{1}.srs";
|
||||||
public const string IPAPIUrl = "https://api.ip.sb/geoip";
|
public const string IPAPIUrl = "https://api.ip.sb/geoip";
|
||||||
|
|
||||||
@@ -26,7 +16,7 @@
|
|||||||
public const string ConfigFileName = "guiNConfig.json";
|
public const string ConfigFileName = "guiNConfig.json";
|
||||||
public const string CoreConfigFileName = "config.json";
|
public const string CoreConfigFileName = "config.json";
|
||||||
public const string CorePreConfigFileName = "configPre.json";
|
public const string CorePreConfigFileName = "configPre.json";
|
||||||
public const string CoreSpeedtestConfigFileName = "configSpeedtest.json";
|
public const string CoreSpeedtestConfigFileName = "configTest{0}.json";
|
||||||
public const string CoreMultipleLoadConfigFileName = "configMultipleLoad.json";
|
public const string CoreMultipleLoadConfigFileName = "configMultipleLoad.json";
|
||||||
public const string ClashMixinConfigFileName = "Mixin.yaml";
|
public const string ClashMixinConfigFileName = "Mixin.yaml";
|
||||||
|
|
||||||
@@ -48,6 +38,8 @@
|
|||||||
public const string ClashTunYaml = NamespaceSample + "clash_tun_yaml";
|
public const string ClashTunYaml = NamespaceSample + "clash_tun_yaml";
|
||||||
public const string LinuxAutostartConfig = NamespaceSample + "linux_autostart_config";
|
public const string LinuxAutostartConfig = NamespaceSample + "linux_autostart_config";
|
||||||
public const string PacFileName = NamespaceSample + "pac";
|
public const string PacFileName = NamespaceSample + "pac";
|
||||||
|
public const string ProxySetOSXShellFileName = NamespaceSample + "proxy_set_osx_sh";
|
||||||
|
public const string ProxySetLinuxShellFileName = NamespaceSample + "proxy_set_linux_sh";
|
||||||
|
|
||||||
public const string DefaultSecurity = "auto";
|
public const string DefaultSecurity = "auto";
|
||||||
public const string DefaultNetwork = "tcp";
|
public const string DefaultNetwork = "tcp";
|
||||||
@@ -68,83 +60,93 @@
|
|||||||
public const string UserEMail = "t@t.tt";
|
public const string UserEMail = "t@t.tt";
|
||||||
public const string AutoRunRegPath = @"Software\Microsoft\Windows\CurrentVersion\Run";
|
public const string AutoRunRegPath = @"Software\Microsoft\Windows\CurrentVersion\Run";
|
||||||
public const string AutoRunName = "v2rayNAutoRun";
|
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 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 RoutingRuleComma = "<COMMA>";
|
||||||
public const string GrpcGunMode = "gun";
|
public const string GrpcGunMode = "gun";
|
||||||
public const string GrpcMultiMode = "multi";
|
public const string GrpcMultiMode = "multi";
|
||||||
public const int MaxPort = 65536;
|
public const int MaxPort = 65536;
|
||||||
public const string DelayUnit = "";
|
|
||||||
public const string SpeedUnit = "";
|
|
||||||
public const int MinFontSize = 8;
|
public const int MinFontSize = 8;
|
||||||
public const string RebootAs = "rebootas";
|
public const string RebootAs = "rebootas";
|
||||||
public const string AvaAssets = "avares://v2rayN/Assets/";
|
public const string AvaAssets = "avares://v2rayN/Assets/";
|
||||||
|
public const string LocalAppData = "V2RAYN_LOCAL_APPLICATION_DATA_V2";
|
||||||
|
public const string V2RayLocalAsset = "V2RAY_LOCATION_ASSET";
|
||||||
|
public const string XrayLocalAsset = "XRAY_LOCATION_ASSET";
|
||||||
|
public const int SpeedTestPageSize = 1000;
|
||||||
|
public const string LinuxBash = "/bin/bash";
|
||||||
|
|
||||||
public static readonly List<string> IEProxyProtocols = new() {
|
public static readonly List<string> IEProxyProtocols =
|
||||||
|
[
|
||||||
"{ip}:{http_port}",
|
"{ip}:{http_port}",
|
||||||
"socks={ip}:{socks_port}",
|
"socks={ip}:{socks_port}",
|
||||||
"http={ip}:{http_port};https={ip}:{http_port};ftp={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}",
|
"http=http://{ip}:{http_port};https=http://{ip}:{http_port}",
|
||||||
""
|
""
|
||||||
};
|
];
|
||||||
|
|
||||||
public static readonly List<string> SubConvertUrls = new List<string> {
|
public static readonly List<string> SubConvertUrls =
|
||||||
|
[
|
||||||
@"https://sub.xeton.dev/sub?url={0}",
|
@"https://sub.xeton.dev/sub?url={0}",
|
||||||
@"https://api.dler.io/sub?url={0}",
|
@"https://api.dler.io/sub?url={0}",
|
||||||
@"http://127.0.0.1:25500/sub?url={0}",
|
@"http://127.0.0.1:25500/sub?url={0}",
|
||||||
""
|
""
|
||||||
};
|
];
|
||||||
|
|
||||||
public static readonly List<string> SubConvertConfig = new List<string> {
|
public static readonly List<string> SubConvertConfig =
|
||||||
@"https://raw.githubusercontent.com/ACL4SSR/ACL4SSR/master/Clash/config/ACL4SSR_Online.ini"
|
[@"https://raw.githubusercontent.com/ACL4SSR/ACL4SSR/master/Clash/config/ACL4SSR_Online.ini"];
|
||||||
};
|
|
||||||
|
|
||||||
public static readonly List<string> SubConvertTargets = new List<string> {
|
public static readonly List<string> SubConvertTargets =
|
||||||
|
[
|
||||||
"",
|
"",
|
||||||
"mixed",
|
"mixed",
|
||||||
"v2ray",
|
"v2ray",
|
||||||
"clash",
|
"clash",
|
||||||
"ss",
|
"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",
|
||||||
};
|
@"https://speed.cloudflare.com/__down?bytes=10000000",
|
||||||
|
@"https://speed.cloudflare.com/__down?bytes=50000000",
|
||||||
|
@"https://speed.cloudflare.com/__down?bytes=100000000",
|
||||||
|
];
|
||||||
|
|
||||||
public static readonly List<string> SpeedPingTestUrls = new() {
|
public static readonly List<string> SpeedPingTestUrls =
|
||||||
|
[
|
||||||
@"https://www.google.com/generate_204",
|
@"https://www.google.com/generate_204",
|
||||||
@"https://www.gstatic.com/generate_204",
|
@"https://www.gstatic.com/generate_204",
|
||||||
@"https://www.apple.com/library/test/success.html",
|
@"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://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/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/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/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()
|
public static readonly Dictionary<string, string> UserAgentTexts = new()
|
||||||
{
|
{
|
||||||
@@ -159,65 +161,361 @@
|
|||||||
|
|
||||||
public static readonly Dictionary<EConfigType, string> ProtocolShares = new()
|
public static readonly Dictionary<EConfigType, string> ProtocolShares = new()
|
||||||
{
|
{
|
||||||
{EConfigType.VMess,"vmess://"},
|
{ EConfigType.VMess, "vmess://" },
|
||||||
{EConfigType.Shadowsocks,"ss://"},
|
{ EConfigType.Shadowsocks, "ss://" },
|
||||||
{EConfigType.SOCKS,"socks://"},
|
{ EConfigType.SOCKS, "socks://" },
|
||||||
{EConfigType.VLESS,"vless://"},
|
{ EConfigType.VLESS, "vless://" },
|
||||||
{EConfigType.Trojan,"trojan://"},
|
{ EConfigType.Trojan, "trojan://" },
|
||||||
{EConfigType.Hysteria2,"hysteria2://"},
|
{ EConfigType.Hysteria2, "hysteria2://" },
|
||||||
{EConfigType.TUIC,"tuic://"},
|
{ EConfigType.TUIC, "tuic://" },
|
||||||
{EConfigType.WireGuard,"wireguard://"}
|
{ EConfigType.WireGuard, "wireguard://" }
|
||||||
};
|
};
|
||||||
|
|
||||||
public static readonly Dictionary<EConfigType, string> ProtocolTypes = new()
|
public static readonly Dictionary<EConfigType, string> ProtocolTypes = new()
|
||||||
{
|
{
|
||||||
{EConfigType.VMess,"vmess"},
|
{ EConfigType.VMess, "vmess" },
|
||||||
{EConfigType.Shadowsocks,"shadowsocks"},
|
{ EConfigType.Shadowsocks, "shadowsocks" },
|
||||||
{EConfigType.SOCKS,"socks"},
|
{ EConfigType.SOCKS, "socks" },
|
||||||
{EConfigType.HTTP,"http"},
|
{ EConfigType.HTTP, "http" },
|
||||||
{EConfigType.VLESS,"vless"},
|
{ EConfigType.VLESS, "vless" },
|
||||||
{EConfigType.Trojan,"trojan"},
|
{ EConfigType.Trojan, "trojan" },
|
||||||
{EConfigType.Hysteria2,"hysteria2"},
|
{ EConfigType.Hysteria2, "hysteria2" },
|
||||||
{EConfigType.TUIC,"tuic"},
|
{ EConfigType.TUIC, "tuic" },
|
||||||
{EConfigType.WireGuard,"wireguard"}
|
{ EConfigType.WireGuard, "wireguard" }
|
||||||
};
|
};
|
||||||
|
|
||||||
public static readonly List<string> VmessSecurities = new() { "aes-128-gcm", "chacha20-poly1305", "auto", "none", "zero" };
|
public static readonly List<string> VmessSecurities =
|
||||||
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" };
|
"aes-128-gcm",
|
||||||
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" };
|
"chacha20-poly1305",
|
||||||
public static readonly List<string> Flows = new() { "", "xtls-rprx-vision", "xtls-rprx-vision-udp443" };
|
"auto",
|
||||||
public static readonly List<string> Networks = new() { "tcp", "kcp", "ws", "httpupgrade", "xhttp", "h2", "quic", "grpc" };
|
"none",
|
||||||
public static readonly List<string> KcpHeaderTypes = new() { "srtp", "utp", "wechat-video", "dtls", "wireguard" };
|
"zero"
|
||||||
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> AllowInsecure = new() { "true", "false", "" };
|
public static readonly List<string> SsSecurities =
|
||||||
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", "" };
|
"aes-256-gcm",
|
||||||
public static readonly List<string> DomainDNSAddress = ["223.5.5.5", "223.6.6.6", "localhost"];
|
"aes-128-gcm",
|
||||||
public static readonly List<string> SingboxDomainDNSAddress = ["223.5.5.5", "223.6.6.6", "dhcp://auto"];
|
"chacha20-poly1305",
|
||||||
public static readonly List<string> Languages = new() { "zh-Hans", "zh-Hant", "en", "fa-Ir", "ru", "hu" };
|
"chacha20-ietf-poly1305",
|
||||||
public static readonly List<string> Alpns = new() { "h3", "h2", "http/1.1", "h3,h2", "h2,http/1.1", "h3,h2,http/1.1", "" };
|
"none",
|
||||||
public static readonly List<string> LogLevels = new() { "debug", "info", "warning", "error", "none" };
|
"plain"
|
||||||
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", "mixed" };
|
|
||||||
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> allowSelectType = new() { "selector", "urltest", "loadbalance", "fallback" };
|
public static readonly List<string> SsSecuritiesInXray =
|
||||||
public static readonly List<string> notAllowTestType = new() { "selector", "urltest", "direct", "reject", "compatible", "pass", "loadbalance", "fallback" };
|
[
|
||||||
public static readonly List<string> proxyVehicleType = new() { "file", "http" };
|
"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<int> 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" },
|
||||||
|
};
|
||||||
|
|
||||||
|
public static readonly List<string> OtherGeoUrls =
|
||||||
|
[
|
||||||
|
@"https://raw.githubusercontent.com/Loyalsoldier/geoip/release/geoip-only-cn-private.dat",
|
||||||
|
@"https://raw.githubusercontent.com/Loyalsoldier/geoip/release/Country.mmdb",
|
||||||
|
@"https://github.com/MetaCubeX/meta-rules-dat/releases/download/latest/geoip.metadb"
|
||||||
|
];
|
||||||
|
|
||||||
#endregion const
|
#endregion const
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
namespace ServiceLib.Handler
|
namespace ServiceLib.Handler
|
||||||
{
|
{
|
||||||
public sealed class AppHandler
|
public sealed class AppHandler
|
||||||
{
|
{
|
||||||
@@ -46,9 +46,9 @@
|
|||||||
|
|
||||||
public bool InitApp()
|
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();
|
Logging.Setup();
|
||||||
@@ -98,6 +98,7 @@
|
|||||||
{
|
{
|
||||||
FileManager.DeleteExpiredFiles(Utils.GetLogPath(), DateTime.Now.AddMonths(-1));
|
FileManager.DeleteExpiredFiles(Utils.GetLogPath(), DateTime.Now.AddMonths(-1));
|
||||||
FileManager.DeleteExpiredFiles(Utils.GetTempPath(), DateTime.Now.AddMonths(-1));
|
FileManager.DeleteExpiredFiles(Utils.GetTempPath(), DateTime.Now.AddMonths(-1));
|
||||||
|
FileManager.DeleteExpiredFiles(Utils.GetBinConfigPath(), DateTime.Now.AddHours(-1));
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
using System.Security.Principal;
|
using System.Security.Principal;
|
||||||
using System.Text.RegularExpressions;
|
using System.Text.RegularExpressions;
|
||||||
|
|
||||||
namespace ServiceLib.Handler
|
namespace ServiceLib.Handler
|
||||||
@@ -29,7 +29,12 @@ namespace ServiceLib.Handler
|
|||||||
}
|
}
|
||||||
else if (Utils.IsOSX())
|
else if (Utils.IsOSX())
|
||||||
{
|
{
|
||||||
//TODO
|
await ClearTaskOSX();
|
||||||
|
|
||||||
|
if (config.GuiItem.AutoRun)
|
||||||
|
{
|
||||||
|
await SetTaskOSX();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
@@ -137,7 +142,7 @@ namespace ServiceLib.Handler
|
|||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
var linuxConfig = Utils.GetEmbedText(Global.LinuxAutostartConfig);
|
var linuxConfig = EmbedUtils.GetEmbedText(Global.LinuxAutostartConfig);
|
||||||
if (linuxConfig.IsNotEmpty())
|
if (linuxConfig.IsNotEmpty())
|
||||||
{
|
{
|
||||||
linuxConfig = linuxConfig.Replace("$ExecPath$", Utils.GetExePath());
|
linuxConfig = linuxConfig.Replace("$ExecPath$", Utils.GetExePath());
|
||||||
@@ -161,5 +166,77 @@ namespace ServiceLib.Handler
|
|||||||
}
|
}
|
||||||
|
|
||||||
#endregion Linux
|
#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(Global.LinuxBash, 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(Global.LinuxBash, 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
|
namespace ServiceLib.Handler
|
||||||
{
|
{
|
||||||
@@ -41,7 +41,7 @@ namespace ServiceLib.Handler
|
|||||||
{
|
{
|
||||||
if (blAll)
|
if (blAll)
|
||||||
{
|
{
|
||||||
for (int i = 0; i < 5; i++)
|
for (var i = 0; i < 5; i++)
|
||||||
{
|
{
|
||||||
if (_proxies != null)
|
if (_proxies != null)
|
||||||
{
|
{
|
||||||
@@ -75,7 +75,7 @@ namespace ServiceLib.Handler
|
|||||||
var urlBase = $"{GetApiUrl()}/proxies";
|
var urlBase = $"{GetApiUrl()}/proxies";
|
||||||
urlBase += @"/{0}/delay?timeout=10000&url=" + AppHandler.Instance.Config.SpeedTestItem.SpeedPingTestUrl;
|
urlBase += @"/{0}/delay?timeout=10000&url=" + AppHandler.Instance.Config.SpeedTestItem.SpeedPingTestUrl;
|
||||||
|
|
||||||
List<Task> tasks = new List<Task>();
|
var tasks = new List<Task>();
|
||||||
foreach (var it in lstProxy)
|
foreach (var it in lstProxy)
|
||||||
{
|
{
|
||||||
if (Global.notAllowTestType.Contains(it.Type.ToLower()))
|
if (Global.notAllowTestType.Contains(it.Type.ToLower()))
|
||||||
@@ -120,7 +120,7 @@ namespace ServiceLib.Handler
|
|||||||
try
|
try
|
||||||
{
|
{
|
||||||
var url = $"{GetApiUrl()}/proxies/{name}";
|
var url = $"{GetApiUrl()}/proxies/{name}";
|
||||||
Dictionary<string, string> headers = new Dictionary<string, string>();
|
var headers = new Dictionary<string, string>();
|
||||||
headers.Add("name", nameNode);
|
headers.Add("name", nameNode);
|
||||||
await HttpClientHelper.Instance.PutAsync(url, headers);
|
await HttpClientHelper.Instance.PutAsync(url, headers);
|
||||||
}
|
}
|
||||||
@@ -148,7 +148,7 @@ namespace ServiceLib.Handler
|
|||||||
try
|
try
|
||||||
{
|
{
|
||||||
var url = $"{GetApiUrl()}/configs?force=true";
|
var url = $"{GetApiUrl()}/configs?force=true";
|
||||||
Dictionary<string, string> headers = new Dictionary<string, string>();
|
var headers = new Dictionary<string, string>();
|
||||||
headers.Add("path", filePath);
|
headers.Add("path", filePath);
|
||||||
await HttpClientHelper.Instance.PutAsync(url, headers);
|
await HttpClientHelper.Instance.PutAsync(url, headers);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -21,7 +21,7 @@ namespace ServiceLib.Handler
|
|||||||
public static Config? LoadConfig()
|
public static Config? LoadConfig()
|
||||||
{
|
{
|
||||||
Config? config = null;
|
Config? config = null;
|
||||||
var result = Utils.LoadResource(Utils.GetConfigPath(_configRes));
|
var result = EmbedUtils.LoadResource(Utils.GetConfigPath(_configRes));
|
||||||
if (Utils.IsNotEmpty(result))
|
if (Utils.IsNotEmpty(result))
|
||||||
{
|
{
|
||||||
config = JsonUtils.Deserialize<Config>(result);
|
config = JsonUtils.Deserialize<Config>(result);
|
||||||
@@ -105,14 +105,9 @@ namespace ServiceLib.Handler
|
|||||||
|
|
||||||
if (Utils.IsNullOrEmpty(config.UiItem.CurrentLanguage))
|
if (Utils.IsNullOrEmpty(config.UiItem.CurrentLanguage))
|
||||||
{
|
{
|
||||||
if (Thread.CurrentThread.CurrentCulture.Name.Equals("zh-cn", StringComparison.CurrentCultureIgnoreCase))
|
config.UiItem.CurrentLanguage = Thread.CurrentThread.CurrentCulture.TwoLetterISOLanguageName.Equals("zh", StringComparison.CurrentCultureIgnoreCase)
|
||||||
{
|
? Global.Languages.First()
|
||||||
config.UiItem.CurrentLanguage = Global.Languages.First();
|
: Global.Languages[2];
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
config.UiItem.CurrentLanguage = Global.Languages[2];
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
config.ConstItem ??= new ConstItem();
|
config.ConstItem ??= new ConstItem();
|
||||||
@@ -130,6 +125,10 @@ namespace ServiceLib.Handler
|
|||||||
{
|
{
|
||||||
config.SpeedTestItem.SpeedPingTestUrl = Global.SpeedPingTestUrl;
|
config.SpeedTestItem.SpeedPingTestUrl = Global.SpeedPingTestUrl;
|
||||||
}
|
}
|
||||||
|
if (config.SpeedTestItem.MixedConcurrencyCount < 1)
|
||||||
|
{
|
||||||
|
config.SpeedTestItem.MixedConcurrencyCount = 5;
|
||||||
|
}
|
||||||
|
|
||||||
config.Mux4RayItem ??= new()
|
config.Mux4RayItem ??= new()
|
||||||
{
|
{
|
||||||
@@ -159,6 +158,7 @@ namespace ServiceLib.Handler
|
|||||||
Length = "100-200",
|
Length = "100-200",
|
||||||
Interval = "10-20"
|
Interval = "10-20"
|
||||||
};
|
};
|
||||||
|
config.GlobalHotkeys ??= new();
|
||||||
|
|
||||||
if (config.SystemProxyItem.SystemProxyExceptions.IsNullOrEmpty())
|
if (config.SystemProxyItem.SystemProxyExceptions.IsNullOrEmpty())
|
||||||
{
|
{
|
||||||
@@ -295,7 +295,7 @@ namespace ServiceLib.Handler
|
|||||||
/// <param name="config"></param>
|
/// <param name="config"></param>
|
||||||
/// <param name="indexes"></param>
|
/// <param name="indexes"></param>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
public static async Task<int> RemoveServer(Config config, List<ProfileItem> indexes)
|
public static async Task<int> RemoveServers(Config config, List<ProfileItem> indexes)
|
||||||
{
|
{
|
||||||
var subid = "TempRemoveSubId";
|
var subid = "TempRemoveSubId";
|
||||||
foreach (var item in indexes)
|
foreach (var item in indexes)
|
||||||
@@ -304,7 +304,7 @@ namespace ServiceLib.Handler
|
|||||||
}
|
}
|
||||||
|
|
||||||
await SQLiteHelper.Instance.UpdateAllAsync(indexes);
|
await SQLiteHelper.Instance.UpdateAllAsync(indexes);
|
||||||
await RemoveServerViaSubid(config, subid, false);
|
await RemoveServersViaSubid(config, subid, false);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@@ -725,7 +725,7 @@ namespace ServiceLib.Handler
|
|||||||
profileItem.Network = string.Empty;
|
profileItem.Network = string.Empty;
|
||||||
if (profileItem.ShortId.IsNullOrEmpty())
|
if (profileItem.ShortId.IsNullOrEmpty())
|
||||||
{
|
{
|
||||||
profileItem.ShortId = Global.TunMtus.FirstOrDefault();
|
profileItem.ShortId = Global.TunMtus.First().ToString();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (profileItem.Id.IsNullOrEmpty())
|
if (profileItem.Id.IsNullOrEmpty())
|
||||||
@@ -759,9 +759,9 @@ namespace ServiceLib.Handler
|
|||||||
Security = t.Security,
|
Security = t.Security,
|
||||||
Network = t.Network,
|
Network = t.Network,
|
||||||
StreamSecurity = t.StreamSecurity,
|
StreamSecurity = t.StreamSecurity,
|
||||||
Delay = t33 == null ? 0 : t33.Delay,
|
Delay = t33?.Delay ?? 0,
|
||||||
Speed = t33 == null ? 0 : t33.Speed,
|
Speed = t33?.Speed ?? 0,
|
||||||
Sort = t33 == null ? 0 : t33.Sort
|
Sort = t33?.Sort ?? 0
|
||||||
}).ToList();
|
}).ToList();
|
||||||
|
|
||||||
Enum.TryParse(colName, true, out EServerColName name);
|
Enum.TryParse(colName, true, out EServerColName name);
|
||||||
@@ -873,7 +873,8 @@ namespace ServiceLib.Handler
|
|||||||
|
|
||||||
List<ProfileItem> lstKeep = new();
|
List<ProfileItem> lstKeep = new();
|
||||||
List<ProfileItem> lstRemove = new();
|
List<ProfileItem> lstRemove = new();
|
||||||
if (!config.GuiItem.KeepOlderDedupl) lstProfile.Reverse();
|
if (!config.GuiItem.KeepOlderDedupl)
|
||||||
|
lstProfile.Reverse();
|
||||||
|
|
||||||
foreach (ProfileItem item in lstProfile)
|
foreach (ProfileItem item in lstProfile)
|
||||||
{
|
{
|
||||||
@@ -886,7 +887,7 @@ namespace ServiceLib.Handler
|
|||||||
lstRemove.Add(item);
|
lstRemove.Add(item);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
await RemoveServer(config, lstRemove);
|
await RemoveServers(config, lstRemove);
|
||||||
|
|
||||||
return new Tuple<int, int>(lstProfile.Count, lstKeep.Count);
|
return new Tuple<int, int>(lstProfile.Count, lstKeep.Count);
|
||||||
}
|
}
|
||||||
@@ -1051,6 +1052,24 @@ namespace ServiceLib.Handler
|
|||||||
return itemSocks;
|
return itemSocks;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static async Task<int> RemoveInvalidServerResult(Config config, string subid)
|
||||||
|
{
|
||||||
|
var lstModel = await AppHandler.Instance.ProfileItems(subid, "");
|
||||||
|
if (lstModel is { Count: <= 0 })
|
||||||
|
{
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
var lstProfileExs = await ProfileExHandler.Instance.GetProfileExs();
|
||||||
|
var lstProfile = (from t in lstModel
|
||||||
|
join t2 in lstProfileExs on t.IndexId equals t2.IndexId
|
||||||
|
where t2.Delay == -1
|
||||||
|
select t).ToList();
|
||||||
|
|
||||||
|
await RemoveServers(config, JsonUtils.Deserialize<List<ProfileItem>>(JsonUtils.Serialize(lstProfile)));
|
||||||
|
|
||||||
|
return lstProfile.Count;
|
||||||
|
}
|
||||||
|
|
||||||
#endregion Server
|
#endregion Server
|
||||||
|
|
||||||
#region Batch add servers
|
#region Batch add servers
|
||||||
@@ -1073,7 +1092,7 @@ namespace ServiceLib.Handler
|
|||||||
//remove sub items
|
//remove sub items
|
||||||
if (isSub && Utils.IsNotEmpty(subid))
|
if (isSub && Utils.IsNotEmpty(subid))
|
||||||
{
|
{
|
||||||
await RemoveServerViaSubid(config, subid, isSub);
|
await RemoveServersViaSubid(config, subid, isSub);
|
||||||
subFilter = (await AppHandler.Instance.GetSubItem(subid))?.Filter ?? "";
|
subFilter = (await AppHandler.Instance.GetSubItem(subid))?.Filter ?? "";
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1167,7 +1186,7 @@ namespace ServiceLib.Handler
|
|||||||
{
|
{
|
||||||
if (isSub && Utils.IsNotEmpty(subid))
|
if (isSub && Utils.IsNotEmpty(subid))
|
||||||
{
|
{
|
||||||
await RemoveServerViaSubid(config, subid, isSub);
|
await RemoveServersViaSubid(config, subid, isSub);
|
||||||
}
|
}
|
||||||
int count = 0;
|
int count = 0;
|
||||||
foreach (var it in lstProfiles)
|
foreach (var it in lstProfiles)
|
||||||
@@ -1223,7 +1242,7 @@ namespace ServiceLib.Handler
|
|||||||
|
|
||||||
if (isSub && Utils.IsNotEmpty(subid))
|
if (isSub && Utils.IsNotEmpty(subid))
|
||||||
{
|
{
|
||||||
await RemoveServerViaSubid(config, subid, isSub);
|
await RemoveServersViaSubid(config, subid, isSub);
|
||||||
}
|
}
|
||||||
|
|
||||||
profileItem.Subid = subid;
|
profileItem.Subid = subid;
|
||||||
@@ -1248,7 +1267,7 @@ namespace ServiceLib.Handler
|
|||||||
|
|
||||||
if (isSub && Utils.IsNotEmpty(subid))
|
if (isSub && Utils.IsNotEmpty(subid))
|
||||||
{
|
{
|
||||||
await RemoveServerViaSubid(config, subid, isSub);
|
await RemoveServersViaSubid(config, subid, isSub);
|
||||||
}
|
}
|
||||||
|
|
||||||
var lstSsServer = ShadowsocksFmt.ResolveSip008(strData);
|
var lstSsServer = ShadowsocksFmt.ResolveSip008(strData);
|
||||||
@@ -1363,7 +1382,8 @@ namespace ServiceLib.Handler
|
|||||||
};
|
};
|
||||||
|
|
||||||
var uri = Utils.TryUri(url);
|
var uri = Utils.TryUri(url);
|
||||||
if (uri == null) return -1;
|
if (uri == null)
|
||||||
|
return -1;
|
||||||
//Do not allow http protocol
|
//Do not allow http protocol
|
||||||
if (url.StartsWith(Global.HttpProtocol) && !Utils.IsPrivateNetwork(uri.IdnHost))
|
if (url.StartsWith(Global.HttpProtocol) && !Utils.IsPrivateNetwork(uri.IdnHost))
|
||||||
{
|
{
|
||||||
@@ -1434,7 +1454,7 @@ namespace ServiceLib.Handler
|
|||||||
/// <param name="config"></param>
|
/// <param name="config"></param>
|
||||||
/// <param name="subid"></param>
|
/// <param name="subid"></param>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
public static async Task<int> RemoveServerViaSubid(Config config, string subid, bool isSub)
|
public static async Task<int> RemoveServersViaSubid(Config config, string subid, bool isSub)
|
||||||
{
|
{
|
||||||
if (Utils.IsNullOrEmpty(subid))
|
if (Utils.IsNullOrEmpty(subid))
|
||||||
{
|
{
|
||||||
@@ -1465,7 +1485,7 @@ namespace ServiceLib.Handler
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
await SQLiteHelper.Instance.DeleteAsync(item);
|
await SQLiteHelper.Instance.DeleteAsync(item);
|
||||||
await RemoveServerViaSubid(config, id, false);
|
await RemoveServersViaSubid(config, id, false);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@@ -1733,7 +1753,7 @@ namespace ServiceLib.Handler
|
|||||||
Url = string.Empty,
|
Url = string.Empty,
|
||||||
Sort = maxSort + 1,
|
Sort = maxSort + 1,
|
||||||
};
|
};
|
||||||
await AddBatchRoutingRules(item2, Utils.GetEmbedText(Global.CustomRoutingFileName + "white"));
|
await AddBatchRoutingRules(item2, EmbedUtils.GetEmbedText(Global.CustomRoutingFileName + "white"));
|
||||||
|
|
||||||
//Blacklist
|
//Blacklist
|
||||||
var item3 = new RoutingItem()
|
var item3 = new RoutingItem()
|
||||||
@@ -1742,7 +1762,7 @@ namespace ServiceLib.Handler
|
|||||||
Url = string.Empty,
|
Url = string.Empty,
|
||||||
Sort = maxSort + 2,
|
Sort = maxSort + 2,
|
||||||
};
|
};
|
||||||
await AddBatchRoutingRules(item3, Utils.GetEmbedText(Global.CustomRoutingFileName + "black"));
|
await AddBatchRoutingRules(item3, EmbedUtils.GetEmbedText(Global.CustomRoutingFileName + "black"));
|
||||||
|
|
||||||
//Global
|
//Global
|
||||||
var item1 = new RoutingItem()
|
var item1 = new RoutingItem()
|
||||||
@@ -1751,7 +1771,7 @@ namespace ServiceLib.Handler
|
|||||||
Url = string.Empty,
|
Url = string.Empty,
|
||||||
Sort = maxSort + 3,
|
Sort = maxSort + 3,
|
||||||
};
|
};
|
||||||
await AddBatchRoutingRules(item1, Utils.GetEmbedText(Global.CustomRoutingFileName + "global"));
|
await AddBatchRoutingRules(item1, EmbedUtils.GetEmbedText(Global.CustomRoutingFileName + "global"));
|
||||||
|
|
||||||
if (!blImportAdvancedRules)
|
if (!blImportAdvancedRules)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
namespace ServiceLib.Handler
|
namespace ServiceLib.Handler
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Core configuration file processing class
|
/// Core configuration file processing class
|
||||||
@@ -109,6 +109,30 @@
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static async Task<RetResult> GenerateClientSpeedtestConfig(Config config, ProfileItem node, ServerTestItem testItem, string fileName)
|
||||||
|
{
|
||||||
|
var result = new RetResult();
|
||||||
|
var initPort = AppHandler.Instance.GetLocalPort(EInboundProtocol.speedtest);
|
||||||
|
var port = Utils.GetFreePort(initPort + testItem.QueueNum);
|
||||||
|
testItem.Port = port;
|
||||||
|
|
||||||
|
if (AppHandler.Instance.GetCoreType(node, node.ConfigType) == ECoreType.sing_box)
|
||||||
|
{
|
||||||
|
result = await new CoreConfigSingboxService(config).GenerateClientSpeedtestConfig(node, port);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
result = await new CoreConfigV2rayService(config).GenerateClientSpeedtestConfig(node, port);
|
||||||
|
}
|
||||||
|
if (result.Success != true)
|
||||||
|
{
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
await File.WriteAllTextAsync(fileName, result.Data.ToString());
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
public static async Task<RetResult> GenerateClientMultipleLoadConfig(Config config, string fileName, List<ProfileItem> selecteds, ECoreType coreType)
|
public static async Task<RetResult> GenerateClientMultipleLoadConfig(Config config, string fileName, List<ProfileItem> selecteds, ECoreType coreType)
|
||||||
{
|
{
|
||||||
var result = new RetResult();
|
var result = new RetResult();
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
using System.Diagnostics;
|
using System.Diagnostics;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
|
|
||||||
namespace ServiceLib.Handler
|
namespace ServiceLib.Handler
|
||||||
@@ -22,8 +22,19 @@ namespace ServiceLib.Handler
|
|||||||
_config = config;
|
_config = config;
|
||||||
_updateFunc = updateFunc;
|
_updateFunc = updateFunc;
|
||||||
|
|
||||||
Environment.SetEnvironmentVariable("V2RAY_LOCATION_ASSET", Utils.GetBinPath(""), EnvironmentVariableTarget.Process);
|
Environment.SetEnvironmentVariable(Global.V2RayLocalAsset, Utils.GetBinPath(""), EnvironmentVariableTarget.Process);
|
||||||
Environment.SetEnvironmentVariable("XRAY_LOCATION_ASSET", 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())
|
if (Utils.IsNonWindows())
|
||||||
{
|
{
|
||||||
@@ -59,7 +70,7 @@ namespace ServiceLib.Handler
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
var fileName = Utils.GetConfigPath(Global.CoreConfigFileName);
|
var fileName = Utils.GetBinConfigPath(Global.CoreConfigFileName);
|
||||||
var result = await CoreConfigHandler.GenerateClientConfig(node, fileName);
|
var result = await CoreConfigHandler.GenerateClientConfig(node, fileName);
|
||||||
if (result.Success != true)
|
if (result.Success != true)
|
||||||
{
|
{
|
||||||
@@ -72,6 +83,13 @@ namespace ServiceLib.Handler
|
|||||||
UpdateFunc(false, string.Format(ResUI.StartService, DateTime.Now.ToString("yyyy/MM/dd HH:mm:ss")));
|
UpdateFunc(false, string.Format(ResUI.StartService, DateTime.Now.ToString("yyyy/MM/dd HH:mm:ss")));
|
||||||
await CoreStop();
|
await CoreStop();
|
||||||
await Task.Delay(100);
|
await Task.Delay(100);
|
||||||
|
|
||||||
|
if (Utils.IsWindows() && _config.TunModeItem.EnableTun)
|
||||||
|
{
|
||||||
|
await Task.Delay(100);
|
||||||
|
await WindowsUtils.RemoveTunDevice();
|
||||||
|
}
|
||||||
|
|
||||||
await CoreStart(node);
|
await CoreStart(node);
|
||||||
await CoreStartPreService(node);
|
await CoreStartPreService(node);
|
||||||
if (_process != null)
|
if (_process != null)
|
||||||
@@ -83,7 +101,8 @@ namespace ServiceLib.Handler
|
|||||||
public async Task<int> LoadCoreConfigSpeedtest(List<ServerTestItem> selecteds)
|
public async Task<int> LoadCoreConfigSpeedtest(List<ServerTestItem> selecteds)
|
||||||
{
|
{
|
||||||
var coreType = selecteds.Exists(t => t.ConfigType is EConfigType.Hysteria2 or EConfigType.TUIC or EConfigType.WireGuard) ? ECoreType.sing_box : ECoreType.Xray;
|
var coreType = selecteds.Exists(t => t.ConfigType is EConfigType.Hysteria2 or EConfigType.TUIC or EConfigType.WireGuard) ? ECoreType.sing_box : ECoreType.Xray;
|
||||||
var configPath = Utils.GetConfigPath(Global.CoreSpeedtestConfigFileName);
|
var fileName = string.Format(Global.CoreSpeedtestConfigFileName, Utils.GetGuid(false));
|
||||||
|
var configPath = Utils.GetBinConfigPath(fileName);
|
||||||
var result = await CoreConfigHandler.GenerateClientSpeedtestConfig(_config, configPath, selecteds, coreType);
|
var result = await CoreConfigHandler.GenerateClientSpeedtestConfig(_config, configPath, selecteds, coreType);
|
||||||
UpdateFunc(false, result.Msg);
|
UpdateFunc(false, result.Msg);
|
||||||
if (result.Success != true)
|
if (result.Success != true)
|
||||||
@@ -95,7 +114,34 @@ namespace ServiceLib.Handler
|
|||||||
UpdateFunc(false, configPath);
|
UpdateFunc(false, configPath);
|
||||||
|
|
||||||
var coreInfo = CoreInfoHandler.Instance.GetCoreInfo(coreType);
|
var coreInfo = CoreInfoHandler.Instance.GetCoreInfo(coreType);
|
||||||
var proc = await RunProcess(coreInfo, Global.CoreSpeedtestConfigFileName, true, false);
|
var proc = await RunProcess(coreInfo, fileName, true, false);
|
||||||
|
if (proc is null)
|
||||||
|
{
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return proc.Id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<int> LoadCoreConfigSpeedtest(ServerTestItem testItem)
|
||||||
|
{
|
||||||
|
var node = await AppHandler.Instance.GetProfileItem(testItem.IndexId);
|
||||||
|
if (node is null)
|
||||||
|
{
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
var fileName = string.Format(Global.CoreSpeedtestConfigFileName, Utils.GetGuid(false));
|
||||||
|
var configPath = Utils.GetBinConfigPath(fileName);
|
||||||
|
var result = await CoreConfigHandler.GenerateClientSpeedtestConfig(_config, node, testItem, configPath);
|
||||||
|
if (result.Success != true)
|
||||||
|
{
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
var coreType = AppHandler.Instance.GetCoreType(node, node.ConfigType);
|
||||||
|
var coreInfo = CoreInfoHandler.Instance.GetCoreInfo(coreType);
|
||||||
|
var proc = await RunProcess(coreInfo, fileName, true, false);
|
||||||
if (proc is null)
|
if (proc is null)
|
||||||
{
|
{
|
||||||
return -1;
|
return -1;
|
||||||
@@ -157,7 +203,7 @@ namespace ServiceLib.Handler
|
|||||||
if (itemSocks != null)
|
if (itemSocks != null)
|
||||||
{
|
{
|
||||||
var preCoreType = itemSocks.CoreType ?? ECoreType.sing_box;
|
var preCoreType = itemSocks.CoreType ?? ECoreType.sing_box;
|
||||||
var fileName = Utils.GetConfigPath(Global.CorePreConfigFileName);
|
var fileName = Utils.GetBinConfigPath(Global.CorePreConfigFileName);
|
||||||
var result = await CoreConfigHandler.GenerateClientConfig(itemSocks, fileName);
|
var result = await CoreConfigHandler.GenerateClientConfig(itemSocks, fileName);
|
||||||
if (result.Success)
|
if (result.Success)
|
||||||
{
|
{
|
||||||
@@ -207,8 +253,8 @@ namespace ServiceLib.Handler
|
|||||||
StartInfo = new()
|
StartInfo = new()
|
||||||
{
|
{
|
||||||
FileName = fileName,
|
FileName = fileName,
|
||||||
Arguments = string.Format(coreInfo.Arguments, configPath),
|
Arguments = string.Format(coreInfo.Arguments, coreInfo.AbsolutePath ? Utils.GetBinConfigPath(configPath).AppendQuotes() : configPath),
|
||||||
WorkingDirectory = Utils.GetConfigPath(),
|
WorkingDirectory = Utils.GetBinConfigPath(),
|
||||||
UseShellExecute = false,
|
UseShellExecute = false,
|
||||||
RedirectStandardOutput = displayLog,
|
RedirectStandardOutput = displayLog,
|
||||||
RedirectStandardError = displayLog,
|
RedirectStandardError = displayLog,
|
||||||
@@ -228,12 +274,14 @@ namespace ServiceLib.Handler
|
|||||||
{
|
{
|
||||||
proc.OutputDataReceived += (sender, e) =>
|
proc.OutputDataReceived += (sender, e) =>
|
||||||
{
|
{
|
||||||
if (Utils.IsNullOrEmpty(e.Data)) return;
|
if (Utils.IsNullOrEmpty(e.Data))
|
||||||
|
return;
|
||||||
UpdateFunc(false, e.Data + Environment.NewLine);
|
UpdateFunc(false, e.Data + Environment.NewLine);
|
||||||
};
|
};
|
||||||
proc.ErrorDataReceived += (sender, e) =>
|
proc.ErrorDataReceived += (sender, e) =>
|
||||||
{
|
{
|
||||||
if (Utils.IsNullOrEmpty(e.Data)) return;
|
if (Utils.IsNullOrEmpty(e.Data))
|
||||||
|
return;
|
||||||
UpdateFunc(false, e.Data + Environment.NewLine);
|
UpdateFunc(false, e.Data + Environment.NewLine);
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
@@ -247,7 +295,8 @@ namespace ServiceLib.Handler
|
|||||||
await Task.Delay(10);
|
await Task.Delay(10);
|
||||||
await proc.StandardInput.WriteLineAsync(pwd);
|
await proc.StandardInput.WriteLineAsync(pwd);
|
||||||
}
|
}
|
||||||
if (isNeedSudo) _linuxSudoPid = proc.Id;
|
if (isNeedSudo)
|
||||||
|
_linuxSudoPid = proc.Id;
|
||||||
|
|
||||||
if (displayLog)
|
if (displayLog)
|
||||||
{
|
{
|
||||||
@@ -266,7 +315,7 @@ namespace ServiceLib.Handler
|
|||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
Logging.SaveLog(_tag, ex);
|
Logging.SaveLog(_tag, ex);
|
||||||
UpdateFunc(true, ex.Message);
|
UpdateFunc(mayNeedSudo, ex.Message);
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -277,7 +326,7 @@ namespace ServiceLib.Handler
|
|||||||
|
|
||||||
private async Task RunProcessAsLinuxSudo(Process proc, string fileName, CoreInfo coreInfo, string configPath)
|
private async Task RunProcessAsLinuxSudo(Process proc, string fileName, CoreInfo coreInfo, string configPath)
|
||||||
{
|
{
|
||||||
var cmdLine = $"{fileName.AppendQuotes()} {string.Format(coreInfo.Arguments, Utils.GetConfigPath(configPath).AppendQuotes())}";
|
var cmdLine = $"{fileName.AppendQuotes()} {string.Format(coreInfo.Arguments, Utils.GetBinConfigPath(configPath).AppendQuotes())}";
|
||||||
|
|
||||||
var shFilePath = await CreateLinuxShellFile(cmdLine, "run_as_sudo.sh");
|
var shFilePath = await CreateLinuxShellFile(cmdLine, "run_as_sudo.sh");
|
||||||
proc.StartInfo.FileName = shFilePath;
|
proc.StartInfo.FileName = shFilePath;
|
||||||
@@ -331,7 +380,7 @@ namespace ServiceLib.Handler
|
|||||||
private async Task<string> CreateLinuxShellFile(string cmdLine, string fileName)
|
private async Task<string> CreateLinuxShellFile(string cmdLine, string fileName)
|
||||||
{
|
{
|
||||||
//Shell scripts
|
//Shell scripts
|
||||||
var shFilePath = Utils.GetBinPath(AppHandler.Instance.IsAdministrator ? "root_" + fileName : fileName);
|
var shFilePath = Utils.GetBinConfigPath(AppHandler.Instance.IsAdministrator ? "root_" + fileName : fileName);
|
||||||
File.Delete(shFilePath);
|
File.Delete(shFilePath);
|
||||||
var sb = new StringBuilder();
|
var sb = new StringBuilder();
|
||||||
sb.AppendLine("#!/bin/sh");
|
sb.AppendLine("#!/bin/sh");
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
namespace ServiceLib.Handler
|
namespace ServiceLib.Handler
|
||||||
{
|
{
|
||||||
public sealed class CoreInfoHandler
|
public sealed class CoreInfoHandler
|
||||||
{
|
{
|
||||||
@@ -44,7 +44,7 @@
|
|||||||
}
|
}
|
||||||
if (fileName.IsNullOrEmpty())
|
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);
|
Logging.SaveLog(msg);
|
||||||
}
|
}
|
||||||
return fileName;
|
return fileName;
|
||||||
@@ -52,107 +52,102 @@
|
|||||||
|
|
||||||
private void InitCoreInfo()
|
private void InitCoreInfo()
|
||||||
{
|
{
|
||||||
|
var urlN = GetCoreUrl(ECoreType.v2rayN);
|
||||||
|
var urlXray = GetCoreUrl(ECoreType.Xray);
|
||||||
|
var urlMihomo = GetCoreUrl(ECoreType.mihomo);
|
||||||
|
var urlSingbox = GetCoreUrl(ECoreType.sing_box);
|
||||||
|
|
||||||
_coreInfo =
|
_coreInfo =
|
||||||
[
|
[
|
||||||
new CoreInfo
|
new CoreInfo
|
||||||
{
|
{
|
||||||
CoreType = ECoreType.v2rayN,
|
CoreType = ECoreType.v2rayN,
|
||||||
Url = Global.NUrl,
|
Url = GetCoreUrl(ECoreType.v2rayN),
|
||||||
ReleaseApiUrl = Global.NUrl.Replace(Global.GithubUrl, Global.GithubApiUrl),
|
ReleaseApiUrl = urlN.Replace(Global.GithubUrl, Global.GithubApiUrl),
|
||||||
DownloadUrlWin64 = Global.NUrl + "/download/{0}/v2rayN-windows-64.zip",
|
DownloadUrlWin64 = urlN + "/download/{0}/v2rayN-windows-64.zip",
|
||||||
DownloadUrlWinArm64 = Global.NUrl + "/download/{0}/v2rayN-windows-arm64.zip",
|
DownloadUrlWinArm64 = urlN + "/download/{0}/v2rayN-windows-arm64.zip",
|
||||||
DownloadUrlLinux64 = Global.NUrl + "/download/{0}/v2rayN-linux-64.zip",
|
DownloadUrlLinux64 = urlN + "/download/{0}/v2rayN-linux-64.zip",
|
||||||
DownloadUrlLinuxArm64 = Global.NUrl + "/download/{0}/v2rayN-linux-arm64.zip",
|
DownloadUrlLinuxArm64 = urlN + "/download/{0}/v2rayN-linux-arm64.zip",
|
||||||
DownloadUrlOSX64 = Global.NUrl + "/download/{0}/v2rayN-macos-64.zip",
|
DownloadUrlOSX64 = urlN + "/download/{0}/v2rayN-macos-64.zip",
|
||||||
DownloadUrlOSXArm64 = Global.NUrl + "/download/{0}/v2rayN-macos-arm64.zip",
|
DownloadUrlOSXArm64 = urlN + "/download/{0}/v2rayN-macos-arm64.zip",
|
||||||
},
|
},
|
||||||
|
|
||||||
new CoreInfo
|
new CoreInfo
|
||||||
{
|
{
|
||||||
CoreType = ECoreType.v2fly,
|
CoreType = ECoreType.v2fly,
|
||||||
CoreExes = ["wv2ray", "v2ray"],
|
CoreExes = ["v2ray"],
|
||||||
Arguments = "",
|
Arguments = "{0}",
|
||||||
Url = Global.V2flyCoreUrl,
|
Url = GetCoreUrl(ECoreType.v2fly),
|
||||||
ReleaseApiUrl = Global.V2flyCoreUrl.Replace(Global.GithubUrl, Global.GithubApiUrl),
|
|
||||||
Match = "V2Ray",
|
Match = "V2Ray",
|
||||||
VersionArg = "-version",
|
VersionArg = "-version",
|
||||||
RedirectInfo = true,
|
|
||||||
},
|
},
|
||||||
|
|
||||||
new CoreInfo
|
new CoreInfo
|
||||||
{
|
{
|
||||||
CoreType = ECoreType.v2fly_v5,
|
CoreType = ECoreType.v2fly_v5,
|
||||||
CoreExes = ["v2ray"],
|
CoreExes = ["v2ray"],
|
||||||
Arguments = "run -c config.json -format jsonv5",
|
Arguments = "run -c {0} -format jsonv5",
|
||||||
Url = Global.V2flyCoreUrl,
|
Url = GetCoreUrl(ECoreType.v2fly_v5),
|
||||||
ReleaseApiUrl = Global.V2flyCoreUrl.Replace(Global.GithubUrl, Global.GithubApiUrl),
|
|
||||||
Match = "V2Ray",
|
Match = "V2Ray",
|
||||||
VersionArg = "version",
|
VersionArg = "version",
|
||||||
RedirectInfo = true,
|
|
||||||
},
|
},
|
||||||
|
|
||||||
new CoreInfo
|
new CoreInfo
|
||||||
{
|
{
|
||||||
CoreType = ECoreType.Xray,
|
CoreType = ECoreType.Xray,
|
||||||
CoreExes = ["xray", "wxray"],
|
CoreExes = ["xray"],
|
||||||
Arguments = "run -c {0}",
|
Arguments = "run -c {0}",
|
||||||
Url = Global.XrayCoreUrl,
|
Url = GetCoreUrl(ECoreType.Xray),
|
||||||
ReleaseApiUrl = Global.XrayCoreUrl.Replace(Global.GithubUrl, Global.GithubApiUrl),
|
ReleaseApiUrl = urlXray.Replace(Global.GithubUrl, Global.GithubApiUrl),
|
||||||
DownloadUrlWin64 = Global.XrayCoreUrl + "/download/{0}/Xray-windows-64.zip",
|
DownloadUrlWin64 = urlXray + "/download/{0}/Xray-windows-64.zip",
|
||||||
DownloadUrlWinArm64 = Global.XrayCoreUrl + "/download/{0}/Xray-windows-arm64-v8a.zip",
|
DownloadUrlWinArm64 = urlXray + "/download/{0}/Xray-windows-arm64-v8a.zip",
|
||||||
DownloadUrlLinux64 = Global.XrayCoreUrl + "/download/{0}/Xray-linux-64.zip",
|
DownloadUrlLinux64 = urlXray + "/download/{0}/Xray-linux-64.zip",
|
||||||
DownloadUrlLinuxArm64 = Global.XrayCoreUrl + "/download/{0}/Xray-linux-arm64-v8a.zip",
|
DownloadUrlLinuxArm64 = urlXray + "/download/{0}/Xray-linux-arm64-v8a.zip",
|
||||||
DownloadUrlOSX64 = Global.XrayCoreUrl + "/download/{0}/Xray-macos-64.zip",
|
DownloadUrlOSX64 = urlXray + "/download/{0}/Xray-macos-64.zip",
|
||||||
DownloadUrlOSXArm64 = Global.XrayCoreUrl + "/download/{0}/Xray-macos-arm64-v8a.zip",
|
DownloadUrlOSXArm64 = urlXray + "/download/{0}/Xray-macos-arm64-v8a.zip",
|
||||||
Match = "Xray",
|
Match = "Xray",
|
||||||
VersionArg = "-version",
|
VersionArg = "-version",
|
||||||
RedirectInfo = true,
|
|
||||||
},
|
},
|
||||||
|
|
||||||
new CoreInfo
|
new CoreInfo
|
||||||
{
|
{
|
||||||
CoreType = ECoreType.mihomo,
|
CoreType = ECoreType.mihomo,
|
||||||
CoreExes = ["mihomo-windows-amd64-compatible", "mihomo-windows-amd64", "mihomo-linux-amd64", "mihomo", "clash"],
|
CoreExes = ["mihomo-windows-amd64-compatible", "mihomo-windows-amd64", "mihomo-linux-amd64", "clash", "mihomo"],
|
||||||
Arguments = "-f config.json" + PortableMode(),
|
Arguments = "-f {0}" + PortableMode(),
|
||||||
Url = Global.MihomoCoreUrl,
|
Url = GetCoreUrl(ECoreType.mihomo),
|
||||||
ReleaseApiUrl = Global.MihomoCoreUrl.Replace(Global.GithubUrl, Global.GithubApiUrl),
|
ReleaseApiUrl = urlMihomo.Replace(Global.GithubUrl, Global.GithubApiUrl),
|
||||||
DownloadUrlWin64 = Global.MihomoCoreUrl + "/download/{0}/mihomo-windows-amd64-compatible-{0}.zip",
|
DownloadUrlWin64 = urlMihomo + "/download/{0}/mihomo-windows-amd64-compatible-{0}.zip",
|
||||||
DownloadUrlWinArm64 = Global.MihomoCoreUrl + "/download/{0}/mihomo-windows-arm64-{0}.zip",
|
DownloadUrlWinArm64 = urlMihomo + "/download/{0}/mihomo-windows-arm64-{0}.zip",
|
||||||
DownloadUrlLinux64 = Global.MihomoCoreUrl + "/download/{0}/mihomo-linux-amd64-compatible-{0}.gz",
|
DownloadUrlLinux64 = urlMihomo + "/download/{0}/mihomo-linux-amd64-compatible-{0}.gz",
|
||||||
DownloadUrlLinuxArm64 = Global.MihomoCoreUrl + "/download/{0}/mihomo-linux-arm64-{0}.gz",
|
DownloadUrlLinuxArm64 = urlMihomo + "/download/{0}/mihomo-linux-arm64-{0}.gz",
|
||||||
DownloadUrlOSX64 = Global.MihomoCoreUrl + "/download/{0}/mihomo-darwin-amd64-compatible-{0}.gz",
|
DownloadUrlOSX64 = urlMihomo + "/download/{0}/mihomo-darwin-amd64-compatible-{0}.gz",
|
||||||
DownloadUrlOSXArm64 = Global.MihomoCoreUrl + "/download/{0}/mihomo-darwin-arm64-{0}.gz",
|
DownloadUrlOSXArm64 = urlMihomo + "/download/{0}/mihomo-darwin-arm64-{0}.gz",
|
||||||
Match = "Mihomo",
|
Match = "Mihomo",
|
||||||
VersionArg = "-v",
|
VersionArg = "-v",
|
||||||
RedirectInfo = true,
|
|
||||||
},
|
},
|
||||||
|
|
||||||
new CoreInfo
|
new CoreInfo
|
||||||
{
|
{
|
||||||
CoreType = ECoreType.hysteria,
|
CoreType = ECoreType.hysteria,
|
||||||
CoreExes = ["hysteria-windows-amd64", "hysteria"],
|
CoreExes = ["hysteria"],
|
||||||
Arguments = "",
|
Arguments = "",
|
||||||
Url = Global.HysteriaCoreUrl,
|
Url = GetCoreUrl(ECoreType.hysteria),
|
||||||
ReleaseApiUrl = Global.HysteriaCoreUrl.Replace(Global.GithubUrl, Global.GithubApiUrl),
|
|
||||||
RedirectInfo = true,
|
|
||||||
},
|
},
|
||||||
|
|
||||||
new CoreInfo
|
new CoreInfo
|
||||||
{
|
{
|
||||||
CoreType = ECoreType.naiveproxy,
|
CoreType = ECoreType.naiveproxy,
|
||||||
CoreExes = ["naiveproxy", "naive"],
|
CoreExes = [ "naive", "naiveproxy"],
|
||||||
Arguments = "config.json",
|
Arguments = "{0}",
|
||||||
Url = Global.NaiveproxyCoreUrl,
|
Url = GetCoreUrl(ECoreType.naiveproxy),
|
||||||
RedirectInfo = false,
|
|
||||||
},
|
},
|
||||||
|
|
||||||
new CoreInfo
|
new CoreInfo
|
||||||
{
|
{
|
||||||
CoreType = ECoreType.tuic,
|
CoreType = ECoreType.tuic,
|
||||||
CoreExes = ["tuic-client", "tuic"],
|
CoreExes = ["tuic-client", "tuic"],
|
||||||
Arguments = "-c config.json",
|
Arguments = "-c {0}",
|
||||||
Url = Global.TuicCoreUrl,
|
Url = GetCoreUrl(ECoreType.tuic),
|
||||||
RedirectInfo = true,
|
|
||||||
},
|
},
|
||||||
|
|
||||||
new CoreInfo
|
new CoreInfo
|
||||||
@@ -160,15 +155,15 @@
|
|||||||
CoreType = ECoreType.sing_box,
|
CoreType = ECoreType.sing_box,
|
||||||
CoreExes = ["sing-box-client", "sing-box"],
|
CoreExes = ["sing-box-client", "sing-box"],
|
||||||
Arguments = "run -c {0} --disable-color",
|
Arguments = "run -c {0} --disable-color",
|
||||||
Url = Global.SingboxCoreUrl,
|
Url = GetCoreUrl(ECoreType.sing_box),
|
||||||
RedirectInfo = true,
|
|
||||||
ReleaseApiUrl = Global.SingboxCoreUrl.Replace(Global.GithubUrl, Global.GithubApiUrl),
|
ReleaseApiUrl = urlSingbox.Replace(Global.GithubUrl, Global.GithubApiUrl),
|
||||||
DownloadUrlWin64 = Global.SingboxCoreUrl + "/download/{0}/sing-box-{1}-windows-amd64.zip",
|
DownloadUrlWin64 = urlSingbox + "/download/{0}/sing-box-{1}-windows-amd64.zip",
|
||||||
DownloadUrlWinArm64 = Global.SingboxCoreUrl + "/download/{0}/sing-box-{1}-windows-arm64.zip",
|
DownloadUrlWinArm64 = urlSingbox + "/download/{0}/sing-box-{1}-windows-arm64.zip",
|
||||||
DownloadUrlLinux64 = Global.SingboxCoreUrl + "/download/{0}/sing-box-{1}-linux-amd64.tar.gz",
|
DownloadUrlLinux64 = urlSingbox + "/download/{0}/sing-box-{1}-linux-amd64.tar.gz",
|
||||||
DownloadUrlLinuxArm64 = Global.SingboxCoreUrl + "/download/{0}/sing-box-{1}-linux-arm64.tar.gz",
|
DownloadUrlLinuxArm64 = urlSingbox + "/download/{0}/sing-box-{1}-linux-arm64.tar.gz",
|
||||||
DownloadUrlOSX64 = Global.SingboxCoreUrl + "/download/{0}/sing-box-{1}-darwin-amd64.tar.gz",
|
DownloadUrlOSX64 = urlSingbox + "/download/{0}/sing-box-{1}-darwin-amd64.tar.gz",
|
||||||
DownloadUrlOSXArm64 = Global.SingboxCoreUrl + "/download/{0}/sing-box-{1}-darwin-arm64.tar.gz",
|
DownloadUrlOSXArm64 = urlSingbox + "/download/{0}/sing-box-{1}-darwin-arm64.tar.gz",
|
||||||
Match = "sing-box",
|
Match = "sing-box",
|
||||||
VersionArg = "version",
|
VersionArg = "version",
|
||||||
},
|
},
|
||||||
@@ -177,8 +172,8 @@
|
|||||||
{
|
{
|
||||||
CoreType = ECoreType.juicity,
|
CoreType = ECoreType.juicity,
|
||||||
CoreExes = ["juicity-client", "juicity"],
|
CoreExes = ["juicity-client", "juicity"],
|
||||||
Arguments = "run -c config.json",
|
Arguments = "run -c {0}",
|
||||||
Url = Global.JuicityCoreUrl
|
Url = GetCoreUrl(ECoreType.juicity)
|
||||||
},
|
},
|
||||||
|
|
||||||
new CoreInfo
|
new CoreInfo
|
||||||
@@ -186,17 +181,38 @@
|
|||||||
CoreType = ECoreType.hysteria2,
|
CoreType = ECoreType.hysteria2,
|
||||||
CoreExes = ["hysteria-windows-amd64", "hysteria-linux-amd64", "hysteria"],
|
CoreExes = ["hysteria-windows-amd64", "hysteria-linux-amd64", "hysteria"],
|
||||||
Arguments = "",
|
Arguments = "",
|
||||||
Url = Global.HysteriaCoreUrl,
|
Url = GetCoreUrl(ECoreType.hysteria2),
|
||||||
ReleaseApiUrl = Global.HysteriaCoreUrl.Replace(Global.GithubUrl, Global.GithubApiUrl),
|
},
|
||||||
RedirectInfo = true,
|
|
||||||
|
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()}";
|
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
|
namespace ServiceLib.Handler.Fmt
|
||||||
{
|
{
|
||||||
@@ -214,7 +214,8 @@ namespace ServiceLib.Handler.Fmt
|
|||||||
{
|
{
|
||||||
foreach (var item in s)
|
foreach (var item in s)
|
||||||
{
|
{
|
||||||
if (str.Contains(item, StringComparison.OrdinalIgnoreCase)) return true;
|
if (str.Contains(item, StringComparison.OrdinalIgnoreCase))
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
namespace ServiceLib.Handler.Fmt
|
namespace ServiceLib.Handler.Fmt
|
||||||
{
|
{
|
||||||
public class Hysteria2Fmt : BaseFmt
|
public class Hysteria2Fmt : BaseFmt
|
||||||
{
|
{
|
||||||
@@ -11,7 +11,8 @@
|
|||||||
};
|
};
|
||||||
|
|
||||||
var url = Utils.TryUri(str);
|
var url = Utils.TryUri(str);
|
||||||
if (url == null) return null;
|
if (url == null)
|
||||||
|
return null;
|
||||||
|
|
||||||
item.Address = url.IdnHost;
|
item.Address = url.IdnHost;
|
||||||
item.Port = url.Port;
|
item.Port = url.Port;
|
||||||
@@ -28,7 +29,8 @@
|
|||||||
|
|
||||||
public static string? ToUri(ProfileItem? item)
|
public static string? ToUri(ProfileItem? item)
|
||||||
{
|
{
|
||||||
if (item == null) return null;
|
if (item == null)
|
||||||
|
return null;
|
||||||
string url = string.Empty;
|
string url = string.Empty;
|
||||||
|
|
||||||
string remark = string.Empty;
|
string remark = string.Empty;
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
using System.Text.RegularExpressions;
|
using System.Text.RegularExpressions;
|
||||||
|
|
||||||
namespace ServiceLib.Handler.Fmt
|
namespace ServiceLib.Handler.Fmt
|
||||||
{
|
{
|
||||||
@@ -26,7 +26,8 @@ namespace ServiceLib.Handler.Fmt
|
|||||||
|
|
||||||
public static string? ToUri(ProfileItem? item)
|
public static string? ToUri(ProfileItem? item)
|
||||||
{
|
{
|
||||||
if (item == null) return null;
|
if (item == null)
|
||||||
|
return null;
|
||||||
string url = string.Empty;
|
string url = string.Empty;
|
||||||
|
|
||||||
string remark = string.Empty;
|
string remark = string.Empty;
|
||||||
@@ -82,7 +83,8 @@ namespace ServiceLib.Handler.Fmt
|
|||||||
private static ProfileItem? ResolveSip002(string result)
|
private static ProfileItem? ResolveSip002(string result)
|
||||||
{
|
{
|
||||||
var parsedUrl = Utils.TryUri(result);
|
var parsedUrl = Utils.TryUri(result);
|
||||||
if (parsedUrl == null) return null;
|
if (parsedUrl == null)
|
||||||
|
return null;
|
||||||
|
|
||||||
ProfileItem item = new()
|
ProfileItem item = new()
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
namespace ServiceLib.Handler.Fmt
|
namespace ServiceLib.Handler.Fmt
|
||||||
{
|
{
|
||||||
public class SocksFmt : BaseFmt
|
public class SocksFmt : BaseFmt
|
||||||
{
|
{
|
||||||
@@ -23,7 +23,8 @@
|
|||||||
|
|
||||||
public static string? ToUri(ProfileItem? item)
|
public static string? ToUri(ProfileItem? item)
|
||||||
{
|
{
|
||||||
if (item == null) return null;
|
if (item == null)
|
||||||
|
return null;
|
||||||
var url = string.Empty;
|
var url = string.Empty;
|
||||||
|
|
||||||
var remark = string.Empty;
|
var remark = string.Empty;
|
||||||
@@ -86,7 +87,8 @@
|
|||||||
private static ProfileItem? ResolveSocksNew(string result)
|
private static ProfileItem? ResolveSocksNew(string result)
|
||||||
{
|
{
|
||||||
var parsedUrl = Utils.TryUri(result);
|
var parsedUrl = Utils.TryUri(result);
|
||||||
if (parsedUrl == null) return null;
|
if (parsedUrl == null)
|
||||||
|
return null;
|
||||||
|
|
||||||
ProfileItem item = new()
|
ProfileItem item = new()
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
namespace ServiceLib.Handler.Fmt
|
namespace ServiceLib.Handler.Fmt
|
||||||
{
|
{
|
||||||
public class TrojanFmt : BaseFmt
|
public class TrojanFmt : BaseFmt
|
||||||
{
|
{
|
||||||
@@ -12,7 +12,8 @@
|
|||||||
};
|
};
|
||||||
|
|
||||||
var url = Utils.TryUri(str);
|
var url = Utils.TryUri(str);
|
||||||
if (url == null) return null;
|
if (url == null)
|
||||||
|
return null;
|
||||||
|
|
||||||
item.Address = url.IdnHost;
|
item.Address = url.IdnHost;
|
||||||
item.Port = url.Port;
|
item.Port = url.Port;
|
||||||
@@ -27,7 +28,8 @@
|
|||||||
|
|
||||||
public static string? ToUri(ProfileItem? item)
|
public static string? ToUri(ProfileItem? item)
|
||||||
{
|
{
|
||||||
if (item == null) return null;
|
if (item == null)
|
||||||
|
return null;
|
||||||
string url = string.Empty;
|
string url = string.Empty;
|
||||||
|
|
||||||
string remark = string.Empty;
|
string remark = string.Empty;
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
namespace ServiceLib.Handler.Fmt
|
namespace ServiceLib.Handler.Fmt
|
||||||
{
|
{
|
||||||
public class TuicFmt : BaseFmt
|
public class TuicFmt : BaseFmt
|
||||||
{
|
{
|
||||||
@@ -12,7 +12,8 @@
|
|||||||
};
|
};
|
||||||
|
|
||||||
var url = Utils.TryUri(str);
|
var url = Utils.TryUri(str);
|
||||||
if (url == null) return null;
|
if (url == null)
|
||||||
|
return null;
|
||||||
|
|
||||||
item.Address = url.IdnHost;
|
item.Address = url.IdnHost;
|
||||||
item.Port = url.Port;
|
item.Port = url.Port;
|
||||||
@@ -34,7 +35,8 @@
|
|||||||
|
|
||||||
public static string? ToUri(ProfileItem? item)
|
public static string? ToUri(ProfileItem? item)
|
||||||
{
|
{
|
||||||
if (item == null) return null;
|
if (item == null)
|
||||||
|
return null;
|
||||||
string url = string.Empty;
|
string url = string.Empty;
|
||||||
|
|
||||||
string remark = string.Empty;
|
string remark = string.Empty;
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
namespace ServiceLib.Handler.Fmt
|
namespace ServiceLib.Handler.Fmt
|
||||||
{
|
{
|
||||||
public class VLESSFmt : BaseFmt
|
public class VLESSFmt : BaseFmt
|
||||||
{
|
{
|
||||||
@@ -13,7 +13,8 @@
|
|||||||
};
|
};
|
||||||
|
|
||||||
var url = Utils.TryUri(str);
|
var url = Utils.TryUri(str);
|
||||||
if (url == null) return null;
|
if (url == null)
|
||||||
|
return null;
|
||||||
|
|
||||||
item.Address = url.IdnHost;
|
item.Address = url.IdnHost;
|
||||||
item.Port = url.Port;
|
item.Port = url.Port;
|
||||||
@@ -30,7 +31,8 @@
|
|||||||
|
|
||||||
public static string? ToUri(ProfileItem? item)
|
public static string? ToUri(ProfileItem? item)
|
||||||
{
|
{
|
||||||
if (item == null) return null;
|
if (item == null)
|
||||||
|
return null;
|
||||||
string url = string.Empty;
|
string url = string.Empty;
|
||||||
|
|
||||||
string remark = string.Empty;
|
string remark = string.Empty;
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
namespace ServiceLib.Handler.Fmt
|
namespace ServiceLib.Handler.Fmt
|
||||||
{
|
{
|
||||||
public class VmessFmt : BaseFmt
|
public class VmessFmt : BaseFmt
|
||||||
{
|
{
|
||||||
@@ -19,7 +19,8 @@
|
|||||||
|
|
||||||
public static string? ToUri(ProfileItem? item)
|
public static string? ToUri(ProfileItem? item)
|
||||||
{
|
{
|
||||||
if (item == null) return null;
|
if (item == null)
|
||||||
|
return null;
|
||||||
string url = string.Empty;
|
string url = string.Empty;
|
||||||
|
|
||||||
VmessQRCode vmessQRCode = new()
|
VmessQRCode vmessQRCode = new()
|
||||||
@@ -106,7 +107,8 @@
|
|||||||
};
|
};
|
||||||
|
|
||||||
var url = Utils.TryUri(str);
|
var url = Utils.TryUri(str);
|
||||||
if (url == null) return null;
|
if (url == null)
|
||||||
|
return null;
|
||||||
|
|
||||||
item.Address = url.IdnHost;
|
item.Address = url.IdnHost;
|
||||||
item.Port = url.Port;
|
item.Port = url.Port;
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
namespace ServiceLib.Handler.Fmt
|
namespace ServiceLib.Handler.Fmt
|
||||||
{
|
{
|
||||||
public class WireguardFmt : BaseFmt
|
public class WireguardFmt : BaseFmt
|
||||||
{
|
{
|
||||||
@@ -12,7 +12,8 @@
|
|||||||
};
|
};
|
||||||
|
|
||||||
var url = Utils.TryUri(str);
|
var url = Utils.TryUri(str);
|
||||||
if (url == null) return null;
|
if (url == null)
|
||||||
|
return null;
|
||||||
|
|
||||||
item.Address = url.IdnHost;
|
item.Address = url.IdnHost;
|
||||||
item.Port = url.Port;
|
item.Port = url.Port;
|
||||||
@@ -31,7 +32,8 @@
|
|||||||
|
|
||||||
public static string? ToUri(ProfileItem? item)
|
public static string? ToUri(ProfileItem? item)
|
||||||
{
|
{
|
||||||
if (item == null) return null;
|
if (item == null)
|
||||||
|
return null;
|
||||||
string url = string.Empty;
|
string url = string.Empty;
|
||||||
|
|
||||||
string remark = string.Empty;
|
string remark = string.Empty;
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
using System.Net.Sockets;
|
using System.Net.Sockets;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
|
|
||||||
namespace ServiceLib.Handler
|
namespace ServiceLib.Handler
|
||||||
@@ -35,7 +35,7 @@ namespace ServiceLib.Handler
|
|||||||
var path = Path.Combine(_configPath, "pac.txt");
|
var path = Path.Combine(_configPath, "pac.txt");
|
||||||
if (!File.Exists(path))
|
if (!File.Exists(path))
|
||||||
{
|
{
|
||||||
var pac = Utils.GetEmbedText(Global.PacFileName);
|
var pac = EmbedUtils.GetEmbedText(Global.PacFileName);
|
||||||
await File.AppendAllTextAsync(path, pac);
|
await File.AppendAllTextAsync(path, pac);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -89,7 +89,8 @@ namespace ServiceLib.Handler
|
|||||||
|
|
||||||
public static void Stop()
|
public static void Stop()
|
||||||
{
|
{
|
||||||
if (_tcpListener == null) return;
|
if (_tcpListener == null)
|
||||||
|
return;
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
_isRunning = false;
|
_isRunning = false;
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
using System.Collections.Concurrent;
|
using System.Collections.Concurrent;
|
||||||
|
|
||||||
//using System.Reactive.Linq;
|
//using System.Reactive.Linq;
|
||||||
|
|
||||||
@@ -8,7 +8,7 @@ namespace ServiceLib.Handler
|
|||||||
{
|
{
|
||||||
private static readonly Lazy<ProfileExHandler> _instance = new(() => new());
|
private static readonly Lazy<ProfileExHandler> _instance = new(() => new());
|
||||||
private ConcurrentBag<ProfileExItem> _lstProfileEx = [];
|
private ConcurrentBag<ProfileExItem> _lstProfileEx = [];
|
||||||
private Queue<string> _queIndexIds = new();
|
private readonly Queue<string> _queIndexIds = new();
|
||||||
public static ProfileExHandler Instance => _instance.Value;
|
public static ProfileExHandler Instance => _instance.Value;
|
||||||
private static readonly string _tag = "ProfileExHandler";
|
private static readonly string _tag = "ProfileExHandler";
|
||||||
|
|
||||||
@@ -59,7 +59,7 @@ namespace ServiceLib.Handler
|
|||||||
List<ProfileExItem> lstInserts = [];
|
List<ProfileExItem> lstInserts = [];
|
||||||
List<ProfileExItem> lstUpdates = [];
|
List<ProfileExItem> lstUpdates = [];
|
||||||
|
|
||||||
for (int i = 0; i < cnt; i++)
|
for (var i = 0; i < cnt; i++)
|
||||||
{
|
{
|
||||||
var id = _queIndexIds.Dequeue();
|
var id = _queIndexIds.Dequeue();
|
||||||
var item = lstExists.FirstOrDefault(t => t.IndexId == id);
|
var item = lstExists.FirstOrDefault(t => t.IndexId == id);
|
||||||
@@ -78,14 +78,19 @@ namespace ServiceLib.Handler
|
|||||||
lstInserts.Add(itemNew);
|
lstInserts.Add(itemNew);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
if (lstInserts.Count() > 0)
|
if (lstInserts.Count > 0)
|
||||||
|
{
|
||||||
await SQLiteHelper.Instance.InsertAllAsync(lstInserts);
|
await SQLiteHelper.Instance.InsertAllAsync(lstInserts);
|
||||||
|
}
|
||||||
|
|
||||||
if (lstUpdates.Count() > 0)
|
if (lstUpdates.Count > 0)
|
||||||
|
{
|
||||||
await SQLiteHelper.Instance.UpdateAllAsync(lstUpdates);
|
await SQLiteHelper.Instance.UpdateAllAsync(lstUpdates);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
Logging.SaveLog(_tag, ex);
|
Logging.SaveLog(_tag, ex);
|
||||||
@@ -93,17 +98,24 @@ namespace ServiceLib.Handler
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void AddProfileEx(string indexId, ref ProfileExItem? profileEx)
|
private ProfileExItem AddProfileEx(string indexId)
|
||||||
{
|
{
|
||||||
profileEx = new()
|
var profileEx = new ProfileExItem()
|
||||||
{
|
{
|
||||||
IndexId = indexId,
|
IndexId = indexId,
|
||||||
Delay = 0,
|
Delay = 0,
|
||||||
Speed = 0,
|
Speed = 0,
|
||||||
Sort = 0
|
Sort = 0,
|
||||||
|
Message = string.Empty
|
||||||
};
|
};
|
||||||
_lstProfileEx.Add(profileEx);
|
_lstProfileEx.Add(profileEx);
|
||||||
IndexIdEnqueue(indexId);
|
IndexIdEnqueue(indexId);
|
||||||
|
return profileEx;
|
||||||
|
}
|
||||||
|
|
||||||
|
private ProfileExItem GetProfileExItem(string? indexId)
|
||||||
|
{
|
||||||
|
return _lstProfileEx.FirstOrDefault(t => t.IndexId == indexId) ?? AddProfileEx(indexId);
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task ClearAll()
|
public async Task ClearAll()
|
||||||
@@ -124,39 +136,34 @@ namespace ServiceLib.Handler
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void SetTestDelay(string indexId, string delayVal)
|
public void SetTestDelay(string indexId, int delay)
|
||||||
{
|
{
|
||||||
var profileEx = _lstProfileEx.FirstOrDefault(t => t.IndexId == indexId);
|
var profileEx = GetProfileExItem(indexId);
|
||||||
if (profileEx == null)
|
|
||||||
{
|
|
||||||
AddProfileEx(indexId, ref profileEx);
|
|
||||||
}
|
|
||||||
|
|
||||||
int.TryParse(delayVal, out int delay);
|
|
||||||
profileEx.Delay = delay;
|
profileEx.Delay = delay;
|
||||||
IndexIdEnqueue(indexId);
|
IndexIdEnqueue(indexId);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void SetTestSpeed(string indexId, string speedVal)
|
public void SetTestSpeed(string indexId, decimal speed)
|
||||||
{
|
{
|
||||||
var profileEx = _lstProfileEx.FirstOrDefault(t => t.IndexId == indexId);
|
var profileEx = GetProfileExItem(indexId);
|
||||||
if (profileEx == null)
|
|
||||||
{
|
profileEx.Speed = speed;
|
||||||
AddProfileEx(indexId, ref profileEx);
|
IndexIdEnqueue(indexId);
|
||||||
}
|
}
|
||||||
|
|
||||||
decimal.TryParse(speedVal, out decimal speed);
|
public void SetTestMessage(string indexId, string message)
|
||||||
profileEx.Speed = speed;
|
{
|
||||||
|
var profileEx = GetProfileExItem(indexId);
|
||||||
|
|
||||||
|
profileEx.Message = message;
|
||||||
IndexIdEnqueue(indexId);
|
IndexIdEnqueue(indexId);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void SetSort(string indexId, int sort)
|
public void SetSort(string indexId, int sort)
|
||||||
{
|
{
|
||||||
var profileEx = _lstProfileEx.FirstOrDefault(t => t.IndexId == indexId);
|
var profileEx = GetProfileExItem(indexId);
|
||||||
if (profileEx == null)
|
|
||||||
{
|
|
||||||
AddProfileEx(indexId, ref profileEx);
|
|
||||||
}
|
|
||||||
profileEx.Sort = sort;
|
profileEx.Sort = sort;
|
||||||
IndexIdEnqueue(indexId);
|
IndexIdEnqueue(indexId);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,202 +1,33 @@
|
|||||||
namespace ServiceLib.Handler.SysProxy
|
namespace ServiceLib.Handler.SysProxy
|
||||||
{
|
{
|
||||||
public class ProxySettingLinux
|
public class ProxySettingLinux
|
||||||
{
|
{
|
||||||
|
private static readonly string _proxySetFileName = $"{Global.ProxySetLinuxShellFileName.Replace(Global.NamespaceSample, "")}.sh";
|
||||||
|
|
||||||
public static async Task SetProxy(string host, int port, string exceptions)
|
public static async Task SetProxy(string host, int port, string exceptions)
|
||||||
{
|
{
|
||||||
var lstCmd = GetSetCmds(host, port, exceptions);
|
List<string> args = ["manual", host, port.ToString(), exceptions];
|
||||||
|
await ExecCmd(args);
|
||||||
await ExecCmd(lstCmd);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static async Task UnsetProxy()
|
public static async Task UnsetProxy()
|
||||||
{
|
{
|
||||||
var lstCmd = GetUnsetCmds();
|
List<string> args = ["none"];
|
||||||
|
await ExecCmd(args);
|
||||||
await ExecCmd(lstCmd);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private static async Task ExecCmd(List<CmdItem> lstCmd)
|
private static async Task ExecCmd(List<string> args)
|
||||||
{
|
{
|
||||||
foreach (var cmd in lstCmd)
|
var fileName = Utils.GetBinConfigPath(_proxySetFileName);
|
||||||
|
if (!File.Exists(fileName))
|
||||||
{
|
{
|
||||||
if (cmd is null || cmd.Cmd.IsNullOrEmpty() || cmd.Arguments is null)
|
var contents = EmbedUtils.GetEmbedText(Global.ProxySetLinuxShellFileName);
|
||||||
{
|
await File.AppendAllTextAsync(fileName, contents);
|
||||||
continue;
|
|
||||||
}
|
await Utils.SetLinuxChmod(fileName);
|
||||||
await Task.Delay(10);
|
|
||||||
await Utils.GetCliWrapOutput(cmd.Cmd, cmd.Arguments);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private static List<CmdItem> GetSetCmds(string host, int port, string exceptions)
|
await Utils.GetCliWrapOutput(fileName, args);
|
||||||
{
|
|
||||||
var isKde = IsKde(out var configDir);
|
|
||||||
List<string> lstType = ["", "http", "https", "socks", "ftp"];
|
|
||||||
List<CmdItem> lstCmd = [];
|
|
||||||
|
|
||||||
//GNOME
|
|
||||||
foreach (var type in lstType)
|
|
||||||
{
|
|
||||||
lstCmd.AddRange(GetSetCmd4Gnome(type, host, port));
|
|
||||||
}
|
|
||||||
if (exceptions.IsNotEmpty())
|
|
||||||
{
|
|
||||||
lstCmd.AddRange(GetSetCmd4Gnome("exceptions", exceptions, 0));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (isKde)
|
|
||||||
{
|
|
||||||
foreach (var type in lstType)
|
|
||||||
{
|
|
||||||
lstCmd.AddRange(GetSetCmd4Kde(type, host, port, configDir));
|
|
||||||
}
|
|
||||||
if (exceptions.IsNotEmpty())
|
|
||||||
{
|
|
||||||
lstCmd.AddRange(GetSetCmd4Kde("exceptions", exceptions, 0, configDir));
|
|
||||||
}
|
|
||||||
|
|
||||||
// Notify system to reload
|
|
||||||
lstCmd.Add(new CmdItem()
|
|
||||||
{
|
|
||||||
Cmd = "dbus-send",
|
|
||||||
Arguments = ["--type=signal", "/KIO/Scheduler", "org.kde.KIO.Scheduler.reparseSlaveConfiguration", "string:''"]
|
|
||||||
});
|
|
||||||
}
|
|
||||||
return lstCmd;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static List<CmdItem> GetUnsetCmds()
|
|
||||||
{
|
|
||||||
var isKde = IsKde(out var configDir);
|
|
||||||
List<CmdItem> lstCmd = [];
|
|
||||||
|
|
||||||
//GNOME
|
|
||||||
lstCmd.Add(new CmdItem()
|
|
||||||
{
|
|
||||||
Cmd = "gsettings",
|
|
||||||
Arguments = ["set", "org.gnome.system.proxy", "mode", "none"]
|
|
||||||
});
|
|
||||||
|
|
||||||
if (isKde)
|
|
||||||
{
|
|
||||||
lstCmd.Add(new CmdItem()
|
|
||||||
{
|
|
||||||
Cmd = GetKdeVersion(),
|
|
||||||
Arguments = ["--file", $"{configDir}/kioslaverc", "--group", "Proxy Settings", "--key", "ProxyType", "0"]
|
|
||||||
});
|
|
||||||
|
|
||||||
// Notify system to reload
|
|
||||||
lstCmd.Add(new CmdItem()
|
|
||||||
{
|
|
||||||
Cmd = "dbus-send",
|
|
||||||
Arguments = ["--type=signal", "/KIO/Scheduler", "org.kde.KIO.Scheduler.reparseSlaveConfiguration", "string:''"]
|
|
||||||
});
|
|
||||||
}
|
|
||||||
return lstCmd;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static List<CmdItem> GetSetCmd4Kde(string type, string host, int port, string configDir)
|
|
||||||
{
|
|
||||||
List<CmdItem> lstCmd = [];
|
|
||||||
var cmd = GetKdeVersion();
|
|
||||||
|
|
||||||
if (type.IsNullOrEmpty())
|
|
||||||
{
|
|
||||||
lstCmd.Add(new()
|
|
||||||
{
|
|
||||||
Cmd = cmd,
|
|
||||||
Arguments = ["--file", $"{configDir}/kioslaverc", "--group", "Proxy Settings", "--key", "ProxyType", "1"]
|
|
||||||
});
|
|
||||||
}
|
|
||||||
else if (type == "exceptions")
|
|
||||||
{
|
|
||||||
lstCmd.Add(new()
|
|
||||||
{
|
|
||||||
Cmd = cmd,
|
|
||||||
Arguments = ["--file", $"{configDir}/kioslaverc", "--group", "Proxy Settings", "--key", "NoProxyFor", host]
|
|
||||||
});
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
var type2 = type.Equals("https") ? "http" : type;
|
|
||||||
lstCmd.Add(new CmdItem()
|
|
||||||
{
|
|
||||||
Cmd = cmd,
|
|
||||||
Arguments = ["--file", $"{configDir}/kioslaverc", "--group", "Proxy Settings", "--key", $"{type}Proxy", $"{type2}://{host}:{port}"]
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
return lstCmd;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static List<CmdItem> GetSetCmd4Gnome(string type, string host, int port)
|
|
||||||
{
|
|
||||||
List<CmdItem> lstCmd = [];
|
|
||||||
|
|
||||||
if (type.IsNullOrEmpty())
|
|
||||||
{
|
|
||||||
lstCmd.Add(new()
|
|
||||||
{
|
|
||||||
Cmd = "gsettings",
|
|
||||||
Arguments = ["set", "org.gnome.system.proxy", "mode", "manual"]
|
|
||||||
});
|
|
||||||
}
|
|
||||||
else if (type == "exceptions")
|
|
||||||
{
|
|
||||||
lstCmd.Add(new()
|
|
||||||
{
|
|
||||||
Cmd = "gsettings",
|
|
||||||
Arguments = ["set", $"org.gnome.system.proxy", "ignore-hosts", JsonUtils.Serialize(host.Split(','), false)]
|
|
||||||
});
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
lstCmd.Add(new()
|
|
||||||
{
|
|
||||||
Cmd = "gsettings",
|
|
||||||
Arguments = ["set", $"org.gnome.system.proxy.{type}", "host", host]
|
|
||||||
});
|
|
||||||
|
|
||||||
lstCmd.Add(new()
|
|
||||||
{
|
|
||||||
Cmd = "gsettings",
|
|
||||||
Arguments = ["set", $"org.gnome.system.proxy.{type}", "port", $"{port}"]
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
return lstCmd;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static bool IsKde(out string configDir)
|
|
||||||
{
|
|
||||||
configDir = "/home";
|
|
||||||
var desktop = Environment.GetEnvironmentVariable("XDG_CURRENT_DESKTOP");
|
|
||||||
var desktop2 = Environment.GetEnvironmentVariable("XDG_SESSION_DESKTOP");
|
|
||||||
var isKde = string.Equals(desktop, "KDE", StringComparison.OrdinalIgnoreCase)
|
|
||||||
|| string.Equals(desktop, "plasma", StringComparison.OrdinalIgnoreCase)
|
|
||||||
|| string.Equals(desktop2, "KDE", StringComparison.OrdinalIgnoreCase)
|
|
||||||
|| string.Equals(desktop2, "plasma", StringComparison.OrdinalIgnoreCase);
|
|
||||||
if (isKde)
|
|
||||||
{
|
|
||||||
var homeDir = Environment.GetEnvironmentVariable("HOME");
|
|
||||||
if (homeDir != null)
|
|
||||||
{
|
|
||||||
configDir = Path.Combine(homeDir, ".config");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return isKde;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static string GetKdeVersion()
|
|
||||||
{
|
|
||||||
var ver = Environment.GetEnvironmentVariable("KDE_SESSION_VERSION") ?? "0";
|
|
||||||
return ver switch
|
|
||||||
{
|
|
||||||
"6" => "kwriteconfig6",
|
|
||||||
_ => "kwriteconfig5"
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,101 +1,38 @@
|
|||||||
namespace ServiceLib.Handler.SysProxy
|
namespace ServiceLib.Handler.SysProxy
|
||||||
{
|
{
|
||||||
public class ProxySettingOSX
|
public class ProxySettingOSX
|
||||||
{
|
{
|
||||||
/// <summary>
|
private static readonly string _proxySetFileName = $"{Global.ProxySetOSXShellFileName.Replace(Global.NamespaceSample, "")}.sh";
|
||||||
/// 应用接口类型
|
|
||||||
/// </summary>
|
|
||||||
private static readonly List<string> LstInterface = ["Ethernet", "Wi-Fi", "Thunderbolt Bridge", "USB 10/100/1000 LAN"];
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 代理类型,对应 http,https,socks
|
|
||||||
/// </summary>
|
|
||||||
private static readonly List<string> LstTypes = ["setwebproxy", "setsecurewebproxy", "setsocksfirewallproxy"];
|
|
||||||
|
|
||||||
public static async Task SetProxy(string host, int port, string exceptions)
|
public static async Task SetProxy(string host, int port, string exceptions)
|
||||||
{
|
{
|
||||||
var lstInterface = await GetListNetworkServices();
|
List<string> args = ["set", host, port.ToString()];
|
||||||
var lstCmd = GetSetCmds(lstInterface, host, port, exceptions);
|
if (exceptions.IsNotEmpty())
|
||||||
await ExecCmd(lstCmd);
|
{
|
||||||
|
args.AddRange(exceptions.Split(','));
|
||||||
|
}
|
||||||
|
|
||||||
|
await ExecCmd(args);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static async Task UnsetProxy()
|
public static async Task UnsetProxy()
|
||||||
{
|
{
|
||||||
var lstInterface = await GetListNetworkServices();
|
List<string> args = ["clear"];
|
||||||
var lstCmd = GetUnsetCmds(lstInterface);
|
await ExecCmd(args);
|
||||||
await ExecCmd(lstCmd);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private static async Task ExecCmd(List<CmdItem> lstCmd)
|
private static async Task ExecCmd(List<string> args)
|
||||||
{
|
{
|
||||||
foreach (var cmd in lstCmd)
|
var fileName = Utils.GetBinConfigPath(_proxySetFileName);
|
||||||
|
if (!File.Exists(fileName))
|
||||||
{
|
{
|
||||||
if (cmd is null || cmd.Cmd.IsNullOrEmpty() || cmd.Arguments is null)
|
var contents = EmbedUtils.GetEmbedText(Global.ProxySetOSXShellFileName);
|
||||||
{
|
await File.AppendAllTextAsync(fileName, contents);
|
||||||
continue;
|
|
||||||
|
await Utils.SetLinuxChmod(fileName);
|
||||||
}
|
}
|
||||||
|
|
||||||
await Task.Delay(10);
|
await Utils.GetCliWrapOutput(fileName, args);
|
||||||
await Utils.GetCliWrapOutput(cmd.Cmd, cmd.Arguments);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private static List<CmdItem> GetSetCmds(List<string> lstInterface, string host, int port, string exceptions)
|
|
||||||
{
|
|
||||||
List<CmdItem> lstCmd = [];
|
|
||||||
foreach (var interf in lstInterface)
|
|
||||||
{
|
|
||||||
foreach (var type in LstTypes)
|
|
||||||
{
|
|
||||||
lstCmd.Add(new CmdItem()
|
|
||||||
{
|
|
||||||
Cmd = "networksetup",
|
|
||||||
Arguments = [$"-{type}", interf, host, port.ToString()]
|
|
||||||
});
|
|
||||||
}
|
|
||||||
if (exceptions.IsNotEmpty())
|
|
||||||
{
|
|
||||||
List<string> args = [$"-setproxybypassdomains", interf];
|
|
||||||
args.AddRange(exceptions.Split(','));
|
|
||||||
lstCmd.Add(new CmdItem()
|
|
||||||
{
|
|
||||||
Cmd = "networksetup",
|
|
||||||
Arguments = args
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return lstCmd;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static List<CmdItem> GetUnsetCmds(List<string> lstInterface)
|
|
||||||
{
|
|
||||||
List<CmdItem> lstCmd = [];
|
|
||||||
foreach (var interf in lstInterface)
|
|
||||||
{
|
|
||||||
foreach (var type in LstTypes)
|
|
||||||
{
|
|
||||||
lstCmd.Add(new CmdItem()
|
|
||||||
{
|
|
||||||
Cmd = "networksetup",
|
|
||||||
Arguments = [$"-{type}state", interf, "off"]
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return lstCmd;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static async Task<List<string>> GetListNetworkServices()
|
|
||||||
{
|
|
||||||
var services = await Utils.GetListNetworkServices();
|
|
||||||
if (services.IsNullOrEmpty())
|
|
||||||
{
|
|
||||||
return LstInterface;
|
|
||||||
}
|
|
||||||
|
|
||||||
var lst = services.Split(Environment.NewLine).Where(t => t.Length > 0 && t.Contains('*') == false);
|
|
||||||
return lst.ToList();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -69,7 +69,7 @@ namespace ServiceLib.Handler.SysProxy
|
|||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch
|
||||||
{
|
{
|
||||||
SetProxyFallback(strProxy, exceptions, type);
|
SetProxyFallback(strProxy, exceptions, type);
|
||||||
return false;
|
return false;
|
||||||
@@ -176,7 +176,8 @@ namespace ServiceLib.Handler.SysProxy
|
|||||||
}
|
}
|
||||||
|
|
||||||
// FREE the data ASAP
|
// 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)
|
if (optionCount > 1)
|
||||||
{
|
{
|
||||||
Marshal.FreeHGlobal(options[1].m_Value.m_StringPtr); // release mem 1
|
Marshal.FreeHGlobal(options[1].m_Value.m_StringPtr); // release mem 1
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
using System.Net;
|
using System.Net;
|
||||||
using WebDav;
|
using WebDav;
|
||||||
|
|
||||||
namespace ServiceLib.Handler
|
namespace ServiceLib.Handler
|
||||||
@@ -61,7 +61,8 @@ namespace ServiceLib.Handler
|
|||||||
|
|
||||||
private async Task<bool> TryCreateDir()
|
private async Task<bool> TryCreateDir()
|
||||||
{
|
{
|
||||||
if (_client is null) return false;
|
if (_client is null)
|
||||||
|
return false;
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
var result2 = await _client.Mkcol(_webDir);
|
var result2 = await _client.Mkcol(_webDir);
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
namespace ServiceLib.Models
|
namespace ServiceLib.Models
|
||||||
{
|
{
|
||||||
[Serializable]
|
[Serializable]
|
||||||
public class CoreBasicItem
|
public class CoreBasicItem
|
||||||
@@ -156,7 +156,7 @@
|
|||||||
public int SpeedTestTimeout { get; set; }
|
public int SpeedTestTimeout { get; set; }
|
||||||
public string SpeedTestUrl { get; set; }
|
public string SpeedTestUrl { get; set; }
|
||||||
public string SpeedPingTestUrl { get; set; }
|
public string SpeedPingTestUrl { get; set; }
|
||||||
public int SpeedTestPageSize { get; set; }
|
public int MixedConcurrencyCount { get; set; }
|
||||||
}
|
}
|
||||||
|
|
||||||
[Serializable]
|
[Serializable]
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
namespace ServiceLib.Models
|
namespace ServiceLib.Models
|
||||||
{
|
{
|
||||||
[Serializable]
|
[Serializable]
|
||||||
public class CoreInfo
|
public class CoreInfo
|
||||||
@@ -16,6 +16,6 @@
|
|||||||
public string? DownloadUrlOSXArm64 { get; set; }
|
public string? DownloadUrlOSXArm64 { get; set; }
|
||||||
public string? Match { get; set; }
|
public string? Match { get; set; }
|
||||||
public string? VersionArg { get; set; }
|
public string? VersionArg { get; set; }
|
||||||
public bool RedirectInfo { get; set; }
|
public bool AbsolutePath { get; set; }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
using SQLite;
|
using SQLite;
|
||||||
|
|
||||||
namespace ServiceLib.Models
|
namespace ServiceLib.Models
|
||||||
{
|
{
|
||||||
@@ -11,5 +11,6 @@ namespace ServiceLib.Models
|
|||||||
public int Delay { get; set; }
|
public int Delay { get; set; }
|
||||||
public decimal Speed { get; set; }
|
public decimal Speed { get; set; }
|
||||||
public int Sort { get; set; }
|
public int Sort { get; set; }
|
||||||
|
public string? Message { get; set; }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
namespace ServiceLib.Models
|
namespace ServiceLib.Models
|
||||||
{
|
{
|
||||||
[Serializable]
|
[Serializable]
|
||||||
public class ServerTestItem
|
public class ServerTestItem
|
||||||
@@ -8,6 +8,6 @@
|
|||||||
public int Port { get; set; }
|
public int Port { get; set; }
|
||||||
public EConfigType ConfigType { get; set; }
|
public EConfigType ConfigType { get; set; }
|
||||||
public bool AllowTest { get; set; }
|
public bool AllowTest { get; set; }
|
||||||
public int Delay { get; set; }
|
public int QueueNum { get; set; }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -4,23 +4,15 @@ namespace ServiceLib.Models
|
|||||||
{
|
{
|
||||||
public class V2rayConfig
|
public class V2rayConfig
|
||||||
{
|
{
|
||||||
public string? remarks { get; set; }
|
|
||||||
|
|
||||||
public Log4Ray log { 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 object dns { get; set; }
|
||||||
|
public List<Inbounds4Ray> inbounds { get; set; }
|
||||||
|
public List<Outbounds4Ray> outbounds { get; set; }
|
||||||
public Routing4Ray routing { 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
|
public class Stats4Ray
|
||||||
|
|||||||
133
v2rayN/ServiceLib/Resx/ResUI.Designer.cs
generated
133
v2rayN/ServiceLib/Resx/ResUI.Designer.cs
generated
@@ -61,7 +61,7 @@ namespace ServiceLib.Resx {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 查找类似 Do you want to append rules? Choose yes to append, choose otherwise to replace 的本地化字符串。
|
/// 查找类似 Do you want to append rules? Choose yes to append, choose otherwise to replace. 的本地化字符串。
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public static string AddBatchRoutingRulesYesNo {
|
public static string AddBatchRoutingRulesYesNo {
|
||||||
get {
|
get {
|
||||||
@@ -196,7 +196,7 @@ namespace ServiceLib.Resx {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 查找类似 Failed to run Core, please see the log 的本地化字符串。
|
/// 查找类似 Failed to run Core, please check the prompt information 的本地化字符串。
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public static string FailedToRunCore {
|
public static string FailedToRunCore {
|
||||||
get {
|
get {
|
||||||
@@ -403,7 +403,7 @@ namespace ServiceLib.Resx {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 查找类似 Custom Icon 的本地化字符串。
|
/// 查找类似 Custom icon 的本地化字符串。
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public static string LvCustomIcon {
|
public static string LvCustomIcon {
|
||||||
get {
|
get {
|
||||||
@@ -610,7 +610,7 @@ namespace ServiceLib.Resx {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 查找类似 URL(Optional) 的本地化字符串。
|
/// 查找类似 URL (optional) 的本地化字符串。
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public static string LvUrl {
|
public static string LvUrl {
|
||||||
get {
|
get {
|
||||||
@@ -1006,7 +1006,7 @@ namespace ServiceLib.Resx {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 查找类似 One-click multi test Latency and speed (Ctrl+E) 的本地化字符串。
|
/// 查找类似 One-click multi-test latency and speed (Ctrl+E) 的本地化字符串。
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public static string menuMixedTestServer {
|
public static string menuMixedTestServer {
|
||||||
get {
|
get {
|
||||||
@@ -1311,6 +1311,15 @@ namespace ServiceLib.Resx {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 查找类似 Remove invalid by test results 的本地化字符串。
|
||||||
|
/// </summary>
|
||||||
|
public static string menuRemoveInvalidServerResult {
|
||||||
|
get {
|
||||||
|
return ResourceManager.GetString("menuRemoveInvalidServerResult", resourceCulture);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 查找类似 Remove selected servers (Delete) 的本地化字符串。
|
/// 查找类似 Remove selected servers (Delete) 的本地化字符串。
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@@ -1366,7 +1375,7 @@ namespace ServiceLib.Resx {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 查找类似 Set as active rule(Enter) 的本地化字符串。
|
/// 查找类似 Set as active rule (Enter) 的本地化字符串。
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public static string menuRoutingAdvancedSetDefault {
|
public static string menuRoutingAdvancedSetDefault {
|
||||||
get {
|
get {
|
||||||
@@ -1680,6 +1689,15 @@ namespace ServiceLib.Resx {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 查找类似 By test result 的本地化字符串。
|
||||||
|
/// </summary>
|
||||||
|
public static string menuTestServerResult {
|
||||||
|
get {
|
||||||
|
return ResourceManager.GetString("menuTestServerResult", resourceCulture);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 查找类似 {0} Website 的本地化字符串。
|
/// 查找类似 {0} Website 的本地化字符串。
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@@ -1689,15 +1707,6 @@ namespace ServiceLib.Resx {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 查找类似 Clear original subscription content 的本地化字符串。
|
|
||||||
/// </summary>
|
|
||||||
public static string MsgClearSubscription {
|
|
||||||
get {
|
|
||||||
return ResourceManager.GetString("MsgClearSubscription", resourceCulture);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 查找类似 Download GeoFile: {0} successfully 的本地化字符串。
|
/// 查找类似 Download GeoFile: {0} successfully 的本地化字符串。
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@@ -2004,6 +2013,15 @@ namespace ServiceLib.Resx {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 查找类似 Removed {0} invalid test results. 的本地化字符串。
|
||||||
|
/// </summary>
|
||||||
|
public static string RemoveInvalidServerResultTip {
|
||||||
|
get {
|
||||||
|
return ResourceManager.GetString("RemoveInvalidServerResultTip", resourceCulture);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 查找类似 Are you sure to remove the rules? 的本地化字符串。
|
/// 查找类似 Are you sure to remove the rules? 的本地化字符串。
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@@ -2094,6 +2112,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>
|
/// <summary>
|
||||||
/// 查找类似 Waiting for testing (press ESC to terminate)... 的本地化字符串。
|
/// 查找类似 Waiting for testing (press ESC to terminate)... 的本地化字符串。
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@@ -2195,7 +2222,7 @@ namespace ServiceLib.Resx {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 查找类似 AutoRefresh 的本地化字符串。
|
/// 查找类似 Auto refresh 的本地化字符串。
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public static string TbAutoRefresh {
|
public static string TbAutoRefresh {
|
||||||
get {
|
get {
|
||||||
@@ -2204,7 +2231,7 @@ namespace ServiceLib.Resx {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 查找类似 Auto ScrollToEnd 的本地化字符串。
|
/// 查找类似 Auto scroll to end 的本地化字符串。
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public static string TbAutoScrollToEnd {
|
public static string TbAutoScrollToEnd {
|
||||||
get {
|
get {
|
||||||
@@ -2294,7 +2321,7 @@ namespace ServiceLib.Resx {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 查找类似 Support DnsObject, Click to view the document 的本地化字符串。
|
/// 查找类似 Supports DnsObject; Click to view documentation 的本地化字符串。
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public static string TbDnsObjectDoc {
|
public static string TbDnsObjectDoc {
|
||||||
get {
|
get {
|
||||||
@@ -2384,7 +2411,7 @@ namespace ServiceLib.Resx {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 查找类似 Set directly by pressing the keyboard, take effect after restart 的本地化字符串。
|
/// 查找类似 Set directly by pressing the keyboard; Takes effect after restart 的本地化字符串。
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public static string TbGlobalHotkeySettingTip {
|
public static string TbGlobalHotkeySettingTip {
|
||||||
get {
|
get {
|
||||||
@@ -2663,7 +2690,7 @@ namespace ServiceLib.Resx {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <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>
|
/// </summary>
|
||||||
public static string TbRoutingTips {
|
public static string TbRoutingTips {
|
||||||
get {
|
get {
|
||||||
@@ -2771,7 +2798,7 @@ namespace ServiceLib.Resx {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 查找类似 Automatic update interval of Geo (hours) 的本地化字符串。
|
/// 查找类似 Automatic update interval for Geo files (hours) 的本地化字符串。
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public static string TbSettingsAutoUpdateInterval {
|
public static string TbSettingsAutoUpdateInterval {
|
||||||
get {
|
get {
|
||||||
@@ -2843,7 +2870,7 @@ namespace ServiceLib.Resx {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 查找类似 FontFamily(Require restart) 的本地化字符串。
|
/// 查找类似 Font family (requires restart) 的本地化字符串。
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public static string TbSettingsCurrentFontFamily {
|
public static string TbSettingsCurrentFontFamily {
|
||||||
get {
|
get {
|
||||||
@@ -2852,7 +2879,7 @@ namespace ServiceLib.Resx {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 查找类似 Install the font to the system and restart the settings 的本地化字符串。
|
/// 查找类似 Install the font to the system, select or fill in the font name, restart the settings 的本地化字符串。
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public static string TbSettingsCurrentFontFamilyLinuxTip {
|
public static string TbSettingsCurrentFontFamilyLinuxTip {
|
||||||
get {
|
get {
|
||||||
@@ -2861,7 +2888,7 @@ namespace ServiceLib.Resx {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <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>
|
/// </summary>
|
||||||
public static string TbSettingsCurrentFontFamilyTip {
|
public static string TbSettingsCurrentFontFamilyTip {
|
||||||
get {
|
get {
|
||||||
@@ -2915,7 +2942,7 @@ namespace ServiceLib.Resx {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 查找类似 Display real-time speed 的本地化字符串。
|
/// 查找类似 Display real-time speed (requires restart) 的本地化字符串。
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public static string TbSettingsDisplayRealTimeSpeed {
|
public static string TbSettingsDisplayRealTimeSpeed {
|
||||||
get {
|
get {
|
||||||
@@ -2951,7 +2978,7 @@ namespace ServiceLib.Resx {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 查找类似 Double-click server make active 的本地化字符串。
|
/// 查找类似 Double-clicking server makes it active 的本地化字符串。
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public static string TbSettingsDoubleClick2Activate {
|
public static string TbSettingsDoubleClick2Activate {
|
||||||
get {
|
get {
|
||||||
@@ -2960,7 +2987,7 @@ namespace ServiceLib.Resx {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 查找类似 Automatically adjust column width after updating subscription 的本地化字符串。
|
/// 查找类似 Automatically adjust column width after subscription update 的本地化字符串。
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public static string TbSettingsEnableAutoAdjustMainLvColWidth {
|
public static string TbSettingsEnableAutoAdjustMainLvColWidth {
|
||||||
get {
|
get {
|
||||||
@@ -2987,7 +3014,7 @@ namespace ServiceLib.Resx {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 查找类似 Enable Server Drag Drop Sort(Require restart) 的本地化字符串。
|
/// 查找类似 Enable sorting servers by drag-n-drop (requires restart) 的本地化字符串。
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public static string TbSettingsEnableDragDropSort {
|
public static string TbSettingsEnableDragDropSort {
|
||||||
get {
|
get {
|
||||||
@@ -3023,7 +3050,7 @@ namespace ServiceLib.Resx {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 查找类似 Enable hardware acceleration(Require restart) 的本地化字符串。
|
/// 查找类似 Enable hardware acceleration (requires restart) 的本地化字符串。
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public static string TbSettingsEnableHWA {
|
public static string TbSettingsEnableHWA {
|
||||||
get {
|
get {
|
||||||
@@ -3059,7 +3086,7 @@ namespace ServiceLib.Resx {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <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>
|
/// </summary>
|
||||||
public static string TbSettingsExceptionTip {
|
public static string TbSettingsExceptionTip {
|
||||||
get {
|
get {
|
||||||
@@ -3068,7 +3095,7 @@ namespace ServiceLib.Resx {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <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>
|
/// </summary>
|
||||||
public static string TbSettingsExceptionTip2 {
|
public static string TbSettingsExceptionTip2 {
|
||||||
get {
|
get {
|
||||||
@@ -3103,15 +3130,6 @@ namespace ServiceLib.Resx {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 查找类似 HTTP Port 的本地化字符串。
|
|
||||||
/// </summary>
|
|
||||||
public static string TbSettingsHttpPort {
|
|
||||||
get {
|
|
||||||
return ResourceManager.GetString("TbSettingsHttpPort", resourceCulture);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 查找类似 Hysteria Max bandwidth (Up/Dw) 的本地化字符串。
|
/// 查找类似 Hysteria Max bandwidth (Up/Dw) 的本地化字符串。
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@@ -3122,7 +3140,7 @@ namespace ServiceLib.Resx {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 查找类似 Keep older when deduplication 的本地化字符串。
|
/// 查找类似 Keep the older when de-duplicating 的本地化字符串。
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public static string TbSettingsKeepOlderDedupl {
|
public static string TbSettingsKeepOlderDedupl {
|
||||||
get {
|
get {
|
||||||
@@ -3167,7 +3185,7 @@ namespace ServiceLib.Resx {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 查找类似 The password is encrypted and stored only in local files. 的本地化字符串。
|
/// 查找类似 The password is encrypted and stored only in local files 的本地化字符串。
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public static string TbSettingsLinuxSudoPasswordTip {
|
public static string TbSettingsLinuxSudoPasswordTip {
|
||||||
get {
|
get {
|
||||||
@@ -3203,7 +3221,7 @@ namespace ServiceLib.Resx {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 查找类似 Main layout orientation(Require restart) 的本地化字符串。
|
/// 查找类似 Main layout orientation (requires restart) 的本地化字符串。
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public static string TbSettingsMainGirdOrientation {
|
public static string TbSettingsMainGirdOrientation {
|
||||||
get {
|
get {
|
||||||
@@ -3211,6 +3229,15 @@ namespace ServiceLib.Resx {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 查找类似 The number of concurrent during multi-test 的本地化字符串。
|
||||||
|
/// </summary>
|
||||||
|
public static string TbSettingsMixedConcurrencyCount {
|
||||||
|
get {
|
||||||
|
return ResourceManager.GetString("TbSettingsMixedConcurrencyCount", resourceCulture);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 查找类似 sing-box Mux Protocol 的本地化字符串。
|
/// 查找类似 sing-box Mux Protocol 的本地化字符串。
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@@ -3346,15 +3373,6 @@ namespace ServiceLib.Resx {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 查找类似 Number per time for auto batch during speedtest(max 1000) 的本地化字符串。
|
|
||||||
/// </summary>
|
|
||||||
public static string TbSettingsSpeedTestPageSize {
|
|
||||||
get {
|
|
||||||
return ResourceManager.GetString("TbSettingsSpeedTestPageSize", resourceCulture);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 查找类似 SpeedTest Single Timeout Value 的本地化字符串。
|
/// 查找类似 SpeedTest Single Timeout Value 的本地化字符串。
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@@ -3401,7 +3419,7 @@ namespace ServiceLib.Resx {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 查找类似 Enable traffic statistics (Require restart) 的本地化字符串。
|
/// 查找类似 Enable traffic statistics (requires restart) 的本地化字符串。
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public static string TbSettingsStatistics {
|
public static string TbSettingsStatistics {
|
||||||
get {
|
get {
|
||||||
@@ -3868,15 +3886,6 @@ namespace ServiceLib.Resx {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 查找类似 You are currently running a standalone package, please manually download the SelfContained.7z file to unzip and overwrite it! 的本地化字符串。
|
|
||||||
/// </summary>
|
|
||||||
public static string UpdateStandalonePackageTip {
|
|
||||||
get {
|
|
||||||
return ResourceManager.GetString("UpdateStandalonePackageTip", resourceCulture);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 查找类似 UpgradeApp does not exist 的本地化字符串。
|
/// 查找类似 UpgradeApp does not exist 的本地化字符串。
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<root>
|
<root>
|
||||||
<!--
|
<!--
|
||||||
Microsoft ResX Schema
|
Microsoft ResX Schema
|
||||||
@@ -210,9 +210,6 @@
|
|||||||
<data name="LvTransportProtocol" xml:space="preserve">
|
<data name="LvTransportProtocol" xml:space="preserve">
|
||||||
<value>جابجایی</value>
|
<value>جابجایی</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="MsgClearSubscription" xml:space="preserve">
|
|
||||||
<value>محتوای اشتراک اصلی را پاک کنید</value>
|
|
||||||
</data>
|
|
||||||
<data name="MsgDownloadV2rayCoreSuccessfully" xml:space="preserve">
|
<data name="MsgDownloadV2rayCoreSuccessfully" xml:space="preserve">
|
||||||
<value>دانلود Core با موفقیت</value>
|
<value>دانلود Core با موفقیت</value>
|
||||||
</data>
|
</data>
|
||||||
@@ -344,10 +341,10 @@
|
|||||||
<value>لطفاً DNS سفارشی صحیح را پر کنید</value>
|
<value>لطفاً DNS سفارشی صحیح را پر کنید</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="TransportPathTip1" xml:space="preserve">
|
<data name="TransportPathTip1" xml:space="preserve">
|
||||||
<value>*ws path</value>
|
<value>* مسیر ws</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="TransportPathTip2" xml:space="preserve">
|
<data name="TransportPathTip2" xml:space="preserve">
|
||||||
<value>*h2 path</value>
|
<value>* مسیر h2</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="TransportPathTip3" xml:space="preserve">
|
<data name="TransportPathTip3" xml:space="preserve">
|
||||||
<value>*QUIC key/Kcp seed</value>
|
<value>*QUIC key/Kcp seed</value>
|
||||||
@@ -356,13 +353,13 @@
|
|||||||
<value>*grpc serviceName</value>
|
<value>*grpc serviceName</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="TransportRequestHostTip1" xml:space="preserve">
|
<data name="TransportRequestHostTip1" xml:space="preserve">
|
||||||
<value>*http host Separated by commas (,)</value>
|
<value>*هاست http جدا شده با کاما (،)</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="TransportRequestHostTip2" xml:space="preserve">
|
<data name="TransportRequestHostTip2" xml:space="preserve">
|
||||||
<value>*ws host</value>
|
<value>*هاست ws</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="TransportRequestHostTip3" xml:space="preserve">
|
<data name="TransportRequestHostTip3" xml:space="preserve">
|
||||||
<value>*h2 host Separated by commas (,)</value>
|
<value>*هاست h2 با کاما (،) جدا شده است</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="TransportRequestHostTip4" xml:space="preserve">
|
<data name="TransportRequestHostTip4" xml:space="preserve">
|
||||||
<value>*QUIC securty</value>
|
<value>*QUIC securty</value>
|
||||||
@@ -377,7 +374,7 @@
|
|||||||
<value>*QUIC camouflage type</value>
|
<value>*QUIC camouflage type</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="TransportHeaderTypeTip4" xml:space="preserve">
|
<data name="TransportHeaderTypeTip4" xml:space="preserve">
|
||||||
<value>*grpc mode</value>
|
<value>*حالت grpc</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="LvTLS" xml:space="preserve">
|
<data name="LvTLS" xml:space="preserve">
|
||||||
<value>TLS</value>
|
<value>TLS</value>
|
||||||
@@ -404,7 +401,7 @@
|
|||||||
<value>درحال تست کردن...</value>
|
<value>درحال تست کردن...</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="LabLAN" xml:space="preserve">
|
<data name="LabLAN" xml:space="preserve">
|
||||||
<value>LAN</value>
|
<value>شبکه محلی</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="LabLocal" xml:space="preserve">
|
<data name="LabLocal" xml:space="preserve">
|
||||||
<value>محلی</value>
|
<value>محلی</value>
|
||||||
@@ -683,7 +680,7 @@
|
|||||||
<value>راه اندازی مخفی کردن خودکار</value>
|
<value>راه اندازی مخفی کردن خودکار</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="TbSettingsAutoUpdateInterval" xml:space="preserve">
|
<data name="TbSettingsAutoUpdateInterval" xml:space="preserve">
|
||||||
<value>فاصله به روز رسانی خودکار و Geo (ساعت)</value>
|
<value>فاصله به روز رسانی خودکار برای فایل های Geo (ساعت)</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="TbSettingsCore" xml:space="preserve">
|
<data name="TbSettingsCore" xml:space="preserve">
|
||||||
<value>هسته: تنظیمات اولیه</value>
|
<value>هسته: تنظیمات اولیه</value>
|
||||||
@@ -704,7 +701,7 @@
|
|||||||
<value>Outbound Freedom domainStrategy</value>
|
<value>Outbound Freedom domainStrategy</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="TbSettingsEnableAutoAdjustMainLvColWidth" xml:space="preserve">
|
<data name="TbSettingsEnableAutoAdjustMainLvColWidth" xml:space="preserve">
|
||||||
<value>پس از بهروزرسانی اشتراک، عرض ستون را به صورت خودکار تنظیم شود</value>
|
<value>پس از بهروزرسانی اشتراک، عرض ستون به صورت خودکار تنظیم شود</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="TbSettingsEnableCheckPreReleaseUpdate" xml:space="preserve">
|
<data name="TbSettingsEnableCheckPreReleaseUpdate" xml:space="preserve">
|
||||||
<value>به روز رسانی های پیش از انتشار را بررسی شود</value>
|
<value>به روز رسانی های پیش از انتشار را بررسی شود</value>
|
||||||
@@ -713,16 +710,13 @@
|
|||||||
<value>استثنا</value>
|
<value>استثنا</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="TbSettingsExceptionTip" xml:space="preserve">
|
<data name="TbSettingsExceptionTip" xml:space="preserve">
|
||||||
<value>استثنا: از سرور پروکسی برای آدرس هایی که با شروع می شوند استفاده نکنید، از نقطه ویرگول (;) استفاده کنید.</value>
|
<value>استثناها: از سرور پروکسی برای آدرس هایی که با موارد زیر شروع می شوند استفاده نکنید. برای جدا کردن ورودی ها از نقطه ویرگول (;) استفاده کنید.</value>
|
||||||
</data>
|
|
||||||
<data name="TbSettingsHttpPort" xml:space="preserve">
|
|
||||||
<value>پورت Http</value>
|
|
||||||
</data>
|
</data>
|
||||||
<data name="TbSettingsDisplayRealTimeSpeed" xml:space="preserve">
|
<data name="TbSettingsDisplayRealTimeSpeed" xml:space="preserve">
|
||||||
<value>Display real-time speed</value>
|
<value>نمایش سرعت واقعی (نیاز به راه اندازی مجدد)</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="TbSettingsKeepOlderDedupl" xml:space="preserve">
|
<data name="TbSettingsKeepOlderDedupl" xml:space="preserve">
|
||||||
<value>هنگام کپی برداری، نگه داری قدیمی تر ها</value>
|
<value>هنگام حذف کپی، قدیمی تر را نگه دارید</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="TbSettingsLogEnabled" xml:space="preserve">
|
<data name="TbSettingsLogEnabled" xml:space="preserve">
|
||||||
<value>ثبت گزارش های محلی</value>
|
<value>ثبت گزارش های محلی</value>
|
||||||
@@ -755,7 +749,7 @@
|
|||||||
<value>درهنگام راه ائدازی شروع شود</value>
|
<value>درهنگام راه ائدازی شروع شود</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="TbSettingsStatistics" xml:space="preserve">
|
<data name="TbSettingsStatistics" xml:space="preserve">
|
||||||
<value>فعال کردن آمار (نیاز به راه اندازی مجدد)</value>
|
<value>فعال کردن آمار ترافیک (نیاز به راه اندازی مجدد)</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="TbSettingsSubConvert" xml:space="preserve">
|
<data name="TbSettingsSubConvert" xml:space="preserve">
|
||||||
<value>آدرس اینترنتی تبدیل اشتراک</value>
|
<value>آدرس اینترنتی تبدیل اشتراک</value>
|
||||||
@@ -863,7 +857,7 @@
|
|||||||
<value>لیست مجموعه قوانین از پیش تعریف شده</value>
|
<value>لیست مجموعه قوانین از پیش تعریف شده</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="TbRoutingTips" xml:space="preserve">
|
<data name="TbRoutingTips" xml:space="preserve">
|
||||||
<value>*قوانین را تنظیم کنید که با کاما از هم جدا شده اند (,); کاما در حالت عادی با <COMMA></value>
|
<value>*قوانین را با کاما (,) جدا کنید. برای کاما به معنای واقعی کلمه از <COMMA>; پیشوند # برای نادیده گرفتن یک قانون</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="menuImportRulesFromClipboard" xml:space="preserve">
|
<data name="menuImportRulesFromClipboard" xml:space="preserve">
|
||||||
<value>وارد کردن قوانین از کلیپ بورد</value>
|
<value>وارد کردن قوانین از کلیپ بورد</value>
|
||||||
@@ -899,7 +893,7 @@
|
|||||||
<value>مستندات شی قانون</value>
|
<value>مستندات شی قانون</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="TbDnsObjectDoc" xml:space="preserve">
|
<data name="TbDnsObjectDoc" xml:space="preserve">
|
||||||
<value>پشتیبانی از DnsObject</value>
|
<value>پشتیبانی از DnsObject. برای مشاهده مستندات کلیک کنید</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="SubUrlTips" xml:space="preserve">
|
<data name="SubUrlTips" xml:space="preserve">
|
||||||
<value>گروه لطفا اینجا را خالی بگذارید</value>
|
<value>گروه لطفا اینجا را خالی بگذارید</value>
|
||||||
@@ -950,7 +944,7 @@
|
|||||||
<value>این پارامتر فقط برای tcp/http و ws معتبر است</value>
|
<value>این پارامتر فقط برای tcp/http و ws معتبر است</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="TbSettingsEnableHWA" xml:space="preserve">
|
<data name="TbSettingsEnableHWA" xml:space="preserve">
|
||||||
<value>فعال سازی شتاب دهنده سختافزاری (نیاز به راهاندازی مجدد)</value>
|
<value>فعال سازی شتاب دهنده سخت افزاری (نیاز به راهاندازی مجدد)</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="TbSettingsEnableCacheFile4Sbox" xml:space="preserve">
|
<data name="TbSettingsEnableCacheFile4Sbox" xml:space="preserve">
|
||||||
<value>فعال کردن کش فایل مجموعه قوانین برای sing-box</value>
|
<value>فعال کردن کش فایل مجموعه قوانین برای sing-box</value>
|
||||||
@@ -1051,9 +1045,6 @@
|
|||||||
<data name="menuShowOrHideMainWindow" xml:space="preserve">
|
<data name="menuShowOrHideMainWindow" xml:space="preserve">
|
||||||
<value>نمایش یا پنهان کردن پنجره اصلی</value>
|
<value>نمایش یا پنهان کردن پنجره اصلی</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="UpdateStandalonePackageTip" xml:space="preserve">
|
|
||||||
<value>شما در حال حاضر در حال اجرای یک بسته مستقل هستید، لطفاً فایل SelfContained.7z را به صورت دستی دانلود کنید تا آن را از حالت فشرده خارج کرده و بازنویسی کنید!</value>
|
|
||||||
</data>
|
|
||||||
<data name="TbPreSocksPort4Sub" xml:space="preserve">
|
<data name="TbPreSocksPort4Sub" xml:space="preserve">
|
||||||
<value>پیکربندی سفارشی ساکس پورت</value>
|
<value>پیکربندی سفارشی ساکس پورت</value>
|
||||||
</data>
|
</data>
|
||||||
@@ -1208,7 +1199,7 @@
|
|||||||
<value>انتقال به گروه</value>
|
<value>انتقال به گروه</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="TbSettingsEnableDragDropSort" xml:space="preserve">
|
<data name="TbSettingsEnableDragDropSort" xml:space="preserve">
|
||||||
<value>فعال کردن مرتب سازی با کشیدن سرور (نیاز به راه اندازی مجدد)</value>
|
<value>فعال کردن مرتبسازی سرورها با کشیدن و رها کردن (نیاز به راهاندازی مجدد)</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="TbAutoRefresh" xml:space="preserve">
|
<data name="TbAutoRefresh" xml:space="preserve">
|
||||||
<value>بازخوانی خودکار</value>
|
<value>بازخوانی خودکار</value>
|
||||||
@@ -1220,7 +1211,7 @@
|
|||||||
<value>ویرایش سرور (Ctrl+D)</value>
|
<value>ویرایش سرور (Ctrl+D)</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="TbSettingsDoubleClick2Activate" xml:space="preserve">
|
<data name="TbSettingsDoubleClick2Activate" xml:space="preserve">
|
||||||
<value>روی server make active دوبار کلیک کنید</value>
|
<value>دوبار کلیک کردن سرور باعث فعال شدن آن می شود</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="SpeedtestingCompleted" xml:space="preserve">
|
<data name="SpeedtestingCompleted" xml:space="preserve">
|
||||||
<value>تست تکمیل شد</value>
|
<value>تست تکمیل شد</value>
|
||||||
@@ -1232,7 +1223,7 @@
|
|||||||
<value>FontFamily (نیاز به راه اندازی مجدد)</value>
|
<value>FontFamily (نیاز به راه اندازی مجدد)</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="TbSettingsCurrentFontFamilyTip" xml:space="preserve">
|
<data name="TbSettingsCurrentFontFamilyTip" xml:space="preserve">
|
||||||
<value>فایل TTF/TTC فونت را در دایرکتوری guiFonts کپی کنید، تنظیمات را مجددا راه اندازی کنید</value>
|
<value>فایل TTF/TTC فونت را در دایرکتوری guiFonts کپی کنید. پنجره تنظیمات را دوباره باز کنید</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="TbSettingsSocksPortTip" xml:space="preserve">
|
<data name="TbSettingsSocksPortTip" xml:space="preserve">
|
||||||
<value>پورت Pac = +3; پورت Xray API = +4; پورت mihomo API = +5;</value>
|
<value>پورت Pac = +3; پورت Xray API = +4; پورت mihomo API = +5;</value>
|
||||||
@@ -1372,11 +1363,11 @@
|
|||||||
<data name="TbSettingsHide2TrayWhenClose" xml:space="preserve">
|
<data name="TbSettingsHide2TrayWhenClose" xml:space="preserve">
|
||||||
<value>هنگام بستن پنجره در سینی پنهان شوید</value>
|
<value>هنگام بستن پنجره در سینی پنهان شوید</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="TbSettingsSpeedTestPageSize" xml:space="preserve">
|
<data name="TbSettingsMixedConcurrencyCount" xml:space="preserve">
|
||||||
<value>تعداد در هر زمان برای دسته خودکار در طول تست سرعت (حداکثر 1000)</value>
|
<value>The number of concurrent during multi-test</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="TbSettingsExceptionTip2" xml:space="preserve">
|
<data name="TbSettingsExceptionTip2" xml:space="preserve">
|
||||||
<value>استثنا:از سرور پروکسی برای آدرس ها، با کاما (،) استفاده نکنید</value>
|
<value>موارد استثنا: از سرور پروکسی برای آدرس های زیر استفاده نکنید. برای جدا کردن ورودی ها از کاما (،) استفاده کنید.</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="TbSettingsDestOverride" xml:space="preserve">
|
<data name="TbSettingsDestOverride" xml:space="preserve">
|
||||||
<value>نوع Sniffing</value>
|
<value>نوع Sniffing</value>
|
||||||
@@ -1393,4 +1384,16 @@
|
|||||||
<data name="menuCopyProxyCmdToClipboard" xml:space="preserve">
|
<data name="menuCopyProxyCmdToClipboard" xml:space="preserve">
|
||||||
<value>کپی کردن دستور پروکسی در کلیپ بورد</value>
|
<value>کپی کردن دستور پروکسی در کلیپ بورد</value>
|
||||||
</data>
|
</data>
|
||||||
|
<data name="SpeedtestingTestFailedPart" xml:space="preserve">
|
||||||
|
<value>شروع آزمایش مجدد قطعات ناموفق، {0} باقی مانده است. برای خاتمه ESC را فشار دهید...</value>
|
||||||
|
</data>
|
||||||
|
<data name="menuTestServerResult" xml:space="preserve">
|
||||||
|
<value>By test result</value>
|
||||||
|
</data>
|
||||||
|
<data name="menuRemoveInvalidServerResult" xml:space="preserve">
|
||||||
|
<value>Remove invalid by test results</value>
|
||||||
|
</data>
|
||||||
|
<data name="RemoveInvalidServerResultTip" xml:space="preserve">
|
||||||
|
<value>Removed {0} invalid test results.</value>
|
||||||
|
</data>
|
||||||
</root>
|
</root>
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<root>
|
<root>
|
||||||
<!--
|
<!--
|
||||||
Microsoft ResX Schema
|
Microsoft ResX Schema
|
||||||
@@ -210,9 +210,6 @@
|
|||||||
<data name="LvTransportProtocol" xml:space="preserve">
|
<data name="LvTransportProtocol" xml:space="preserve">
|
||||||
<value>Szállítás</value>
|
<value>Szállítás</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="MsgClearSubscription" xml:space="preserve">
|
|
||||||
<value>Eredeti előfizetési tartalom törlése</value>
|
|
||||||
</data>
|
|
||||||
<data name="MsgDownloadV2rayCoreSuccessfully" xml:space="preserve">
|
<data name="MsgDownloadV2rayCoreSuccessfully" xml:space="preserve">
|
||||||
<value>A Core letöltése sikerült</value>
|
<value>A Core letöltése sikerült</value>
|
||||||
</data>
|
</data>
|
||||||
@@ -715,9 +712,6 @@
|
|||||||
<data name="TbSettingsExceptionTip" xml:space="preserve">
|
<data name="TbSettingsExceptionTip" xml:space="preserve">
|
||||||
<value>Kivétel. Ne használjon proxy szervert a címek esetében, amelyek pontosan itt kezdődnek, használjon pontosvesszőt (;)</value>
|
<value>Kivétel. Ne használjon proxy szervert a címek esetében, amelyek pontosan itt kezdődnek, használjon pontosvesszőt (;)</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="TbSettingsHttpPort" xml:space="preserve">
|
|
||||||
<value>HTTP Port</value>
|
|
||||||
</data>
|
|
||||||
<data name="TbSettingsDisplayRealTimeSpeed" xml:space="preserve">
|
<data name="TbSettingsDisplayRealTimeSpeed" xml:space="preserve">
|
||||||
<value>Display real-time speed</value>
|
<value>Display real-time speed</value>
|
||||||
</data>
|
</data>
|
||||||
@@ -1255,9 +1249,6 @@
|
|||||||
<data name="menuShowOrHideMainWindow" xml:space="preserve">
|
<data name="menuShowOrHideMainWindow" xml:space="preserve">
|
||||||
<value>Fő ablak megjelenítése vagy elrejtése</value>
|
<value>Fő ablak megjelenítése vagy elrejtése</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="UpdateStandalonePackageTip" xml:space="preserve">
|
|
||||||
<value>Jelenleg egy önálló csomagot futtatsz, kérlek, töltsd le manuálisan a SelfContained.7z fájlt, bontsd ki és írd felül!</value>
|
|
||||||
</data>
|
|
||||||
<data name="TbPreSocksPort4Sub" xml:space="preserve">
|
<data name="TbPreSocksPort4Sub" xml:space="preserve">
|
||||||
<value>Testreszabott konfigurációs socks port</value>
|
<value>Testreszabott konfigurációs socks port</value>
|
||||||
</data>
|
</data>
|
||||||
@@ -1372,8 +1363,8 @@
|
|||||||
<data name="TbSettingsHide2TrayWhenClose" xml:space="preserve">
|
<data name="TbSettingsHide2TrayWhenClose" xml:space="preserve">
|
||||||
<value>Minimálás tálcára ablak zárásakor</value>
|
<value>Minimálás tálcára ablak zárásakor</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="TbSettingsSpeedTestPageSize" xml:space="preserve">
|
<data name="TbSettingsMixedConcurrencyCount" xml:space="preserve">
|
||||||
<value>Szám / időszak az automatikus batch során a sebességvizsgálat során (maximum 1000)</value>
|
<value>The number of concurrent during multi-test</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="TbSettingsExceptionTip2" xml:space="preserve">
|
<data name="TbSettingsExceptionTip2" xml:space="preserve">
|
||||||
<value>Kivétel. Ne használj proxy szervert a címeknél, évezz pontosvesszőt (,)</value>
|
<value>Kivétel. Ne használj proxy szervert a címeknél, évezz pontosvesszőt (,)</value>
|
||||||
@@ -1393,4 +1384,16 @@
|
|||||||
<data name="menuCopyProxyCmdToClipboard" xml:space="preserve">
|
<data name="menuCopyProxyCmdToClipboard" xml:space="preserve">
|
||||||
<value>Copy proxy command to clipboard</value>
|
<value>Copy proxy command to clipboard</value>
|
||||||
</data>
|
</data>
|
||||||
|
<data name="SpeedtestingTestFailedPart" xml:space="preserve">
|
||||||
|
<value>Starting retesting failed parts, {0} remaining. Press ESC to terminate...</value>
|
||||||
|
</data>
|
||||||
|
<data name="menuTestServerResult" xml:space="preserve">
|
||||||
|
<value>By test result</value>
|
||||||
|
</data>
|
||||||
|
<data name="menuRemoveInvalidServerResult" xml:space="preserve">
|
||||||
|
<value>Remove invalid by test results</value>
|
||||||
|
</data>
|
||||||
|
<data name="RemoveInvalidServerResultTip" xml:space="preserve">
|
||||||
|
<value>Removed {0} invalid test results.</value>
|
||||||
|
</data>
|
||||||
</root>
|
</root>
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<root>
|
<root>
|
||||||
<!--
|
<!--
|
||||||
Microsoft ResX Schema
|
Microsoft ResX Schema
|
||||||
@@ -210,9 +210,6 @@
|
|||||||
<data name="LvTransportProtocol" xml:space="preserve">
|
<data name="LvTransportProtocol" xml:space="preserve">
|
||||||
<value>Transport</value>
|
<value>Transport</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="MsgClearSubscription" xml:space="preserve">
|
|
||||||
<value>Clear original subscription content</value>
|
|
||||||
</data>
|
|
||||||
<data name="MsgDownloadV2rayCoreSuccessfully" xml:space="preserve">
|
<data name="MsgDownloadV2rayCoreSuccessfully" xml:space="preserve">
|
||||||
<value>Download Core successfully</value>
|
<value>Download Core successfully</value>
|
||||||
</data>
|
</data>
|
||||||
@@ -320,7 +317,7 @@
|
|||||||
<value>Remarks</value>
|
<value>Remarks</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="LvUrl" xml:space="preserve">
|
<data name="LvUrl" xml:space="preserve">
|
||||||
<value>URL(Optional)</value>
|
<value>URL (optional)</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="LvCount" xml:space="preserve">
|
<data name="LvCount" xml:space="preserve">
|
||||||
<value>Count</value>
|
<value>Count</value>
|
||||||
@@ -329,7 +326,7 @@
|
|||||||
<value>Please fill in the URL</value>
|
<value>Please fill in the URL</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="AddBatchRoutingRulesYesNo" xml:space="preserve">
|
<data name="AddBatchRoutingRulesYesNo" xml:space="preserve">
|
||||||
<value>Do you want to append rules? Choose yes to append, choose otherwise to replace</value>
|
<value>Do you want to append rules? Choose yes to append, choose otherwise to replace.</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="MsgDownloadGeoFileSuccessfully" xml:space="preserve">
|
<data name="MsgDownloadGeoFileSuccessfully" xml:space="preserve">
|
||||||
<value>Download GeoFile: {0} successfully</value>
|
<value>Download GeoFile: {0} successfully</value>
|
||||||
@@ -338,7 +335,7 @@
|
|||||||
<value>Information</value>
|
<value>Information</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="LvCustomIcon" xml:space="preserve">
|
<data name="LvCustomIcon" xml:space="preserve">
|
||||||
<value>Custom Icon</value>
|
<value>Custom icon</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="FillCorrectDNSText" xml:space="preserve">
|
<data name="FillCorrectDNSText" xml:space="preserve">
|
||||||
<value>Please fill in the correct custom DNS</value>
|
<value>Please fill in the correct custom DNS</value>
|
||||||
@@ -683,7 +680,7 @@
|
|||||||
<value>Auto hide startup</value>
|
<value>Auto hide startup</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="TbSettingsAutoUpdateInterval" xml:space="preserve">
|
<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>
|
||||||
<data name="TbSettingsCore" xml:space="preserve">
|
<data name="TbSettingsCore" xml:space="preserve">
|
||||||
<value>Core: basic settings</value>
|
<value>Core: basic settings</value>
|
||||||
@@ -704,7 +701,7 @@
|
|||||||
<value>Outbound Freedom domainStrategy</value>
|
<value>Outbound Freedom domainStrategy</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="TbSettingsEnableAutoAdjustMainLvColWidth" xml:space="preserve">
|
<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>
|
||||||
<data name="TbSettingsEnableCheckPreReleaseUpdate" xml:space="preserve">
|
<data name="TbSettingsEnableCheckPreReleaseUpdate" xml:space="preserve">
|
||||||
<value>Check for pre-release updates</value>
|
<value>Check for pre-release updates</value>
|
||||||
@@ -713,16 +710,13 @@
|
|||||||
<value>Exception</value>
|
<value>Exception</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="TbSettingsExceptionTip" xml:space="preserve">
|
<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>
|
||||||
<data name="TbSettingsDisplayRealTimeSpeed" xml:space="preserve">
|
<data name="TbSettingsDisplayRealTimeSpeed" xml:space="preserve">
|
||||||
<value>Display real-time speed (Require restart)</value>
|
<value>Display real-time speed (requires restart)</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="TbSettingsKeepOlderDedupl" xml:space="preserve">
|
<data name="TbSettingsKeepOlderDedupl" xml:space="preserve">
|
||||||
<value>Keep older when deduplication</value>
|
<value>Keep the older when de-duplicating</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="TbSettingsLogEnabled" xml:space="preserve">
|
<data name="TbSettingsLogEnabled" xml:space="preserve">
|
||||||
<value>Enable Log</value>
|
<value>Enable Log</value>
|
||||||
@@ -755,7 +749,7 @@
|
|||||||
<value>Start on boot</value>
|
<value>Start on boot</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="TbSettingsStatistics" xml:space="preserve">
|
<data name="TbSettingsStatistics" xml:space="preserve">
|
||||||
<value>Enable traffic statistics (Require restart)</value>
|
<value>Enable traffic statistics (requires restart)</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="TbSettingsSubConvert" xml:space="preserve">
|
<data name="TbSettingsSubConvert" xml:space="preserve">
|
||||||
<value>Subscription conversion URL</value>
|
<value>Subscription conversion URL</value>
|
||||||
@@ -785,7 +779,7 @@
|
|||||||
<value>Global Hotkey Settings</value>
|
<value>Global Hotkey Settings</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="TbGlobalHotkeySettingTip" xml:space="preserve">
|
<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>
|
||||||
<data name="TbNotChangeSystemProxy" xml:space="preserve">
|
<data name="TbNotChangeSystemProxy" xml:space="preserve">
|
||||||
<value>Do not change system proxy</value>
|
<value>Do not change system proxy</value>
|
||||||
@@ -842,7 +836,7 @@
|
|||||||
<value>Remove selected (Delete)</value>
|
<value>Remove selected (Delete)</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="menuRoutingAdvancedSetDefault" xml:space="preserve">
|
<data name="menuRoutingAdvancedSetDefault" xml:space="preserve">
|
||||||
<value>Set as active rule(Enter)</value>
|
<value>Set as active rule (Enter)</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="TbdomainMatcher" xml:space="preserve">
|
<data name="TbdomainMatcher" xml:space="preserve">
|
||||||
<value>Domain Matcher</value>
|
<value>Domain Matcher</value>
|
||||||
@@ -863,7 +857,7 @@
|
|||||||
<value>Pre-defined Rule Set List</value>
|
<value>Pre-defined Rule Set List</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="TbRoutingTips" xml:space="preserve">
|
<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>
|
||||||
<data name="menuImportRulesFromClipboard" xml:space="preserve">
|
<data name="menuImportRulesFromClipboard" xml:space="preserve">
|
||||||
<value>Import Rules From Clipboard</value>
|
<value>Import Rules From Clipboard</value>
|
||||||
@@ -899,7 +893,7 @@
|
|||||||
<value>Ruleobject Doc</value>
|
<value>Ruleobject Doc</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="TbDnsObjectDoc" xml:space="preserve">
|
<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>
|
||||||
<data name="SubUrlTips" xml:space="preserve">
|
<data name="SubUrlTips" xml:space="preserve">
|
||||||
<value>For group please leave blank here</value>
|
<value>For group please leave blank here</value>
|
||||||
@@ -917,7 +911,7 @@
|
|||||||
<value>Do not use proxy servers for local (intranet) addresses</value>
|
<value>Do not use proxy servers for local (intranet) addresses</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="menuMixedTestServer" xml:space="preserve">
|
<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>
|
||||||
<data name="LvTestDelay" xml:space="preserve">
|
<data name="LvTestDelay" xml:space="preserve">
|
||||||
<value>Delay(ms)</value>
|
<value>Delay(ms)</value>
|
||||||
@@ -926,7 +920,7 @@
|
|||||||
<value>Speed(M/s)</value>
|
<value>Speed(M/s)</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="FailedToRunCore" xml:space="preserve">
|
<data name="FailedToRunCore" xml:space="preserve">
|
||||||
<value>Failed to run Core, please see the log</value>
|
<value>Failed to run Core, please check the prompt information</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="LvFilter" xml:space="preserve">
|
<data name="LvFilter" xml:space="preserve">
|
||||||
<value>Remarks regular filter</value>
|
<value>Remarks regular filter</value>
|
||||||
@@ -947,10 +941,10 @@
|
|||||||
<value>Move to group</value>
|
<value>Move to group</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="TbSettingsEnableDragDropSort" xml:space="preserve">
|
<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>
|
||||||
<data name="TbAutoRefresh" xml:space="preserve">
|
<data name="TbAutoRefresh" xml:space="preserve">
|
||||||
<value>AutoRefresh</value>
|
<value>Auto refresh</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="SpeedtestingSkip" xml:space="preserve">
|
<data name="SpeedtestingSkip" xml:space="preserve">
|
||||||
<value>Skip test</value>
|
<value>Skip test</value>
|
||||||
@@ -959,7 +953,7 @@
|
|||||||
<value>Edit Server (Ctrl+D)</value>
|
<value>Edit Server (Ctrl+D)</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="TbSettingsDoubleClick2Activate" xml:space="preserve">
|
<data name="TbSettingsDoubleClick2Activate" xml:space="preserve">
|
||||||
<value>Double-click server make active</value>
|
<value>Double-clicking server makes it active</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="SpeedtestingCompleted" xml:space="preserve">
|
<data name="SpeedtestingCompleted" xml:space="preserve">
|
||||||
<value>Test completed</value>
|
<value>Test completed</value>
|
||||||
@@ -974,10 +968,10 @@
|
|||||||
<value>This parameter is valid only for tcp/http and ws</value>
|
<value>This parameter is valid only for tcp/http and ws</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="TbSettingsCurrentFontFamily" xml:space="preserve">
|
<data name="TbSettingsCurrentFontFamily" xml:space="preserve">
|
||||||
<value>FontFamily(Require restart)</value>
|
<value>Font family (requires restart)</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="TbSettingsCurrentFontFamilyTip" xml:space="preserve">
|
<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>
|
||||||
<data name="TbSettingsSocksPortTip" xml:space="preserve">
|
<data name="TbSettingsSocksPortTip" xml:space="preserve">
|
||||||
<value>Pac port = +3; Xray API port = +4; mihomo API port = +5;</value>
|
<value>Pac port = +3; Xray API port = +4; mihomo API port = +5;</value>
|
||||||
@@ -1007,7 +1001,7 @@
|
|||||||
<value>SpiderX</value>
|
<value>SpiderX</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="TbSettingsEnableHWA" xml:space="preserve">
|
<data name="TbSettingsEnableHWA" xml:space="preserve">
|
||||||
<value>Enable hardware acceleration(Require restart)</value>
|
<value>Enable hardware acceleration (requires restart)</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="SpeedtestingWait" xml:space="preserve">
|
<data name="SpeedtestingWait" xml:space="preserve">
|
||||||
<value>Waiting for testing (press ESC to terminate)...</value>
|
<value>Waiting for testing (press ESC to terminate)...</value>
|
||||||
@@ -1115,7 +1109,7 @@
|
|||||||
<value>(Domain or IP or ProcName) and Port and Protocol and InboundTag => OutboundTag</value>
|
<value>(Domain or IP or ProcName) and Port and Protocol and InboundTag => OutboundTag</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="TbAutoScrollToEnd" xml:space="preserve">
|
<data name="TbAutoScrollToEnd" xml:space="preserve">
|
||||||
<value>Auto ScrollToEnd</value>
|
<value>Auto scroll to end</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="TbSettingsSpeedPingTestUrl" xml:space="preserve">
|
<data name="TbSettingsSpeedPingTestUrl" xml:space="preserve">
|
||||||
<value>Speed Ping Test URL</value>
|
<value>Speed Ping Test URL</value>
|
||||||
@@ -1235,7 +1229,7 @@
|
|||||||
<value>Multi-Server lowest latency</value>
|
<value>Multi-Server lowest latency</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="TbSettingsMainGirdOrientation" xml:space="preserve">
|
<data name="TbSettingsMainGirdOrientation" xml:space="preserve">
|
||||||
<value>Main layout orientation(Require restart)</value>
|
<value>Main layout orientation (requires restart)</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="menuSetDefaultLoadBalanceServer" xml:space="preserve">
|
<data name="menuSetDefaultLoadBalanceServer" xml:space="preserve">
|
||||||
<value>Multi-server load balancing</value>
|
<value>Multi-server load balancing</value>
|
||||||
@@ -1255,9 +1249,6 @@
|
|||||||
<data name="menuShowOrHideMainWindow" xml:space="preserve">
|
<data name="menuShowOrHideMainWindow" xml:space="preserve">
|
||||||
<value>Show or hide the main window</value>
|
<value>Show or hide the main window</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="UpdateStandalonePackageTip" xml:space="preserve">
|
|
||||||
<value>You are currently running a standalone package, please manually download the SelfContained.7z file to unzip and overwrite it!</value>
|
|
||||||
</data>
|
|
||||||
<data name="TbPreSocksPort4Sub" xml:space="preserve">
|
<data name="TbPreSocksPort4Sub" xml:space="preserve">
|
||||||
<value>Custom config socks port</value>
|
<value>Custom config socks port</value>
|
||||||
</data>
|
</data>
|
||||||
@@ -1343,7 +1334,7 @@
|
|||||||
<value>Please do not use the insecure HTTP protocol subscription address</value>
|
<value>Please do not use the insecure HTTP protocol subscription address</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="TbSettingsCurrentFontFamilyLinuxTip" xml:space="preserve">
|
<data name="TbSettingsCurrentFontFamilyLinuxTip" xml:space="preserve">
|
||||||
<value>Install the font to the system and restart the settings</value>
|
<value>Install the font to the system, select or fill in the font name, restart the settings</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="menuExitTips" xml:space="preserve">
|
<data name="menuExitTips" xml:space="preserve">
|
||||||
<value>Are you sure to exit?</value>
|
<value>Are you sure to exit?</value>
|
||||||
@@ -1355,7 +1346,7 @@
|
|||||||
<value>System sudo password</value>
|
<value>System sudo password</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="TbSettingsLinuxSudoPasswordTip" xml:space="preserve">
|
<data name="TbSettingsLinuxSudoPasswordTip" xml:space="preserve">
|
||||||
<value>The password is encrypted and stored only in local files.</value>
|
<value>The password is encrypted and stored only in local files</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="TbSettingsLinuxSudoPasswordIsEmpty" xml:space="preserve">
|
<data name="TbSettingsLinuxSudoPasswordIsEmpty" xml:space="preserve">
|
||||||
<value>Please set the sudo password in Tun mode settings first</value>
|
<value>Please set the sudo password in Tun mode settings first</value>
|
||||||
@@ -1372,11 +1363,11 @@
|
|||||||
<data name="TbSettingsHide2TrayWhenClose" xml:space="preserve">
|
<data name="TbSettingsHide2TrayWhenClose" xml:space="preserve">
|
||||||
<value>Hide to tray when closing the window</value>
|
<value>Hide to tray when closing the window</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="TbSettingsSpeedTestPageSize" xml:space="preserve">
|
<data name="TbSettingsMixedConcurrencyCount" xml:space="preserve">
|
||||||
<value>Number per time for auto batch during speedtest(max 1000)</value>
|
<value>The number of concurrent during multi-test</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="TbSettingsExceptionTip2" xml:space="preserve">
|
<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>
|
||||||
<data name="TbSettingsDestOverride" xml:space="preserve">
|
<data name="TbSettingsDestOverride" xml:space="preserve">
|
||||||
<value>Sniffing type</value>
|
<value>Sniffing type</value>
|
||||||
@@ -1393,4 +1384,16 @@
|
|||||||
<data name="menuCopyProxyCmdToClipboard" xml:space="preserve">
|
<data name="menuCopyProxyCmdToClipboard" xml:space="preserve">
|
||||||
<value>Copy proxy command to clipboard</value>
|
<value>Copy proxy command to clipboard</value>
|
||||||
</data>
|
</data>
|
||||||
|
<data name="SpeedtestingTestFailedPart" xml:space="preserve">
|
||||||
|
<value>Starting retesting failed parts, {0} remaining. Press ESC to terminate...</value>
|
||||||
|
</data>
|
||||||
|
<data name="menuTestServerResult" xml:space="preserve">
|
||||||
|
<value>By test result</value>
|
||||||
|
</data>
|
||||||
|
<data name="menuRemoveInvalidServerResult" xml:space="preserve">
|
||||||
|
<value>Remove invalid by test results</value>
|
||||||
|
</data>
|
||||||
|
<data name="RemoveInvalidServerResultTip" xml:space="preserve">
|
||||||
|
<value>Removed {0} invalid test results.</value>
|
||||||
|
</data>
|
||||||
</root>
|
</root>
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<root>
|
<root>
|
||||||
<!--
|
<!--
|
||||||
Microsoft ResX Schema
|
Microsoft ResX Schema
|
||||||
@@ -210,9 +210,6 @@
|
|||||||
<data name="LvTransportProtocol" xml:space="preserve">
|
<data name="LvTransportProtocol" xml:space="preserve">
|
||||||
<value>Протокол</value>
|
<value>Протокол</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="MsgClearSubscription" xml:space="preserve">
|
|
||||||
<value>Очистить контент оригинальной подписки</value>
|
|
||||||
</data>
|
|
||||||
<data name="MsgDownloadV2rayCoreSuccessfully" xml:space="preserve">
|
<data name="MsgDownloadV2rayCoreSuccessfully" xml:space="preserve">
|
||||||
<value>Ядро успешно загружено</value>
|
<value>Ядро успешно загружено</value>
|
||||||
</data>
|
</data>
|
||||||
@@ -721,9 +718,6 @@
|
|||||||
<data name="TbSettingsExceptionTip" xml:space="preserve">
|
<data name="TbSettingsExceptionTip" xml:space="preserve">
|
||||||
<value>Исключение. Не используйте прокси-сервер для адресов, начинающихся с (,), используйте точку с запятой (;)</value>
|
<value>Исключение. Не используйте прокси-сервер для адресов, начинающихся с (,), используйте точку с запятой (;)</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="TbSettingsHttpPort" xml:space="preserve">
|
|
||||||
<value>HTTP порт</value>
|
|
||||||
</data>
|
|
||||||
<data name="TbSettingsDisplayRealTimeSpeed" xml:space="preserve">
|
<data name="TbSettingsDisplayRealTimeSpeed" xml:space="preserve">
|
||||||
<value>Display real-time speed</value>
|
<value>Display real-time speed</value>
|
||||||
</data>
|
</data>
|
||||||
@@ -1210,9 +1204,6 @@
|
|||||||
<data name="menuAddTuicServer" xml:space="preserve">
|
<data name="menuAddTuicServer" xml:space="preserve">
|
||||||
<value>Add [TUIC] server</value>
|
<value>Add [TUIC] server</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="UpdateStandalonePackageTip" xml:space="preserve">
|
|
||||||
<value>You are currently running a standalone package, please manually download the SelfContained.7z file to unzip and overwrite it!</value>
|
|
||||||
</data>
|
|
||||||
<data name="TbSettingsEnableIPv6Address" xml:space="preserve">
|
<data name="TbSettingsEnableIPv6Address" xml:space="preserve">
|
||||||
<value>Enable IPv6 Address</value>
|
<value>Enable IPv6 Address</value>
|
||||||
</data>
|
</data>
|
||||||
@@ -1372,8 +1363,8 @@
|
|||||||
<data name="TbSettingsHide2TrayWhenClose" xml:space="preserve">
|
<data name="TbSettingsHide2TrayWhenClose" xml:space="preserve">
|
||||||
<value>Hide to tray when closing the window</value>
|
<value>Hide to tray when closing the window</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="TbSettingsSpeedTestPageSize" xml:space="preserve">
|
<data name="TbSettingsMixedConcurrencyCount" xml:space="preserve">
|
||||||
<value>Number per time for auto batch during speedtest(max 1000)</value>
|
<value>The number of concurrent during multi-test</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="TbSettingsExceptionTip2" xml:space="preserve">
|
<data name="TbSettingsExceptionTip2" xml:space="preserve">
|
||||||
<value>Exception. Do not use proxy server for addresses,with a comma (,)</value>
|
<value>Exception. Do not use proxy server for addresses,with a comma (,)</value>
|
||||||
@@ -1393,4 +1384,16 @@
|
|||||||
<data name="menuCopyProxyCmdToClipboard" xml:space="preserve">
|
<data name="menuCopyProxyCmdToClipboard" xml:space="preserve">
|
||||||
<value>Copy proxy command to clipboard</value>
|
<value>Copy proxy command to clipboard</value>
|
||||||
</data>
|
</data>
|
||||||
|
<data name="SpeedtestingTestFailedPart" xml:space="preserve">
|
||||||
|
<value>Starting retesting failed parts, {0} remaining. Press ESC to terminate...</value>
|
||||||
|
</data>
|
||||||
|
<data name="menuTestServerResult" xml:space="preserve">
|
||||||
|
<value>By test result</value>
|
||||||
|
</data>
|
||||||
|
<data name="menuRemoveInvalidServerResult" xml:space="preserve">
|
||||||
|
<value>Remove invalid by test results</value>
|
||||||
|
</data>
|
||||||
|
<data name="RemoveInvalidServerResultTip" xml:space="preserve">
|
||||||
|
<value>Removed {0} invalid test results.</value>
|
||||||
|
</data>
|
||||||
</root>
|
</root>
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<root>
|
<root>
|
||||||
<!--
|
<!--
|
||||||
Microsoft ResX Schema
|
Microsoft ResX Schema
|
||||||
@@ -175,10 +175,10 @@
|
|||||||
<value>初始化配置</value>
|
<value>初始化配置</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="IsLatestCore" xml:space="preserve">
|
<data name="IsLatestCore" xml:space="preserve">
|
||||||
<value>{0} {1} 已是最新版本</value>
|
<value>{0} {1} 已是最新版本。</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="IsLatestN" xml:space="preserve">
|
<data name="IsLatestN" xml:space="preserve">
|
||||||
<value>{0} {1} 已是最新版本</value>
|
<value>{0} {1} 已是最新版本。</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="LvAddress" xml:space="preserve">
|
<data name="LvAddress" xml:space="preserve">
|
||||||
<value>地址</value>
|
<value>地址</value>
|
||||||
@@ -210,9 +210,6 @@
|
|||||||
<data name="LvTransportProtocol" xml:space="preserve">
|
<data name="LvTransportProtocol" xml:space="preserve">
|
||||||
<value>传输协议</value>
|
<value>传输协议</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="MsgClearSubscription" xml:space="preserve">
|
|
||||||
<value>清除原订阅内容</value>
|
|
||||||
</data>
|
|
||||||
<data name="MsgDownloadV2rayCoreSuccessfully" xml:space="preserve">
|
<data name="MsgDownloadV2rayCoreSuccessfully" xml:space="preserve">
|
||||||
<value>下载Core成功</value>
|
<value>下载Core成功</value>
|
||||||
</data>
|
</data>
|
||||||
@@ -277,7 +274,7 @@
|
|||||||
<value>请先选择服务器</value>
|
<value>请先选择服务器</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="RemoveDuplicateServerResult" xml:space="preserve">
|
<data name="RemoveDuplicateServerResult" xml:space="preserve">
|
||||||
<value>服务器去重完成。原数量: {0},现数量: {1}</value>
|
<value>服务器去重完成。原数量: {0},现数量: {1}。</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="RemoveServer" xml:space="preserve">
|
<data name="RemoveServer" xml:space="preserve">
|
||||||
<value>是否确定移除服务器?</value>
|
<value>是否确定移除服务器?</value>
|
||||||
@@ -715,9 +712,6 @@
|
|||||||
<data name="TbSettingsExceptionTip" xml:space="preserve">
|
<data name="TbSettingsExceptionTip" xml:space="preserve">
|
||||||
<value>例外:对于下列字符开头的地址,不使用代理配置文件。使用分号(;)分隔。</value>
|
<value>例外:对于下列字符开头的地址,不使用代理配置文件。使用分号(;)分隔。</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="TbSettingsHttpPort" xml:space="preserve">
|
|
||||||
<value>本地http监听端口</value>
|
|
||||||
</data>
|
|
||||||
<data name="TbSettingsDisplayRealTimeSpeed" xml:space="preserve">
|
<data name="TbSettingsDisplayRealTimeSpeed" xml:space="preserve">
|
||||||
<value>显示实时速度(需重启)</value>
|
<value>显示实时速度(需重启)</value>
|
||||||
</data>
|
</data>
|
||||||
@@ -926,7 +920,7 @@
|
|||||||
<value>速度(M/s)</value>
|
<value>速度(M/s)</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="FailedToRunCore" xml:space="preserve">
|
<data name="FailedToRunCore" xml:space="preserve">
|
||||||
<value>运行Core失败,请查看日志</value>
|
<value>运行 Core 失败,请查看提示信息</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="LvFilter" xml:space="preserve">
|
<data name="LvFilter" xml:space="preserve">
|
||||||
<value>别名正则过滤</value>
|
<value>别名正则过滤</value>
|
||||||
@@ -1252,9 +1246,6 @@
|
|||||||
<data name="menuShowOrHideMainWindow" xml:space="preserve">
|
<data name="menuShowOrHideMainWindow" xml:space="preserve">
|
||||||
<value>显示或隐藏主界面</value>
|
<value>显示或隐藏主界面</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="UpdateStandalonePackageTip" xml:space="preserve">
|
|
||||||
<value>您当前运行的是独立包,请手动下载 SelfContained.7z文件解压覆盖!</value>
|
|
||||||
</data>
|
|
||||||
<data name="TbPreSocksPort4Sub" xml:space="preserve">
|
<data name="TbPreSocksPort4Sub" xml:space="preserve">
|
||||||
<value>自定义配置的Socks端口</value>
|
<value>自定义配置的Socks端口</value>
|
||||||
</data>
|
</data>
|
||||||
@@ -1340,7 +1331,7 @@
|
|||||||
<value>请不要使用不安全的HTTP协议订阅地址</value>
|
<value>请不要使用不安全的HTTP协议订阅地址</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="TbSettingsCurrentFontFamilyLinuxTip" xml:space="preserve">
|
<data name="TbSettingsCurrentFontFamilyLinuxTip" xml:space="preserve">
|
||||||
<value>安装字体到系统中,重启设置</value>
|
<value>安装字体到系统中,选择或填入字体名称,重启设置</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="menuExitTips" xml:space="preserve">
|
<data name="menuExitTips" xml:space="preserve">
|
||||||
<value>是否确定退出?</value>
|
<value>是否确定退出?</value>
|
||||||
@@ -1369,8 +1360,8 @@
|
|||||||
<data name="TbSettingsHide2TrayWhenClose" xml:space="preserve">
|
<data name="TbSettingsHide2TrayWhenClose" xml:space="preserve">
|
||||||
<value>关闭窗口时隐藏至托盘</value>
|
<value>关闭窗口时隐藏至托盘</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="TbSettingsSpeedTestPageSize" xml:space="preserve">
|
<data name="TbSettingsMixedConcurrencyCount" xml:space="preserve">
|
||||||
<value>测试时自动分批的每批数量(最大1000)</value>
|
<value>多线程测试时的并发数量</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="TbSettingsExceptionTip2" xml:space="preserve">
|
<data name="TbSettingsExceptionTip2" xml:space="preserve">
|
||||||
<value>例外:对于下列地址不使用代理配置文件。使用逗号(,)分隔。</value>
|
<value>例外:对于下列地址不使用代理配置文件。使用逗号(,)分隔。</value>
|
||||||
@@ -1390,4 +1381,16 @@
|
|||||||
<data name="menuCopyProxyCmdToClipboard" xml:space="preserve">
|
<data name="menuCopyProxyCmdToClipboard" xml:space="preserve">
|
||||||
<value>复制终端代理命令至剪贴板</value>
|
<value>复制终端代理命令至剪贴板</value>
|
||||||
</data>
|
</data>
|
||||||
|
<data name="SpeedtestingTestFailedPart" xml:space="preserve">
|
||||||
|
<value>开始对失败部分进行重新测试,剩余 {0} 个。可按 ESC 终止...</value>
|
||||||
|
</data>
|
||||||
|
<data name="menuTestServerResult" xml:space="preserve">
|
||||||
|
<value>按测试结果</value>
|
||||||
|
</data>
|
||||||
|
<data name="menuRemoveInvalidServerResult" xml:space="preserve">
|
||||||
|
<value>按测试结果移除无效</value>
|
||||||
|
</data>
|
||||||
|
<data name="RemoveInvalidServerResultTip" xml:space="preserve">
|
||||||
|
<value>移除无效测试结果 {0} 个。</value>
|
||||||
|
</data>
|
||||||
</root>
|
</root>
|
||||||
@@ -175,10 +175,10 @@
|
|||||||
<value>初始化設定</value>
|
<value>初始化設定</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="IsLatestCore" xml:space="preserve">
|
<data name="IsLatestCore" xml:space="preserve">
|
||||||
<value>{0} {1} 已是最新版本</value>
|
<value>{0} {1} 已是最新版本。</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="IsLatestN" xml:space="preserve">
|
<data name="IsLatestN" xml:space="preserve">
|
||||||
<value>{0} {1} 已是最新版本</value>
|
<value>{0} {1} 已是最新版本。</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="LvAddress" xml:space="preserve">
|
<data name="LvAddress" xml:space="preserve">
|
||||||
<value>位址</value>
|
<value>位址</value>
|
||||||
@@ -210,9 +210,6 @@
|
|||||||
<data name="LvTransportProtocol" xml:space="preserve">
|
<data name="LvTransportProtocol" xml:space="preserve">
|
||||||
<value>傳輸協定</value>
|
<value>傳輸協定</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="MsgClearSubscription" xml:space="preserve">
|
|
||||||
<value>清除原訂閱內容</value>
|
|
||||||
</data>
|
|
||||||
<data name="MsgDownloadV2rayCoreSuccessfully" xml:space="preserve">
|
<data name="MsgDownloadV2rayCoreSuccessfully" xml:space="preserve">
|
||||||
<value>下載Core成功</value>
|
<value>下載Core成功</value>
|
||||||
</data>
|
</data>
|
||||||
@@ -277,7 +274,7 @@
|
|||||||
<value>請先選擇伺服器</value>
|
<value>請先選擇伺服器</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="RemoveDuplicateServerResult" xml:space="preserve">
|
<data name="RemoveDuplicateServerResult" xml:space="preserve">
|
||||||
<value>伺服器去重完成。原數量: {0},現數量: {1}</value>
|
<value>伺服器去重完成。原數量: {0},現數量: {1}。</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="RemoveServer" xml:space="preserve">
|
<data name="RemoveServer" xml:space="preserve">
|
||||||
<value>是否確定移除伺服器?</value>
|
<value>是否確定移除伺服器?</value>
|
||||||
@@ -716,9 +713,6 @@
|
|||||||
<data name="TbSettingsExceptionTip" xml:space="preserve">
|
<data name="TbSettingsExceptionTip" xml:space="preserve">
|
||||||
<value>例外:對於下列字元開頭的位址,不使用代理設定檔。使用分號(;)分隔。</value>
|
<value>例外:對於下列字元開頭的位址,不使用代理設定檔。使用分號(;)分隔。</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="TbSettingsHttpPort" xml:space="preserve">
|
|
||||||
<value>本機HTTP偵聽埠</value>
|
|
||||||
</data>
|
|
||||||
<data name="TbSettingsDisplayRealTimeSpeed" xml:space="preserve">
|
<data name="TbSettingsDisplayRealTimeSpeed" xml:space="preserve">
|
||||||
<value>顯示即時速度(需重啟)</value>
|
<value>顯示即時速度(需重啟)</value>
|
||||||
</data>
|
</data>
|
||||||
@@ -927,7 +921,7 @@
|
|||||||
<value>速度(M/s)</value>
|
<value>速度(M/s)</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="FailedToRunCore" xml:space="preserve">
|
<data name="FailedToRunCore" xml:space="preserve">
|
||||||
<value>執行Core失敗,請查閲日誌</value>
|
<value>執行Core失敗,請查看提示訊息</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="LvFilter" xml:space="preserve">
|
<data name="LvFilter" xml:space="preserve">
|
||||||
<value>別名正則過濾</value>
|
<value>別名正則過濾</value>
|
||||||
@@ -1133,9 +1127,6 @@
|
|||||||
<data name="menuShowOrHideMainWindow" xml:space="preserve">
|
<data name="menuShowOrHideMainWindow" xml:space="preserve">
|
||||||
<value>顯示或隱藏主介面</value>
|
<value>顯示或隱藏主介面</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="UpdateStandalonePackageTip" xml:space="preserve">
|
|
||||||
<value>您目前運行的是獨立包,請手動下載 SelfContained.7z檔案解壓縮覆蓋!</value>
|
|
||||||
</data>
|
|
||||||
<data name="TbPreSocksPort4Sub" xml:space="preserve">
|
<data name="TbPreSocksPort4Sub" xml:space="preserve">
|
||||||
<value>自訂設定的Socks連接埠</value>
|
<value>自訂設定的Socks連接埠</value>
|
||||||
</data>
|
</data>
|
||||||
@@ -1221,7 +1212,7 @@
|
|||||||
<value>請不要使用不安全的HTTP協定訂閱位址</value>
|
<value>請不要使用不安全的HTTP協定訂閱位址</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="TbSettingsCurrentFontFamilyLinuxTip" xml:space="preserve">
|
<data name="TbSettingsCurrentFontFamilyLinuxTip" xml:space="preserve">
|
||||||
<value>安裝字型到系統中,重新啟動設定</value>
|
<value>安裝字體到系統中,選擇或填入字體名稱,重新啟動設定</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="menuExitTips" xml:space="preserve">
|
<data name="menuExitTips" xml:space="preserve">
|
||||||
<value>是否確定退出?</value>
|
<value>是否確定退出?</value>
|
||||||
@@ -1370,8 +1361,8 @@
|
|||||||
<data name="TbSettingsHide2TrayWhenClose" xml:space="preserve">
|
<data name="TbSettingsHide2TrayWhenClose" xml:space="preserve">
|
||||||
<value>關閉視窗時隱藏至托盤</value>
|
<value>關閉視窗時隱藏至托盤</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="TbSettingsSpeedTestPageSize" xml:space="preserve">
|
<data name="TbSettingsMixedConcurrencyCount" xml:space="preserve">
|
||||||
<value>測試時自動分批的每批數量(最大1000)</value>
|
<value>多執行緒測試時的並發數量</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="TbSettingsExceptionTip2" xml:space="preserve">
|
<data name="TbSettingsExceptionTip2" xml:space="preserve">
|
||||||
<value>例外:對於下列位址不使用代理設定檔,使用逗號(,)分隔。</value>
|
<value>例外:對於下列位址不使用代理設定檔,使用逗號(,)分隔。</value>
|
||||||
@@ -1391,4 +1382,16 @@
|
|||||||
<data name="menuCopyProxyCmdToClipboard" xml:space="preserve">
|
<data name="menuCopyProxyCmdToClipboard" xml:space="preserve">
|
||||||
<value>複製終端代理指令至剪貼簿</value>
|
<value>複製終端代理指令至剪貼簿</value>
|
||||||
</data>
|
</data>
|
||||||
|
<data name="SpeedtestingTestFailedPart" xml:space="preserve">
|
||||||
|
<value>開始對失敗部分進行重新測試,剩餘 {0} 個。可按 ESC 終止...</value>
|
||||||
|
</data>
|
||||||
|
<data name="menuTestServerResult" xml:space="preserve">
|
||||||
|
<value>按測試結果</value>
|
||||||
|
</data>
|
||||||
|
<data name="menuRemoveInvalidServerResult" xml:space="preserve">
|
||||||
|
<value>按測試結果移除無效</value>
|
||||||
|
</data>
|
||||||
|
<data name="RemoveInvalidServerResultTip" xml:space="preserve">
|
||||||
|
<value>移除無效測試結果 {0} 個。</value>
|
||||||
|
</data>
|
||||||
</root>
|
</root>
|
||||||
118
v2rayN/ServiceLib/Sample/proxy_set_linux_sh
Normal file
118
v2rayN/ServiceLib/Sample/proxy_set_linux_sh
Normal file
@@ -0,0 +1,118 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
# Function to set proxy for GNOME
|
||||||
|
set_gnome_proxy() {
|
||||||
|
local MODE=$1
|
||||||
|
local PROXY_IP=$2
|
||||||
|
local PROXY_PORT=$3
|
||||||
|
local IGNORE_HOSTS=$4
|
||||||
|
|
||||||
|
# Set the proxy mode
|
||||||
|
gsettings set org.gnome.system.proxy mode "$MODE"
|
||||||
|
|
||||||
|
if [ "$MODE" == "manual" ]; then
|
||||||
|
# List of protocols
|
||||||
|
local PROTOCOLS=("http" "https" "ftp" "socks")
|
||||||
|
|
||||||
|
# Loop through protocols to set the proxy
|
||||||
|
for PROTOCOL in "${PROTOCOLS[@]}"; do
|
||||||
|
gsettings set org.gnome.system.proxy.$PROTOCOL host "$PROXY_IP"
|
||||||
|
gsettings set org.gnome.system.proxy.$PROTOCOL port "$PROXY_PORT"
|
||||||
|
done
|
||||||
|
|
||||||
|
# Set ignored hosts
|
||||||
|
gsettings set org.gnome.system.proxy ignore-hosts "['$IGNORE_HOSTS']"
|
||||||
|
|
||||||
|
echo "GNOME: Manual proxy settings applied."
|
||||||
|
echo "Proxy IP: $PROXY_IP"
|
||||||
|
echo "Proxy Port: $PROXY_PORT"
|
||||||
|
echo "Ignored Hosts: $IGNORE_HOSTS"
|
||||||
|
elif [ "$MODE" == "none" ]; then
|
||||||
|
echo "GNOME: Proxy disabled."
|
||||||
|
else
|
||||||
|
echo "GNOME: Invalid mode. Use 'none' or 'manual'."
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
# Function to set proxy for KDE
|
||||||
|
set_kde_proxy() {
|
||||||
|
local MODE=$1
|
||||||
|
local PROXY_IP=$2
|
||||||
|
local PROXY_PORT=$3
|
||||||
|
local IGNORE_HOSTS=$4
|
||||||
|
|
||||||
|
# Determine the correct kwriteconfig command based on KDE_SESSION_VERSION
|
||||||
|
if [ "$KDE_SESSION_VERSION" == "6" ]; then
|
||||||
|
KWRITECONFIG="kwriteconfig6"
|
||||||
|
else
|
||||||
|
KWRITECONFIG="kwriteconfig5"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# KDE uses kwriteconfig to modify proxy settings
|
||||||
|
if [ "$MODE" == "manual" ]; then
|
||||||
|
# Set proxy for all protocols
|
||||||
|
$KWRITECONFIG --file kioslaverc --group "Proxy Settings" --key ProxyType 1
|
||||||
|
$KWRITECONFIG --file kioslaverc --group "Proxy Settings" --key httpProxy "http://$PROXY_IP:$PROXY_PORT"
|
||||||
|
$KWRITECONFIG --file kioslaverc --group "Proxy Settings" --key httpsProxy "http://$PROXY_IP:$PROXY_PORT"
|
||||||
|
$KWRITECONFIG --file kioslaverc --group "Proxy Settings" --key ftpProxy "http://$PROXY_IP:$PROXY_PORT"
|
||||||
|
$KWRITECONFIG --file kioslaverc --group "Proxy Settings" --key socksProxy "http://$PROXY_IP:$PROXY_PORT"
|
||||||
|
|
||||||
|
# Set ignored hosts
|
||||||
|
$KWRITECONFIG --file kioslaverc --group "Proxy Settings" --key NoProxyFor "$IGNORE_HOSTS"
|
||||||
|
|
||||||
|
echo "KDE: Manual proxy settings applied."
|
||||||
|
echo "Proxy IP: $PROXY_IP"
|
||||||
|
echo "Proxy Port: $PROXY_PORT"
|
||||||
|
echo "Ignored Hosts: $IGNORE_HOSTS"
|
||||||
|
elif [ "$MODE" == "none" ]; then
|
||||||
|
# Disable proxy
|
||||||
|
$KWRITECONFIG --file kioslaverc --group "Proxy Settings" --key ProxyType 0
|
||||||
|
echo "KDE: Proxy disabled."
|
||||||
|
else
|
||||||
|
echo "KDE: Invalid mode. Use 'none' or 'manual'."
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Apply changes by restarting KDE's network settings
|
||||||
|
dbus-send --type=signal /KIO/Scheduler org.kde.KIO.Scheduler.reparseSlaveConfiguration string:""
|
||||||
|
}
|
||||||
|
|
||||||
|
# Detect the current desktop environment
|
||||||
|
detect_desktop_environment() {
|
||||||
|
if [ "$XDG_CURRENT_DESKTOP" == "GNOME" ] || [ "$XDG_CURRENT_DESKTOP" == "ubuntu:GNOME" ] || [ "$XDG_SESSION_DESKTOP" == "GNOME" ] || [ "$XDG_SESSION_DESKTOP" == "ubuntu:GNOME" ]; then
|
||||||
|
echo "gnome"
|
||||||
|
elif [ "$XDG_CURRENT_DESKTOP" == "KDE" ] || [ "$XDG_CURRENT_DESKTOP" == "plasma" ] || [ "$XDG_SESSION_DESKTOP" == "KDE" ] || [ "$XDG_SESSION_DESKTOP" == "plasma" ]; then
|
||||||
|
echo "kde"
|
||||||
|
else
|
||||||
|
echo "unsupported"
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
# Main script logic
|
||||||
|
if [ "$#" -lt 1 ]; then
|
||||||
|
echo "Usage: $0 <mode> [proxy_ip proxy_port ignore_hosts]"
|
||||||
|
echo " mode: 'none' or 'manual'"
|
||||||
|
echo " If mode is 'manual', provide proxy IP, port, and ignore hosts."
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Get the mode
|
||||||
|
MODE=$1
|
||||||
|
PROXY_IP=$2
|
||||||
|
PROXY_PORT=$3
|
||||||
|
IGNORE_HOSTS=$4
|
||||||
|
|
||||||
|
# Detect desktop environment
|
||||||
|
DE=$(detect_desktop_environment)
|
||||||
|
|
||||||
|
# Apply settings based on the desktop environment
|
||||||
|
if [ "$DE" == "gnome" ]; then
|
||||||
|
set_gnome_proxy "$MODE" "$PROXY_IP" "$PROXY_PORT" "$IGNORE_HOSTS"
|
||||||
|
elif [ "$DE" == "kde" ]; then
|
||||||
|
set_gnome_proxy "$MODE" "$PROXY_IP" "$PROXY_PORT" "$IGNORE_HOSTS"
|
||||||
|
set_kde_proxy "$MODE" "$PROXY_IP" "$PROXY_PORT" "$IGNORE_HOSTS"
|
||||||
|
else
|
||||||
|
echo "Unsupported desktop environment: $DE"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
74
v2rayN/ServiceLib/Sample/proxy_set_osx_sh
Normal file
74
v2rayN/ServiceLib/Sample/proxy_set_osx_sh
Normal file
@@ -0,0 +1,74 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
# Function to set proxy
|
||||||
|
set_proxy() {
|
||||||
|
PROXY_IP=$1
|
||||||
|
PROXY_PORT=$2
|
||||||
|
|
||||||
|
shift 2
|
||||||
|
BYPASS_DOMAINS=("$@")
|
||||||
|
# If no bypass domains are provided, set it to empty by default
|
||||||
|
if [ ${#BYPASS_DOMAINS[@]} -eq 0 ]; then
|
||||||
|
BYPASS_DOMAINS=("")
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Get all network service names
|
||||||
|
SERVICES=$(networksetup -listallnetworkservices | grep -v '*')
|
||||||
|
|
||||||
|
# Loop through each network service
|
||||||
|
echo "$SERVICES" | while read -r SERVICE; do
|
||||||
|
echo "Setting proxy for network service '$SERVICE'..."
|
||||||
|
# Set HTTP proxy
|
||||||
|
networksetup -setwebproxy "$SERVICE" "$PROXY_IP" "$PROXY_PORT"
|
||||||
|
|
||||||
|
# Set HTTPS proxy
|
||||||
|
networksetup -setsecurewebproxy "$SERVICE" "$PROXY_IP" "$PROXY_PORT"
|
||||||
|
|
||||||
|
# Set SOCKS proxy
|
||||||
|
networksetup -setsocksfirewallproxy "$SERVICE" "$PROXY_IP" "$PROXY_PORT"
|
||||||
|
|
||||||
|
# Set bypass domains
|
||||||
|
networksetup -setproxybypassdomains "$SERVICE" "${BYPASS_DOMAINS[@]}"
|
||||||
|
echo "Proxy for network service '$SERVICE' has been set to $PROXY_IP:$PROXY_PORT"
|
||||||
|
done
|
||||||
|
echo "Proxy settings for all network services are complete!"
|
||||||
|
}
|
||||||
|
|
||||||
|
# Function to disable proxy
|
||||||
|
clear_proxy() {
|
||||||
|
# Get all network service names
|
||||||
|
SERVICES=$(networksetup -listallnetworkservices | grep -v '*')
|
||||||
|
|
||||||
|
# Loop through each network service
|
||||||
|
echo "$SERVICES" | while read -r SERVICE; do
|
||||||
|
echo "Disabling proxy and clearing bypass domains for network service '$SERVICE'..."
|
||||||
|
# Disable HTTP proxy
|
||||||
|
networksetup -setwebproxystate "$SERVICE" off
|
||||||
|
|
||||||
|
# Disable HTTPS proxy
|
||||||
|
networksetup -setsecurewebproxystate "$SERVICE" off
|
||||||
|
|
||||||
|
# Disable SOCKS proxy
|
||||||
|
networksetup -setsocksfirewallproxystate "$SERVICE" off
|
||||||
|
|
||||||
|
echo "Proxy for network service '$SERVICE' has been disabled"
|
||||||
|
done
|
||||||
|
echo "Proxy for all network services has been disabled!"
|
||||||
|
}
|
||||||
|
|
||||||
|
# Main script logic
|
||||||
|
if [ "$1" == "set" ]; then
|
||||||
|
# Check if enough parameters are passed for setting proxy
|
||||||
|
if [ "$#" -lt 3 ]; then
|
||||||
|
echo "Usage: $0 set <IP Address> <Port> [Bypass Domain 1 Bypass Domain 2 ...]"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
set_proxy "$2" "$3" "${@:4}"
|
||||||
|
elif [ "$1" == "clear" ]; then
|
||||||
|
clear_proxy
|
||||||
|
else
|
||||||
|
echo "Usage:"
|
||||||
|
echo " To set proxy: $0 set <IP Address> <Port> [Bypass Domain 1 Bypass Domain 2 ...]"
|
||||||
|
echo " To clear proxy: $0 clear"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
@@ -1,26 +1,23 @@
|
|||||||
<Project Sdk="Microsoft.NET.Sdk">
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<TargetFramework>net8.0</TargetFramework>
|
<OutputType>Library</OutputType>
|
||||||
<ImplicitUsings>enable</ImplicitUsings>
|
|
||||||
<Nullable>enable</Nullable>
|
|
||||||
<Version>7.6.2</Version>
|
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="Downloader" Version="3.3.1" />
|
<PackageReference Include="Downloader" />
|
||||||
<PackageReference Include="ReactiveUI" Version="20.1.63" />
|
<PackageReference Include="ReactiveUI">
|
||||||
<PackageReference Include="ReactiveUI.Fody" Version="19.5.41" />
|
<TreatAsUsed>true</TreatAsUsed>
|
||||||
<PackageReference Include="sqlite-net-pcl" Version="1.9.172" />
|
</PackageReference>
|
||||||
<PackageReference Include="Splat.NLog" Version="15.2.22" />
|
<PackageReference Include="ReactiveUI.Fody" />
|
||||||
<PackageReference Include="WebDav.Client" Version="2.8.0" />
|
<PackageReference Include="sqlite-net-pcl" />
|
||||||
<PackageReference Include="YamlDotNet" Version="16.3.0" />
|
<PackageReference Include="Splat.NLog" />
|
||||||
<PackageReference Include="QRCoder" Version="1.6.0" />
|
<PackageReference Include="WebDav.Client" />
|
||||||
<PackageReference Include="CliWrap" Version="3.7.0" />
|
<PackageReference Include="YamlDotNet" />
|
||||||
<PackageReference Include="SkiaSharp.QrCode" Version="0.7.0" />
|
<PackageReference Include="QRCoder" />
|
||||||
<PackageReference Include="ZXing.Net.Bindings.SkiaSharp" Version="0.16.14" />
|
<PackageReference Include="CliWrap" />
|
||||||
<PackageReference Include="TaskScheduler" Version="2.11.0" />
|
<PackageReference Include="ZXing.Net.Bindings.SkiaSharp" />
|
||||||
|
<PackageReference Include="TaskScheduler" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
@@ -32,6 +29,8 @@
|
|||||||
<EmbeddedResource Include="Sample\dns_singbox_normal" />
|
<EmbeddedResource Include="Sample\dns_singbox_normal" />
|
||||||
<EmbeddedResource Include="Sample\dns_v2ray_normal" />
|
<EmbeddedResource Include="Sample\dns_v2ray_normal" />
|
||||||
<EmbeddedResource Include="Sample\pac" />
|
<EmbeddedResource Include="Sample\pac" />
|
||||||
|
<EmbeddedResource Include="Sample\proxy_set_linux_sh" />
|
||||||
|
<EmbeddedResource Include="Sample\proxy_set_osx_sh" />
|
||||||
<EmbeddedResource Include="Sample\SampleClientConfig" />
|
<EmbeddedResource Include="Sample\SampleClientConfig" />
|
||||||
<EmbeddedResource Include="Sample\SampleHttpRequest" />
|
<EmbeddedResource Include="Sample\SampleHttpRequest" />
|
||||||
<EmbeddedResource Include="Sample\SampleHttpResponse" />
|
<EmbeddedResource Include="Sample\SampleHttpResponse" />
|
||||||
@@ -51,9 +50,6 @@
|
|||||||
<DesignTime>True</DesignTime>
|
<DesignTime>True</DesignTime>
|
||||||
<AutoGen>True</AutoGen>
|
<AutoGen>True</AutoGen>
|
||||||
</Compile>
|
</Compile>
|
||||||
</ItemGroup>
|
|
||||||
|
|
||||||
<ItemGroup>
|
|
||||||
<EmbeddedResource Update="Resx\ResUI.fa-Ir.resx">
|
<EmbeddedResource Update="Resx\ResUI.fa-Ir.resx">
|
||||||
<SubType>Designer</SubType>
|
<SubType>Designer</SubType>
|
||||||
<Generator>PublicResXFileCodeGenerator</Generator>
|
<Generator>PublicResXFileCodeGenerator</Generator>
|
||||||
|
|||||||
@@ -116,7 +116,7 @@ namespace ServiceLib.Services.CoreConfig
|
|||||||
//enable tun mode
|
//enable tun mode
|
||||||
if (_config.TunModeItem.EnableTun)
|
if (_config.TunModeItem.EnableTun)
|
||||||
{
|
{
|
||||||
string tun = Utils.GetEmbedText(Global.ClashTunYaml);
|
var tun = EmbedUtils.GetEmbedText(Global.ClashTunYaml);
|
||||||
if (Utils.IsNotEmpty(tun))
|
if (Utils.IsNotEmpty(tun))
|
||||||
{
|
{
|
||||||
var tunContent = YamlUtils.FromYaml<Dictionary<string, object>>(tun);
|
var tunContent = YamlUtils.FromYaml<Dictionary<string, object>>(tun);
|
||||||
@@ -128,7 +128,7 @@ namespace ServiceLib.Services.CoreConfig
|
|||||||
//Mixin
|
//Mixin
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
MixinContent(fileContent, node);
|
await MixinContent(fileContent, node);
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
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)
|
if (!_config.ClashUIItem.EnableMixinContent)
|
||||||
//{
|
|
||||||
// return;
|
|
||||||
//}
|
|
||||||
|
|
||||||
var path = Utils.GetConfigPath(Global.ClashMixinConfigFileName);
|
|
||||||
if (!File.Exists(path))
|
|
||||||
{
|
{
|
||||||
return;
|
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);
|
var mixinContent = YamlUtils.FromYaml<Dictionary<string, object>>(txtFile);
|
||||||
if (mixinContent == null)
|
if (mixinContent == null)
|
||||||
|
|||||||
@@ -35,7 +35,7 @@ namespace ServiceLib.Services.CoreConfig
|
|||||||
|
|
||||||
ret.Msg = ResUI.InitialConfiguration;
|
ret.Msg = ResUI.InitialConfiguration;
|
||||||
|
|
||||||
string result = Utils.GetEmbedText(Global.SingboxSampleClient);
|
string result = EmbedUtils.GetEmbedText(Global.SingboxSampleClient);
|
||||||
if (Utils.IsNullOrEmpty(result))
|
if (Utils.IsNullOrEmpty(result))
|
||||||
{
|
{
|
||||||
ret.Msg = ResUI.FailedGetDefaultConfiguration;
|
ret.Msg = ResUI.FailedGetDefaultConfiguration;
|
||||||
@@ -91,8 +91,8 @@ namespace ServiceLib.Services.CoreConfig
|
|||||||
|
|
||||||
ret.Msg = ResUI.InitialConfiguration;
|
ret.Msg = ResUI.InitialConfiguration;
|
||||||
|
|
||||||
var result = Utils.GetEmbedText(Global.SingboxSampleClient);
|
var result = EmbedUtils.GetEmbedText(Global.SingboxSampleClient);
|
||||||
var txtOutbound = Utils.GetEmbedText(Global.SingboxSampleOutbound);
|
var txtOutbound = EmbedUtils.GetEmbedText(Global.SingboxSampleOutbound);
|
||||||
if (Utils.IsNullOrEmpty(result) || txtOutbound.IsNullOrEmpty())
|
if (Utils.IsNullOrEmpty(result) || txtOutbound.IsNullOrEmpty())
|
||||||
{
|
{
|
||||||
ret.Msg = ResUI.FailedGetDefaultConfiguration;
|
ret.Msg = ResUI.FailedGetDefaultConfiguration;
|
||||||
@@ -242,6 +242,66 @@ namespace ServiceLib.Services.CoreConfig
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public async Task<RetResult> GenerateClientSpeedtestConfig(ProfileItem node, int port)
|
||||||
|
{
|
||||||
|
var ret = new RetResult();
|
||||||
|
try
|
||||||
|
{
|
||||||
|
if (node is not { Port: > 0 })
|
||||||
|
{
|
||||||
|
ret.Msg = ResUI.CheckServerSettings;
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
if (node.GetNetwork() is nameof(ETransport.kcp) or nameof(ETransport.xhttp))
|
||||||
|
{
|
||||||
|
ret.Msg = ResUI.Incorrectconfiguration + $" - {node.GetNetwork()}";
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
ret.Msg = ResUI.InitialConfiguration;
|
||||||
|
|
||||||
|
var result = EmbedUtils.GetEmbedText(Global.SingboxSampleClient);
|
||||||
|
if (Utils.IsNullOrEmpty(result))
|
||||||
|
{
|
||||||
|
ret.Msg = ResUI.FailedGetDefaultConfiguration;
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
var singboxConfig = JsonUtils.Deserialize<SingboxConfig>(result);
|
||||||
|
if (singboxConfig == null)
|
||||||
|
{
|
||||||
|
ret.Msg = ResUI.FailedGenDefaultConfiguration;
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
await GenLog(singboxConfig);
|
||||||
|
await GenOutbound(node, singboxConfig.outbounds.First());
|
||||||
|
await GenMoreOutbounds(node, singboxConfig);
|
||||||
|
await GenDnsDomains(null, singboxConfig, null);
|
||||||
|
|
||||||
|
singboxConfig.route.rules.Clear();
|
||||||
|
singboxConfig.inbounds.Clear();
|
||||||
|
singboxConfig.inbounds.Add(new()
|
||||||
|
{
|
||||||
|
tag = $"{EInboundProtocol.mixed}{port}",
|
||||||
|
listen = Global.Loopback,
|
||||||
|
listen_port = port,
|
||||||
|
type = EInboundProtocol.mixed.ToString(),
|
||||||
|
});
|
||||||
|
|
||||||
|
ret.Msg = string.Format(ResUI.SuccessfulConfiguration, "");
|
||||||
|
ret.Success = true;
|
||||||
|
ret.Data = JsonUtils.Serialize(singboxConfig);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
Logging.SaveLog(_tag, ex);
|
||||||
|
ret.Msg = ResUI.FailedGenDefaultConfiguration;
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public async Task<RetResult> GenerateClientMultipleLoadConfig(List<ProfileItem> selecteds)
|
public async Task<RetResult> GenerateClientMultipleLoadConfig(List<ProfileItem> selecteds)
|
||||||
{
|
{
|
||||||
var ret = new RetResult();
|
var ret = new RetResult();
|
||||||
@@ -255,8 +315,8 @@ namespace ServiceLib.Services.CoreConfig
|
|||||||
|
|
||||||
ret.Msg = ResUI.InitialConfiguration;
|
ret.Msg = ResUI.InitialConfiguration;
|
||||||
|
|
||||||
string result = Utils.GetEmbedText(Global.SingboxSampleClient);
|
string result = EmbedUtils.GetEmbedText(Global.SingboxSampleClient);
|
||||||
string txtOutbound = Utils.GetEmbedText(Global.SingboxSampleOutbound);
|
string txtOutbound = EmbedUtils.GetEmbedText(Global.SingboxSampleOutbound);
|
||||||
if (Utils.IsNullOrEmpty(result) || txtOutbound.IsNullOrEmpty())
|
if (Utils.IsNullOrEmpty(result) || txtOutbound.IsNullOrEmpty())
|
||||||
{
|
{
|
||||||
ret.Msg = ResUI.FailedGetDefaultConfiguration;
|
ret.Msg = ResUI.FailedGetDefaultConfiguration;
|
||||||
@@ -539,14 +599,14 @@ namespace ServiceLib.Services.CoreConfig
|
|||||||
{
|
{
|
||||||
if (_config.TunModeItem.Mtu <= 0)
|
if (_config.TunModeItem.Mtu <= 0)
|
||||||
{
|
{
|
||||||
_config.TunModeItem.Mtu = Utils.ToInt(Global.TunMtus.First());
|
_config.TunModeItem.Mtu = Global.TunMtus.First();
|
||||||
}
|
}
|
||||||
if (Utils.IsNullOrEmpty(_config.TunModeItem.Stack))
|
if (Utils.IsNullOrEmpty(_config.TunModeItem.Stack))
|
||||||
{
|
{
|
||||||
_config.TunModeItem.Stack = Global.TunStacks.First();
|
_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.interface_name = Utils.IsOSX() ? $"utun{new Random().Next(99)}" : "singbox_tun";
|
||||||
tunInbound.mtu = _config.TunModeItem.Mtu;
|
tunInbound.mtu = _config.TunModeItem.Mtu;
|
||||||
tunInbound.strict_route = _config.TunModeItem.StrictRoute;
|
tunInbound.strict_route = _config.TunModeItem.StrictRoute;
|
||||||
@@ -685,7 +745,7 @@ namespace ServiceLib.Services.CoreConfig
|
|||||||
outbound.peer_public_key = node.PublicKey;
|
outbound.peer_public_key = node.PublicKey;
|
||||||
outbound.reserved = Utils.String2List(node.Path)?.Select(int.Parse).ToList();
|
outbound.reserved = Utils.String2List(node.Path)?.Select(int.Parse).ToList();
|
||||||
outbound.local_address = Utils.String2List(node.RequestHost);
|
outbound.local_address = Utils.String2List(node.RequestHost);
|
||||||
outbound.mtu = Utils.ToInt(node.ShortId.IsNullOrEmpty() ? Global.TunMtus.FirstOrDefault() : node.ShortId);
|
outbound.mtu = Utils.ToInt(node.ShortId.IsNullOrEmpty() ? Global.TunMtus.First() : node.ShortId);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -867,7 +927,7 @@ namespace ServiceLib.Services.CoreConfig
|
|||||||
|
|
||||||
//current proxy
|
//current proxy
|
||||||
var outbound = singboxConfig.outbounds.First();
|
var outbound = singboxConfig.outbounds.First();
|
||||||
var txtOutbound = Utils.GetEmbedText(Global.SingboxSampleOutbound);
|
var txtOutbound = EmbedUtils.GetEmbedText(Global.SingboxSampleOutbound);
|
||||||
|
|
||||||
//Previous proxy
|
//Previous proxy
|
||||||
var prevNode = await AppHandler.Instance.GetProfileItemViaRemarks(subItem.PrevProfile);
|
var prevNode = await AppHandler.Instance.GetProfileItemViaRemarks(subItem.PrevProfile);
|
||||||
@@ -934,7 +994,7 @@ namespace ServiceLib.Services.CoreConfig
|
|||||||
{
|
{
|
||||||
singboxConfig.route.auto_detect_interface = true;
|
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)
|
if (tunRules != null)
|
||||||
{
|
{
|
||||||
singboxConfig.route.rules.AddRange(tunRules);
|
singboxConfig.route.rules.AddRange(tunRules);
|
||||||
@@ -1048,7 +1108,8 @@ namespace ServiceLib.Services.CoreConfig
|
|||||||
var countDomain = 0;
|
var countDomain = 0;
|
||||||
foreach (var it in item.Domain)
|
foreach (var it in item.Domain)
|
||||||
{
|
{
|
||||||
if (ParseV2Domain(it, rule1)) countDomain++;
|
if (ParseV2Domain(it, rule1))
|
||||||
|
countDomain++;
|
||||||
}
|
}
|
||||||
if (countDomain > 0)
|
if (countDomain > 0)
|
||||||
{
|
{
|
||||||
@@ -1062,7 +1123,8 @@ namespace ServiceLib.Services.CoreConfig
|
|||||||
var countIp = 0;
|
var countIp = 0;
|
||||||
foreach (var it in item.Ip)
|
foreach (var it in item.Ip)
|
||||||
{
|
{
|
||||||
if (ParseV2Address(it, rule2)) countIp++;
|
if (ParseV2Address(it, rule2))
|
||||||
|
countIp++;
|
||||||
}
|
}
|
||||||
if (countIp > 0)
|
if (countIp > 0)
|
||||||
{
|
{
|
||||||
@@ -1148,12 +1210,14 @@ namespace ServiceLib.Services.CoreConfig
|
|||||||
}
|
}
|
||||||
else if (address.StartsWith("geoip:"))
|
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));
|
rule.geoip?.Add(address.Substring(6));
|
||||||
}
|
}
|
||||||
else
|
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);
|
rule.ip_cidr?.Add(address);
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
@@ -1167,11 +1231,11 @@ namespace ServiceLib.Services.CoreConfig
|
|||||||
var strDNS = string.Empty;
|
var strDNS = string.Empty;
|
||||||
if (_config.TunModeItem.EnableTun)
|
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
|
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);
|
var dns4Sbox = JsonUtils.Deserialize<Dns4Sbox>(strDNS);
|
||||||
@@ -1260,7 +1324,7 @@ namespace ServiceLib.Services.CoreConfig
|
|||||||
singboxConfig.experimental.cache_file = new CacheFile4Sbox()
|
singboxConfig.experimental.cache_file = new CacheFile4Sbox()
|
||||||
{
|
{
|
||||||
enabled = true,
|
enabled = true,
|
||||||
path = Utils.GetConfigPath("cache.db")
|
path = Utils.GetBinPath("cache.db")
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1271,7 +1335,8 @@ namespace ServiceLib.Services.CoreConfig
|
|||||||
{
|
{
|
||||||
static void AddRuleSets(List<string> ruleSets, List<string>? rule_set)
|
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 geosite = "geosite";
|
||||||
var geoip = "geoip";
|
var geoip = "geoip";
|
||||||
@@ -1321,7 +1386,7 @@ namespace ServiceLib.Services.CoreConfig
|
|||||||
var routing = await ConfigHandler.GetDefaultRouting(_config);
|
var routing = await ConfigHandler.GetDefaultRouting(_config);
|
||||||
if (Utils.IsNotEmpty(routing.CustomRulesetPath4Singbox))
|
if (Utils.IsNotEmpty(routing.CustomRulesetPath4Singbox))
|
||||||
{
|
{
|
||||||
var result = Utils.LoadResource(routing.CustomRulesetPath4Singbox);
|
var result = EmbedUtils.LoadResource(routing.CustomRulesetPath4Singbox);
|
||||||
if (Utils.IsNotEmpty(result))
|
if (Utils.IsNotEmpty(result))
|
||||||
{
|
{
|
||||||
customRulesets = (JsonUtils.Deserialize<List<Ruleset4Sbox>>(result) ?? [])
|
customRulesets = (JsonUtils.Deserialize<List<Ruleset4Sbox>>(result) ?? [])
|
||||||
@@ -1339,7 +1404,8 @@ namespace ServiceLib.Services.CoreConfig
|
|||||||
singboxConfig.route.rule_set = [];
|
singboxConfig.route.rule_set = [];
|
||||||
foreach (var item in new HashSet<string>(ruleSets))
|
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));
|
var customRuleset = customRulesets.FirstOrDefault(t => t.tag != null && t.tag.Equals(item));
|
||||||
if (customRuleset is null)
|
if (customRuleset is null)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
using System.Net;
|
using System.Net;
|
||||||
using System.Net.NetworkInformation;
|
using System.Net.NetworkInformation;
|
||||||
using System.Text.Json.Nodes;
|
using System.Text.Json.Nodes;
|
||||||
|
|
||||||
@@ -36,7 +36,7 @@ namespace ServiceLib.Services.CoreConfig
|
|||||||
|
|
||||||
ret.Msg = ResUI.InitialConfiguration;
|
ret.Msg = ResUI.InitialConfiguration;
|
||||||
|
|
||||||
var result = Utils.GetEmbedText(Global.V2raySampleClient);
|
var result = EmbedUtils.GetEmbedText(Global.V2raySampleClient);
|
||||||
if (Utils.IsNullOrEmpty(result))
|
if (Utils.IsNullOrEmpty(result))
|
||||||
{
|
{
|
||||||
ret.Msg = ResUI.FailedGetDefaultConfiguration;
|
ret.Msg = ResUI.FailedGetDefaultConfiguration;
|
||||||
@@ -91,8 +91,8 @@ namespace ServiceLib.Services.CoreConfig
|
|||||||
|
|
||||||
ret.Msg = ResUI.InitialConfiguration;
|
ret.Msg = ResUI.InitialConfiguration;
|
||||||
|
|
||||||
string result = Utils.GetEmbedText(Global.V2raySampleClient);
|
string result = EmbedUtils.GetEmbedText(Global.V2raySampleClient);
|
||||||
string txtOutbound = Utils.GetEmbedText(Global.V2raySampleOutbound);
|
string txtOutbound = EmbedUtils.GetEmbedText(Global.V2raySampleOutbound);
|
||||||
if (Utils.IsNullOrEmpty(result) || txtOutbound.IsNullOrEmpty())
|
if (Utils.IsNullOrEmpty(result) || txtOutbound.IsNullOrEmpty())
|
||||||
{
|
{
|
||||||
ret.Msg = ResUI.FailedGetDefaultConfiguration;
|
ret.Msg = ResUI.FailedGetDefaultConfiguration;
|
||||||
@@ -214,8 +214,8 @@ namespace ServiceLib.Services.CoreConfig
|
|||||||
|
|
||||||
ret.Msg = ResUI.InitialConfiguration;
|
ret.Msg = ResUI.InitialConfiguration;
|
||||||
|
|
||||||
var result = Utils.GetEmbedText(Global.V2raySampleClient);
|
var result = EmbedUtils.GetEmbedText(Global.V2raySampleClient);
|
||||||
var txtOutbound = Utils.GetEmbedText(Global.V2raySampleOutbound);
|
var txtOutbound = EmbedUtils.GetEmbedText(Global.V2raySampleOutbound);
|
||||||
if (Utils.IsNullOrEmpty(result) || txtOutbound.IsNullOrEmpty())
|
if (Utils.IsNullOrEmpty(result) || txtOutbound.IsNullOrEmpty())
|
||||||
{
|
{
|
||||||
ret.Msg = ResUI.FailedGetDefaultConfiguration;
|
ret.Msg = ResUI.FailedGetDefaultConfiguration;
|
||||||
@@ -353,6 +353,64 @@ namespace ServiceLib.Services.CoreConfig
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public async Task<RetResult> GenerateClientSpeedtestConfig(ProfileItem node, int port)
|
||||||
|
{
|
||||||
|
var ret = new RetResult();
|
||||||
|
try
|
||||||
|
{
|
||||||
|
if (node is not { Port: > 0 })
|
||||||
|
{
|
||||||
|
ret.Msg = ResUI.CheckServerSettings;
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (node.GetNetwork() is nameof(ETransport.quic))
|
||||||
|
{
|
||||||
|
ret.Msg = ResUI.Incorrectconfiguration + $" - {node.GetNetwork()}";
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
var result = EmbedUtils.GetEmbedText(Global.V2raySampleClient);
|
||||||
|
if (Utils.IsNullOrEmpty(result))
|
||||||
|
{
|
||||||
|
ret.Msg = ResUI.FailedGetDefaultConfiguration;
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
var v2rayConfig = JsonUtils.Deserialize<V2rayConfig>(result);
|
||||||
|
if (v2rayConfig == null)
|
||||||
|
{
|
||||||
|
ret.Msg = ResUI.FailedGenDefaultConfiguration;
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
await GenLog(v2rayConfig);
|
||||||
|
await GenOutbound(node, v2rayConfig.outbounds.First());
|
||||||
|
await GenMoreOutbounds(node, v2rayConfig);
|
||||||
|
|
||||||
|
v2rayConfig.routing.rules.Clear();
|
||||||
|
v2rayConfig.inbounds.Clear();
|
||||||
|
v2rayConfig.inbounds.Add(new()
|
||||||
|
{
|
||||||
|
tag = $"{EInboundProtocol.socks}{port}",
|
||||||
|
listen = Global.Loopback,
|
||||||
|
port = port,
|
||||||
|
protocol = EInboundProtocol.socks.ToString(),
|
||||||
|
});
|
||||||
|
|
||||||
|
ret.Msg = string.Format(ResUI.SuccessfulConfiguration, "");
|
||||||
|
ret.Success = true;
|
||||||
|
ret.Data = JsonUtils.Serialize(v2rayConfig);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
Logging.SaveLog(_tag, ex);
|
||||||
|
ret.Msg = ResUI.FailedGenDefaultConfiguration;
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#endregion public gen function
|
#endregion public gen function
|
||||||
|
|
||||||
#region private gen function
|
#region private gen function
|
||||||
@@ -428,7 +486,7 @@ namespace ServiceLib.Services.CoreConfig
|
|||||||
|
|
||||||
private Inbounds4Ray GetInbound(InItem inItem, EInboundProtocol protocol, bool bSocks)
|
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))
|
if (Utils.IsNullOrEmpty(result))
|
||||||
{
|
{
|
||||||
return new();
|
return new();
|
||||||
@@ -992,7 +1050,7 @@ namespace ServiceLib.Services.CoreConfig
|
|||||||
};
|
};
|
||||||
|
|
||||||
//request Host
|
//request Host
|
||||||
string request = Utils.GetEmbedText(Global.V2raySampleHttpRequestFileName);
|
string request = EmbedUtils.GetEmbedText(Global.V2raySampleHttpRequestFileName);
|
||||||
string[] arrHost = host.Split(',');
|
string[] arrHost = host.Split(',');
|
||||||
string host2 = string.Join(",".AppendQuotes(), arrHost);
|
string host2 = string.Join(",".AppendQuotes(), arrHost);
|
||||||
request = request.Replace("$requestHost$", $"{host2.AppendQuotes()}");
|
request = request.Replace("$requestHost$", $"{host2.AppendQuotes()}");
|
||||||
@@ -1028,7 +1086,7 @@ namespace ServiceLib.Services.CoreConfig
|
|||||||
var domainStrategy4Freedom = item?.DomainStrategy4Freedom;
|
var domainStrategy4Freedom = item?.DomainStrategy4Freedom;
|
||||||
if (Utils.IsNullOrEmpty(normalDNS))
|
if (Utils.IsNullOrEmpty(normalDNS))
|
||||||
{
|
{
|
||||||
normalDNS = Utils.GetEmbedText(Global.DNSV2rayNormalFileName);
|
normalDNS = EmbedUtils.GetEmbedText(Global.DNSV2rayNormalFileName);
|
||||||
}
|
}
|
||||||
|
|
||||||
//Outbound Freedom domainStrategy
|
//Outbound Freedom domainStrategy
|
||||||
@@ -1196,7 +1254,7 @@ namespace ServiceLib.Services.CoreConfig
|
|||||||
|
|
||||||
//current proxy
|
//current proxy
|
||||||
var outbound = v2rayConfig.outbounds.First();
|
var outbound = v2rayConfig.outbounds.First();
|
||||||
var txtOutbound = Utils.GetEmbedText(Global.V2raySampleOutbound);
|
var txtOutbound = EmbedUtils.GetEmbedText(Global.V2raySampleOutbound);
|
||||||
|
|
||||||
//Previous proxy
|
//Previous proxy
|
||||||
var prevNode = await AppHandler.Instance.GetProfileItemViaRemarks(subItem.PrevProfile);
|
var prevNode = await AppHandler.Instance.GetProfileItemViaRemarks(subItem.PrevProfile);
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
using System.Diagnostics;
|
using System.Diagnostics;
|
||||||
using System.Net;
|
using System.Net;
|
||||||
using System.Net.Http.Headers;
|
using System.Net.Http.Headers;
|
||||||
using System.Net.Sockets;
|
using System.Net.Sockets;
|
||||||
@@ -222,28 +222,29 @@ namespace ServiceLib.Services
|
|||||||
|
|
||||||
public async Task<int> RunAvailabilityCheck(IWebProxy? webProxy)
|
public async Task<int> RunAvailabilityCheck(IWebProxy? webProxy)
|
||||||
{
|
{
|
||||||
|
var responseTime = -1;
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
webProxy ??= await GetWebProxy(true);
|
webProxy ??= await GetWebProxy(true);
|
||||||
|
|
||||||
try
|
|
||||||
{
|
|
||||||
var config = AppHandler.Instance.Config;
|
var config = AppHandler.Instance.Config;
|
||||||
var responseTime = await GetRealPingTime(config.SpeedTestItem.SpeedPingTestUrl, webProxy, 10);
|
|
||||||
|
for (var i = 0; i < 2; i++)
|
||||||
|
{
|
||||||
|
responseTime = await GetRealPingTime(config.SpeedTestItem.SpeedPingTestUrl, webProxy, 10);
|
||||||
|
if (responseTime > 0)
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
await Task.Delay(500);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
Logging.SaveLog(_tag, ex);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
return responseTime;
|
return responseTime;
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
|
||||||
{
|
|
||||||
Logging.SaveLog(_tag, ex);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
catch (Exception ex)
|
|
||||||
{
|
|
||||||
Logging.SaveLog(_tag, ex);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public async Task<int> GetRealPingTime(string url, IWebProxy? webProxy, int downloadTimeout)
|
public async Task<int> GetRealPingTime(string url, IWebProxy? webProxy, int downloadTimeout)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
using ReactiveUI;
|
using System.Collections.Concurrent;
|
||||||
using System.Diagnostics;
|
using System.Diagnostics;
|
||||||
using System.Net;
|
using System.Net;
|
||||||
using System.Net.Sockets;
|
using System.Net.Sockets;
|
||||||
@@ -7,17 +7,68 @@ namespace ServiceLib.Services
|
|||||||
{
|
{
|
||||||
public class SpeedtestService
|
public class SpeedtestService
|
||||||
{
|
{
|
||||||
|
private static readonly string _tag = "SpeedtestService";
|
||||||
private Config? _config;
|
private Config? _config;
|
||||||
private Action<SpeedTestResult>? _updateFunc;
|
private Action<SpeedTestResult>? _updateFunc;
|
||||||
|
private static readonly ConcurrentBag<string> _lstExitLoop = new();
|
||||||
|
|
||||||
private bool _exitLoop = false;
|
public SpeedtestService(Config config, Action<SpeedTestResult> updateFunc)
|
||||||
private static readonly string _tag = "SpeedtestService";
|
|
||||||
|
|
||||||
public SpeedtestService(Config config, List<ProfileItem> selecteds, ESpeedActionType actionType, Action<SpeedTestResult> updateFunc)
|
|
||||||
{
|
{
|
||||||
_config = config;
|
_config = config;
|
||||||
_updateFunc = updateFunc;
|
_updateFunc = updateFunc;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void RunLoop(ESpeedActionType actionType, List<ProfileItem> selecteds)
|
||||||
|
{
|
||||||
|
Task.Run(async () =>
|
||||||
|
{
|
||||||
|
await RunAsync(actionType, selecteds);
|
||||||
|
await ProfileExHandler.Instance.SaveTo();
|
||||||
|
UpdateFunc("", ResUI.SpeedtestingCompleted);
|
||||||
|
|
||||||
|
FileManager.DeleteExpiredFiles(Utils.GetBinConfigPath(), DateTime.Now.AddHours(-1));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public void ExitLoop()
|
||||||
|
{
|
||||||
|
if (_lstExitLoop.Count > 0)
|
||||||
|
{
|
||||||
|
UpdateFunc("", ResUI.SpeedtestingStop);
|
||||||
|
|
||||||
|
_lstExitLoop.Clear();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private async Task RunAsync(ESpeedActionType actionType, List<ProfileItem> selecteds)
|
||||||
|
{
|
||||||
|
var exitLoopKey = Utils.GetGuid(false);
|
||||||
|
_lstExitLoop.Add(exitLoopKey);
|
||||||
|
|
||||||
|
var lstSelected = GetClearItem(actionType, selecteds);
|
||||||
|
|
||||||
|
switch (actionType)
|
||||||
|
{
|
||||||
|
case ESpeedActionType.Tcping:
|
||||||
|
await RunTcpingAsync(lstSelected);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case ESpeedActionType.Realping:
|
||||||
|
await RunRealPingBatchAsync(lstSelected, exitLoopKey);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case ESpeedActionType.Speedtest:
|
||||||
|
await RunMixedTestAsync(lstSelected, 1, true, exitLoopKey);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case ESpeedActionType.Mixedtest:
|
||||||
|
await RunMixedTestAsync(lstSelected, _config.SpeedTestItem.MixedConcurrencyCount, true, exitLoopKey);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private List<ServerTestItem> GetClearItem(ESpeedActionType actionType, List<ProfileItem> selecteds)
|
||||||
|
{
|
||||||
var lstSelected = new List<ServerTestItem>();
|
var lstSelected = new List<ServerTestItem>();
|
||||||
foreach (var it in selecteds)
|
foreach (var it in selecteds)
|
||||||
{
|
{
|
||||||
@@ -25,16 +76,19 @@ namespace ServiceLib.Services
|
|||||||
{
|
{
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (it.Port <= 0)
|
if (it.Port <= 0)
|
||||||
{
|
{
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
lstSelected.Add(new ServerTestItem()
|
lstSelected.Add(new ServerTestItem()
|
||||||
{
|
{
|
||||||
IndexId = it.IndexId,
|
IndexId = it.IndexId,
|
||||||
Address = it.Address,
|
Address = it.Address,
|
||||||
Port = it.Port,
|
Port = it.Port,
|
||||||
ConfigType = it.ConfigType
|
ConfigType = it.ConfigType,
|
||||||
|
QueueNum = selecteds.IndexOf(it)
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -46,87 +100,26 @@ namespace ServiceLib.Services
|
|||||||
case ESpeedActionType.Tcping:
|
case ESpeedActionType.Tcping:
|
||||||
case ESpeedActionType.Realping:
|
case ESpeedActionType.Realping:
|
||||||
UpdateFunc(it.IndexId, ResUI.Speedtesting, "");
|
UpdateFunc(it.IndexId, ResUI.Speedtesting, "");
|
||||||
ProfileExHandler.Instance.SetTestDelay(it.IndexId, "0");
|
ProfileExHandler.Instance.SetTestDelay(it.IndexId, 0);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case ESpeedActionType.Speedtest:
|
case ESpeedActionType.Speedtest:
|
||||||
UpdateFunc(it.IndexId, "", ResUI.SpeedtestingWait);
|
UpdateFunc(it.IndexId, "", ResUI.SpeedtestingWait);
|
||||||
ProfileExHandler.Instance.SetTestSpeed(it.IndexId, "0");
|
ProfileExHandler.Instance.SetTestSpeed(it.IndexId, 0);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case ESpeedActionType.Mixedtest:
|
case ESpeedActionType.Mixedtest:
|
||||||
UpdateFunc(it.IndexId, ResUI.Speedtesting, ResUI.SpeedtestingWait);
|
UpdateFunc(it.IndexId, ResUI.Speedtesting, ResUI.SpeedtestingWait);
|
||||||
ProfileExHandler.Instance.SetTestDelay(it.IndexId, "0");
|
ProfileExHandler.Instance.SetTestDelay(it.IndexId, 0);
|
||||||
ProfileExHandler.Instance.SetTestSpeed(it.IndexId, "0");
|
ProfileExHandler.Instance.SetTestSpeed(it.IndexId, 0);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
MessageBus.Current.Listen<string>(EMsgCommand.StopSpeedtest.ToString()).Subscribe(ExitLoop);
|
return lstSelected;
|
||||||
|
|
||||||
Task.Run(async () => { await RunAsync(actionType, lstSelected); });
|
|
||||||
}
|
|
||||||
|
|
||||||
private async Task RunAsync(ESpeedActionType actionType, List<ServerTestItem> lstSelected)
|
|
||||||
{
|
|
||||||
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();
|
|
||||||
|
|
||||||
for (var num = 0; num < (int)Math.Ceiling(lst1.Count * 1.0 / pageSize); num++)
|
|
||||||
{
|
|
||||||
lstTest.Add(lst1.Skip(num * pageSize).Take(pageSize).ToList());
|
|
||||||
}
|
|
||||||
for (var num = 0; num < (int)Math.Ceiling(lst2.Count * 1.0 / pageSize); num++)
|
|
||||||
{
|
|
||||||
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);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private async Task RunTcpingAsync(List<ServerTestItem> selecteds)
|
private async Task RunTcpingAsync(List<ServerTestItem> selecteds)
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
{
|
||||||
List<Task> tasks = [];
|
List<Task> tasks = [];
|
||||||
foreach (var it in selecteds)
|
foreach (var it in selecteds)
|
||||||
@@ -139,11 +132,10 @@ namespace ServiceLib.Services
|
|||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
var time = await GetTcpingTime(it.Address, it.Port);
|
var responseTime = await GetTcpingTime(it.Address, it.Port);
|
||||||
var output = FormatOut(time, Global.DelayUnit);
|
|
||||||
|
|
||||||
ProfileExHandler.Instance.SetTestDelay(it.IndexId, output);
|
ProfileExHandler.Instance.SetTestDelay(it.IndexId, responseTime);
|
||||||
UpdateFunc(it.IndexId, output);
|
UpdateFunc(it.IndexId, responseTime.ToString());
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
@@ -152,18 +144,52 @@ namespace ServiceLib.Services
|
|||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
Task.WaitAll([.. tasks]);
|
Task.WaitAll([.. tasks]);
|
||||||
|
await Task.CompletedTask;
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
|
||||||
|
private async Task RunRealPingBatchAsync(List<ServerTestItem> lstSelected, string exitLoopKey, int pageSize = 0)
|
||||||
{
|
{
|
||||||
Logging.SaveLog(_tag, ex);
|
if (pageSize <= 0)
|
||||||
|
{
|
||||||
|
pageSize = lstSelected.Count < Global.SpeedTestPageSize ? lstSelected.Count : Global.SpeedTestPageSize;
|
||||||
}
|
}
|
||||||
finally
|
var lstTest = GetTestBatchItem(lstSelected, pageSize);
|
||||||
|
|
||||||
|
List<ServerTestItem> lstFailed = new();
|
||||||
|
foreach (var lst in lstTest)
|
||||||
{
|
{
|
||||||
await ProfileExHandler.Instance.SaveTo();
|
var ret = await RunRealPingAsync(lst, exitLoopKey);
|
||||||
|
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));
|
||||||
|
|
||||||
|
if (pageSizeNext > _config.SpeedTestItem.MixedConcurrencyCount)
|
||||||
|
{
|
||||||
|
await RunRealPingBatchAsync(lstFailed, exitLoopKey, pageSizeNext);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
await RunMixedTestAsync(lstSelected, _config.SpeedTestItem.MixedConcurrencyCount, false, exitLoopKey);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private async Task RunRealPingAsync(List<ServerTestItem> selecteds)
|
private async Task<bool> RunRealPingAsync(List<ServerTestItem> selecteds, string exitLoopKey)
|
||||||
{
|
{
|
||||||
var pid = -1;
|
var pid = -1;
|
||||||
try
|
try
|
||||||
@@ -171,8 +197,7 @@ namespace ServiceLib.Services
|
|||||||
pid = await CoreHandler.Instance.LoadCoreConfigSpeedtest(selecteds);
|
pid = await CoreHandler.Instance.LoadCoreConfigSpeedtest(selecteds);
|
||||||
if (pid < 0)
|
if (pid < 0)
|
||||||
{
|
{
|
||||||
UpdateFunc("", ResUI.FailedToRunCore);
|
return false;
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
var downloadHandle = new DownloadService();
|
var downloadHandle = new DownloadService();
|
||||||
@@ -190,20 +215,7 @@ namespace ServiceLib.Services
|
|||||||
}
|
}
|
||||||
tasks.Add(Task.Run(async () =>
|
tasks.Add(Task.Run(async () =>
|
||||||
{
|
{
|
||||||
try
|
await DoRealPing(downloadHandle, it);
|
||||||
{
|
|
||||||
var webProxy = new WebProxy($"socks5://{Global.Loopback}:{it.Port}");
|
|
||||||
var output = await GetRealPingTime(downloadHandle, webProxy);
|
|
||||||
|
|
||||||
ProfileExHandler.Instance.SetTestDelay(it.IndexId, output);
|
|
||||||
UpdateFunc(it.IndexId, output);
|
|
||||||
int.TryParse(output, out var delay);
|
|
||||||
it.Delay = delay;
|
|
||||||
}
|
|
||||||
catch (Exception ex)
|
|
||||||
{
|
|
||||||
Logging.SaveLog(_tag, ex);
|
|
||||||
}
|
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
Task.WaitAll(tasks.ToArray());
|
Task.WaitAll(tasks.ToArray());
|
||||||
@@ -218,151 +230,100 @@ namespace ServiceLib.Services
|
|||||||
{
|
{
|
||||||
await ProcUtils.ProcessKill(pid);
|
await ProcUtils.ProcessKill(pid);
|
||||||
}
|
}
|
||||||
await ProfileExHandler.Instance.SaveTo();
|
|
||||||
}
|
}
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
private async Task RunSpeedTestAsync(List<ServerTestItem> selecteds)
|
private async Task RunMixedTestAsync(List<ServerTestItem> selecteds, int concurrencyCount, bool blSpeedTest, string exitLoopKey)
|
||||||
{
|
{
|
||||||
var pid = -1;
|
using var concurrencySemaphore = new SemaphoreSlim(concurrencyCount);
|
||||||
pid = await CoreHandler.Instance.LoadCoreConfigSpeedtest(selecteds);
|
var downloadHandle = new DownloadService();
|
||||||
if (pid < 0)
|
List<Task> tasks = new();
|
||||||
{
|
|
||||||
UpdateFunc("", ResUI.FailedToRunCore);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
var url = _config.SpeedTestItem.SpeedTestUrl;
|
|
||||||
var timeout = _config.SpeedTestItem.SpeedTestTimeout;
|
|
||||||
|
|
||||||
DownloadService downloadHandle = new();
|
|
||||||
|
|
||||||
foreach (var it in selecteds)
|
foreach (var it in selecteds)
|
||||||
{
|
{
|
||||||
if (_exitLoop)
|
if (_lstExitLoop.Any(p => p == exitLoopKey) == false)
|
||||||
{
|
{
|
||||||
UpdateFunc(it.IndexId, "", ResUI.SpeedtestingSkip);
|
UpdateFunc(it.IndexId, "", ResUI.SpeedtestingSkip);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (!it.AllowTest)
|
|
||||||
{
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if (it.ConfigType == EConfigType.Custom)
|
if (it.ConfigType == EConfigType.Custom)
|
||||||
{
|
{
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
//if (it.delay < 0)
|
await concurrencySemaphore.WaitAsync();
|
||||||
//{
|
|
||||||
// UpdateFunc(it.indexId, "", ResUI.SpeedtestingSkip);
|
tasks.Add(Task.Run(async () =>
|
||||||
// continue;
|
{
|
||||||
//}
|
var pid = -1;
|
||||||
ProfileExHandler.Instance.SetTestSpeed(it.IndexId, "-1");
|
try
|
||||||
|
{
|
||||||
|
pid = await CoreHandler.Instance.LoadCoreConfigSpeedtest(it);
|
||||||
|
if (pid > 0)
|
||||||
|
{
|
||||||
|
await Task.Delay(500);
|
||||||
|
var delay = await DoRealPing(downloadHandle, it);
|
||||||
|
if (blSpeedTest)
|
||||||
|
{
|
||||||
|
if (delay > 0)
|
||||||
|
{
|
||||||
|
await DoSpeedTest(downloadHandle, it);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
UpdateFunc(it.IndexId, "", ResUI.SpeedtestingSkip);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
UpdateFunc(it.IndexId, "", ResUI.FailedToRunCore);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
Logging.SaveLog(_tag, ex);
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
if (pid > 0)
|
||||||
|
{
|
||||||
|
await ProcUtils.ProcessKill(pid);
|
||||||
|
}
|
||||||
|
concurrencySemaphore.Release();
|
||||||
|
}
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
Task.WaitAll(tasks.ToArray());
|
||||||
|
}
|
||||||
|
|
||||||
|
private async Task<int> DoRealPing(DownloadService downloadHandle, ServerTestItem it)
|
||||||
|
{
|
||||||
|
var webProxy = new WebProxy($"socks5://{Global.Loopback}:{it.Port}");
|
||||||
|
var responseTime = await downloadHandle.GetRealPingTime(_config.SpeedTestItem.SpeedPingTestUrl, webProxy, 10);
|
||||||
|
|
||||||
|
ProfileExHandler.Instance.SetTestDelay(it.IndexId, responseTime);
|
||||||
|
UpdateFunc(it.IndexId, responseTime.ToString());
|
||||||
|
return responseTime;
|
||||||
|
}
|
||||||
|
|
||||||
|
private async Task DoSpeedTest(DownloadService downloadHandle, ServerTestItem it)
|
||||||
|
{
|
||||||
UpdateFunc(it.IndexId, "", ResUI.Speedtesting);
|
UpdateFunc(it.IndexId, "", ResUI.Speedtesting);
|
||||||
|
|
||||||
var item = await AppHandler.Instance.GetProfileItem(it.IndexId);
|
|
||||||
if (item is null) continue;
|
|
||||||
|
|
||||||
var webProxy = new WebProxy($"socks5://{Global.Loopback}:{it.Port}");
|
var webProxy = new WebProxy($"socks5://{Global.Loopback}:{it.Port}");
|
||||||
|
var url = _config.SpeedTestItem.SpeedTestUrl;
|
||||||
|
var timeout = _config.SpeedTestItem.SpeedTestTimeout;
|
||||||
await downloadHandle.DownloadDataAsync(url, webProxy, timeout, (success, msg) =>
|
await downloadHandle.DownloadDataAsync(url, webProxy, timeout, (success, msg) =>
|
||||||
{
|
{
|
||||||
decimal.TryParse(msg, out var dec);
|
decimal.TryParse(msg, out var dec);
|
||||||
if (dec > 0)
|
if (dec > 0)
|
||||||
{
|
{
|
||||||
ProfileExHandler.Instance.SetTestSpeed(it.IndexId, msg);
|
ProfileExHandler.Instance.SetTestSpeed(it.IndexId, dec);
|
||||||
}
|
}
|
||||||
UpdateFunc(it.IndexId, "", msg);
|
UpdateFunc(it.IndexId, "", msg);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
if (pid > 0)
|
|
||||||
{
|
|
||||||
await ProcUtils.ProcessKill(pid);
|
|
||||||
}
|
|
||||||
await ProfileExHandler.Instance.SaveTo();
|
|
||||||
}
|
|
||||||
|
|
||||||
private async Task RunSpeedTestMulti(List<ServerTestItem> selecteds)
|
|
||||||
{
|
|
||||||
var pid = -1;
|
|
||||||
pid = await CoreHandler.Instance.LoadCoreConfigSpeedtest(selecteds);
|
|
||||||
if (pid < 0)
|
|
||||||
{
|
|
||||||
UpdateFunc("", ResUI.FailedToRunCore);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
var url = _config.SpeedTestItem.SpeedTestUrl;
|
|
||||||
var timeout = _config.SpeedTestItem.SpeedTestTimeout;
|
|
||||||
|
|
||||||
DownloadService downloadHandle = new();
|
|
||||||
|
|
||||||
foreach (var it in selecteds)
|
|
||||||
{
|
|
||||||
if (_exitLoop)
|
|
||||||
{
|
|
||||||
UpdateFunc(it.IndexId, "", ResUI.SpeedtestingSkip);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!it.AllowTest)
|
|
||||||
{
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if (it.ConfigType == EConfigType.Custom)
|
|
||||||
{
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if (it.Delay < 0)
|
|
||||||
{
|
|
||||||
UpdateFunc(it.IndexId, "", ResUI.SpeedtestingSkip);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
ProfileExHandler.Instance.SetTestSpeed(it.IndexId, "-1");
|
|
||||||
UpdateFunc(it.IndexId, "", ResUI.Speedtesting);
|
|
||||||
|
|
||||||
var item = await AppHandler.Instance.GetProfileItem(it.IndexId);
|
|
||||||
if (item is null) continue;
|
|
||||||
|
|
||||||
var webProxy = new WebProxy($"socks5://{Global.Loopback}:{it.Port}");
|
|
||||||
_ = downloadHandle.DownloadDataAsync(url, webProxy, timeout, (success, msg) =>
|
|
||||||
{
|
|
||||||
decimal.TryParse(msg, out var dec);
|
|
||||||
if (dec > 0)
|
|
||||||
{
|
|
||||||
ProfileExHandler.Instance.SetTestSpeed(it.IndexId, msg);
|
|
||||||
}
|
|
||||||
UpdateFunc(it.IndexId, "", msg);
|
|
||||||
});
|
|
||||||
await Task.Delay(2000);
|
|
||||||
}
|
|
||||||
|
|
||||||
await Task.Delay((timeout + 2) * 1000);
|
|
||||||
|
|
||||||
if (pid > 0)
|
|
||||||
{
|
|
||||||
await ProcUtils.ProcessKill(pid);
|
|
||||||
}
|
|
||||||
await ProfileExHandler.Instance.SaveTo();
|
|
||||||
}
|
|
||||||
|
|
||||||
private async Task RunMixedTestAsync(List<ServerTestItem> selecteds)
|
|
||||||
{
|
|
||||||
await RunRealPingAsync(selecteds);
|
|
||||||
|
|
||||||
await Task.Delay(1000);
|
|
||||||
|
|
||||||
await RunSpeedTestMulti(selecteds);
|
|
||||||
}
|
|
||||||
|
|
||||||
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);
|
|
||||||
}
|
|
||||||
|
|
||||||
private async Task<int> GetTcpingTime(string url, int port)
|
private async Task<int> GetTcpingTime(string url, int port)
|
||||||
{
|
{
|
||||||
var responseTime = -1;
|
var responseTime = -1;
|
||||||
@@ -375,18 +336,19 @@ namespace ServiceLib.Services
|
|||||||
ipAddress = ipHostInfo.AddressList.First();
|
ipAddress = ipHostInfo.AddressList.First();
|
||||||
}
|
}
|
||||||
|
|
||||||
var timer = Stopwatch.StartNew();
|
|
||||||
|
|
||||||
IPEndPoint endPoint = new(ipAddress, port);
|
IPEndPoint endPoint = new(ipAddress, port);
|
||||||
using Socket clientSocket = new(endPoint.AddressFamily, SocketType.Stream, ProtocolType.Tcp);
|
using Socket clientSocket = new(endPoint.AddressFamily, SocketType.Stream, ProtocolType.Tcp);
|
||||||
|
|
||||||
|
var timer = Stopwatch.StartNew();
|
||||||
var result = clientSocket.BeginConnect(endPoint, null, null);
|
var result = clientSocket.BeginConnect(endPoint, null, null);
|
||||||
if (!result.AsyncWaitHandle.WaitOne(TimeSpan.FromSeconds(5)))
|
if (!result.AsyncWaitHandle.WaitOne(TimeSpan.FromSeconds(5)))
|
||||||
|
{
|
||||||
throw new TimeoutException("connect timeout (5s): " + url);
|
throw new TimeoutException("connect timeout (5s): " + url);
|
||||||
clientSocket.EndConnect(result);
|
}
|
||||||
|
|
||||||
timer.Stop();
|
timer.Stop();
|
||||||
responseTime = (int)timer.Elapsed.TotalMilliseconds;
|
responseTime = (int)timer.Elapsed.TotalMilliseconds;
|
||||||
|
|
||||||
|
clientSocket.EndConnect(result);
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
@@ -395,14 +357,31 @@ namespace ServiceLib.Services
|
|||||||
return responseTime;
|
return responseTime;
|
||||||
}
|
}
|
||||||
|
|
||||||
private string FormatOut(object time, string unit)
|
private List<List<ServerTestItem>> GetTestBatchItem(List<ServerTestItem> lstSelected, int pageSize)
|
||||||
{
|
{
|
||||||
return $"{time}";
|
List<List<ServerTestItem>> lstTest = new();
|
||||||
|
var lst1 = lstSelected.Where(t => t.ConfigType is not (EConfigType.Hysteria2 or EConfigType.TUIC or EConfigType.WireGuard)).ToList();
|
||||||
|
var lst2 = lstSelected.Where(t => t.ConfigType is EConfigType.Hysteria2 or EConfigType.TUIC or EConfigType.WireGuard).ToList();
|
||||||
|
|
||||||
|
for (var num = 0; num < (int)Math.Ceiling(lst1.Count * 1.0 / pageSize); num++)
|
||||||
|
{
|
||||||
|
lstTest.Add(lst1.Skip(num * pageSize).Take(pageSize).ToList());
|
||||||
|
}
|
||||||
|
for (var num = 0; num < (int)Math.Ceiling(lst2.Count * 1.0 / pageSize); num++)
|
||||||
|
{
|
||||||
|
lstTest.Add(lst2.Skip(num * pageSize).Take(pageSize).ToList());
|
||||||
|
}
|
||||||
|
|
||||||
|
return lstTest;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void UpdateFunc(string indexId, string delay, string speed = "")
|
private void UpdateFunc(string indexId, string delay, string speed = "")
|
||||||
{
|
{
|
||||||
_updateFunc?.Invoke(new() { IndexId = indexId, Delay = delay, Speed = speed });
|
_updateFunc?.Invoke(new() { IndexId = indexId, Delay = delay, Speed = speed });
|
||||||
|
if (indexId.IsNotEmpty() && speed.IsNotEmpty())
|
||||||
|
{
|
||||||
|
ProfileExHandler.Instance.SetTestMessage(indexId, speed);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
using System.Net.WebSockets;
|
using System.Net.WebSockets;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
|
|
||||||
namespace ServiceLib.Services.Statistics
|
namespace ServiceLib.Services.Statistics
|
||||||
@@ -21,7 +21,7 @@ namespace ServiceLib.Services.Statistics
|
|||||||
Task.Run(Run);
|
Task.Run(Run);
|
||||||
}
|
}
|
||||||
|
|
||||||
private async void Init()
|
private async Task Init()
|
||||||
{
|
{
|
||||||
await Task.Delay(5000);
|
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)
|
while (!_exitFlag)
|
||||||
{
|
{
|
||||||
@@ -73,7 +73,7 @@ namespace ServiceLib.Services.Statistics
|
|||||||
{
|
{
|
||||||
webSocket.Abort();
|
webSocket.Abort();
|
||||||
webSocket = null;
|
webSocket = null;
|
||||||
Init();
|
await Init();
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -109,7 +109,8 @@ namespace ServiceLib.Services.Statistics
|
|||||||
|
|
||||||
private void ParseOutput(string source, out ulong up, out ulong down)
|
private void ParseOutput(string source, out ulong up, out ulong down)
|
||||||
{
|
{
|
||||||
up = 0; down = 0;
|
up = 0;
|
||||||
|
down = 0;
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
var trafficItem = JsonUtils.Deserialize<TrafficItem>(source);
|
var trafficItem = JsonUtils.Deserialize<TrafficItem>(source);
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
namespace ServiceLib.Services.Statistics
|
namespace ServiceLib.Services.Statistics
|
||||||
{
|
{
|
||||||
public class StatisticsXrayService
|
public class StatisticsXrayService
|
||||||
{
|
{
|
||||||
@@ -23,7 +23,7 @@
|
|||||||
_exitFlag = true;
|
_exitFlag = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
private async void Run()
|
private async Task Run()
|
||||||
{
|
{
|
||||||
while (!_exitFlag)
|
while (!_exitFlag)
|
||||||
{
|
{
|
||||||
@@ -63,7 +63,8 @@
|
|||||||
foreach (string key in source.stats.outbound.Keys)
|
foreach (string key in source.stats.outbound.Keys)
|
||||||
{
|
{
|
||||||
var value = source.stats.outbound[key];
|
var value = source.stats.outbound[key];
|
||||||
if (value == null) continue;
|
if (value == null)
|
||||||
|
continue;
|
||||||
var state = JsonUtils.Deserialize<V2rayMetricsVarsLink>(value.ToString());
|
var state = JsonUtils.Deserialize<V2rayMetricsVarsLink>(value.ToString());
|
||||||
|
|
||||||
if (key.StartsWith(Global.ProxyTag))
|
if (key.StartsWith(Global.ProxyTag))
|
||||||
|
|||||||
@@ -237,13 +237,13 @@ namespace ServiceLib.Services
|
|||||||
|
|
||||||
public async Task UpdateGeoFileAll(Config config, Action<bool, string> updateFunc)
|
public async Task UpdateGeoFileAll(Config config, Action<bool, string> updateFunc)
|
||||||
{
|
{
|
||||||
await UpdateGeoFile("geosite", config, updateFunc);
|
await UpdateGeoFiles(config, updateFunc);
|
||||||
await UpdateGeoFile("geoip", config, updateFunc);
|
await UpdateOtherFiles(config, updateFunc);
|
||||||
await UpdateSrsFileAll(config, updateFunc);
|
await UpdateSrsFileAll(config, updateFunc);
|
||||||
_updateFunc?.Invoke(true, string.Format(ResUI.MsgDownloadGeoFileSuccessfully, "geo"));
|
_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 downloadHandle = new DownloadService();
|
||||||
var time = await downloadHandle.RunAvailabilityCheck(null);
|
var time = await downloadHandle.RunAvailabilityCheck(null);
|
||||||
@@ -255,7 +255,7 @@ namespace ServiceLib.Services
|
|||||||
ip = $"({ipInfo?.country_code}) {ipInfo?.ip}";
|
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
|
#region CheckUpdate private
|
||||||
@@ -368,6 +368,7 @@ namespace ServiceLib.Services
|
|||||||
try
|
try
|
||||||
{
|
{
|
||||||
var coreInfo = CoreInfoHandler.Instance.GetCoreInfo(type);
|
var coreInfo = CoreInfoHandler.Instance.GetCoreInfo(type);
|
||||||
|
var coreUrl = await GetUrlFromCore(coreInfo) ?? string.Empty;
|
||||||
SemanticVersion curVersion;
|
SemanticVersion curVersion;
|
||||||
string message;
|
string message;
|
||||||
string? url;
|
string? url;
|
||||||
@@ -379,28 +380,28 @@ namespace ServiceLib.Services
|
|||||||
{
|
{
|
||||||
curVersion = await GetCoreVersion(type);
|
curVersion = await GetCoreVersion(type);
|
||||||
message = string.Format(ResUI.IsLatestCore, type, curVersion.ToVersionString("v"));
|
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;
|
break;
|
||||||
}
|
}
|
||||||
case ECoreType.mihomo:
|
case ECoreType.mihomo:
|
||||||
{
|
{
|
||||||
curVersion = await GetCoreVersion(type);
|
curVersion = await GetCoreVersion(type);
|
||||||
message = string.Format(ResUI.IsLatestCore, type, curVersion);
|
message = string.Format(ResUI.IsLatestCore, type, curVersion);
|
||||||
url = string.Format(GetUrlFromCore(coreInfo), version.ToVersionString("v"));
|
url = string.Format(coreUrl, version.ToVersionString("v"));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case ECoreType.sing_box:
|
case ECoreType.sing_box:
|
||||||
{
|
{
|
||||||
curVersion = await GetCoreVersion(type);
|
curVersion = await GetCoreVersion(type);
|
||||||
message = string.Format(ResUI.IsLatestCore, type, curVersion.ToVersionString("v"));
|
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;
|
break;
|
||||||
}
|
}
|
||||||
case ECoreType.v2rayN:
|
case ECoreType.v2rayN:
|
||||||
{
|
{
|
||||||
curVersion = new SemanticVersion(Utils.GetVersionInfo());
|
curVersion = new SemanticVersion(Utils.GetVersionInfo());
|
||||||
message = string.Format(ResUI.IsLatestN, type, curVersion);
|
message = string.Format(ResUI.IsLatestN, type, curVersion);
|
||||||
url = string.Format(GetUrlFromCore(coreInfo), version);
|
url = string.Format(coreUrl, version);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
@@ -422,25 +423,36 @@ namespace ServiceLib.Services
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private string? GetUrlFromCore(CoreInfo? coreInfo)
|
private async Task<string?> GetUrlFromCore(CoreInfo? coreInfo)
|
||||||
{
|
{
|
||||||
if (Utils.IsWindows())
|
if (Utils.IsWindows())
|
||||||
{
|
{
|
||||||
//Check for standalone windows .Net version
|
var url = RuntimeInformation.ProcessArchitecture switch
|
||||||
if (coreInfo?.CoreType == ECoreType.v2rayN
|
|
||||||
&& File.Exists(Path.Combine(Utils.StartupPath(), "wpfgfx_cor3.dll"))
|
|
||||||
&& File.Exists(Path.Combine(Utils.StartupPath(), "D3DCompiler_47_cor3.dll"))
|
|
||||||
)
|
|
||||||
{
|
|
||||||
return coreInfo?.DownloadUrlWin64?.Replace(".zip", "-SelfContained.zip");
|
|
||||||
}
|
|
||||||
|
|
||||||
return RuntimeInformation.ProcessArchitecture switch
|
|
||||||
{
|
{
|
||||||
Architecture.Arm64 => coreInfo?.DownloadUrlWinArm64,
|
Architecture.Arm64 => coreInfo?.DownloadUrlWinArm64,
|
||||||
Architecture.X64 => coreInfo?.DownloadUrlWin64,
|
Architecture.X64 => coreInfo?.DownloadUrlWin64,
|
||||||
_ => null,
|
_ => null,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
if (coreInfo?.CoreType != ECoreType.v2rayN)
|
||||||
|
{
|
||||||
|
return url;
|
||||||
|
}
|
||||||
|
|
||||||
|
//Check for standalone windows .Net version
|
||||||
|
if (File.Exists(Path.Combine(Utils.GetBaseDirectory(), "wpfgfx_cor3.dll"))
|
||||||
|
&& File.Exists(Path.Combine(Utils.GetBaseDirectory(), "D3DCompiler_47_cor3.dll")))
|
||||||
|
{
|
||||||
|
return url?.Replace(".zip", "-SelfContained.zip");
|
||||||
|
}
|
||||||
|
|
||||||
|
//Check for avalonia desktop windows version
|
||||||
|
if (File.Exists(Path.Combine(Utils.GetBaseDirectory(), "libHarfBuzzSharp.dll")))
|
||||||
|
{
|
||||||
|
return url?.Replace(".zip", "-desktop.zip");
|
||||||
|
}
|
||||||
|
|
||||||
|
return url;
|
||||||
}
|
}
|
||||||
else if (Utils.IsLinux())
|
else if (Utils.IsLinux())
|
||||||
{
|
{
|
||||||
@@ -460,14 +472,14 @@ namespace ServiceLib.Services
|
|||||||
_ => null,
|
_ => null,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
return null;
|
return await Task.FromResult("");
|
||||||
}
|
}
|
||||||
|
|
||||||
#endregion CheckUpdate private
|
#endregion CheckUpdate private
|
||||||
|
|
||||||
#region Geo private
|
#region Geo private
|
||||||
|
|
||||||
private async Task UpdateGeoFile(string geoName, Config config, Action<bool, string> updateFunc)
|
private async Task UpdateGeoFiles(Config config, Action<bool, string> updateFunc)
|
||||||
{
|
{
|
||||||
_updateFunc = updateFunc;
|
_updateFunc = updateFunc;
|
||||||
|
|
||||||
@@ -475,12 +487,29 @@ namespace ServiceLib.Services
|
|||||||
? Global.GeoUrl
|
? Global.GeoUrl
|
||||||
: config.ConstItem.GeoSourceUrl;
|
: config.ConstItem.GeoSourceUrl;
|
||||||
|
|
||||||
|
List<string> files = ["geosite", "geoip"];
|
||||||
|
foreach (var geoName in files)
|
||||||
|
{
|
||||||
var fileName = $"{geoName}.dat";
|
var fileName = $"{geoName}.dat";
|
||||||
var targetPath = Utils.GetBinPath($"{fileName}");
|
var targetPath = Utils.GetBinPath($"{fileName}");
|
||||||
var url = string.Format(geoUrl, geoName);
|
var url = string.Format(geoUrl, geoName);
|
||||||
|
|
||||||
await DownloadGeoFile(url, fileName, targetPath, updateFunc);
|
await DownloadGeoFile(url, fileName, targetPath, updateFunc);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private async Task UpdateOtherFiles(Config config, Action<bool, string> updateFunc)
|
||||||
|
{
|
||||||
|
_updateFunc = updateFunc;
|
||||||
|
|
||||||
|
foreach (var url in Global.OtherGeoUrls)
|
||||||
|
{
|
||||||
|
var fileName = Path.GetFileName(url);
|
||||||
|
var targetPath = Utils.GetBinPath($"{fileName}");
|
||||||
|
|
||||||
|
await DownloadGeoFile(url, fileName, targetPath, updateFunc);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private async Task UpdateSrsFileAll(Config config, Action<bool, string> updateFunc)
|
private async Task UpdateSrsFileAll(Config config, Action<bool, string> updateFunc)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
|
using System.Reactive;
|
||||||
using ReactiveUI;
|
using ReactiveUI;
|
||||||
using ReactiveUI.Fody.Helpers;
|
using ReactiveUI.Fody.Helpers;
|
||||||
using System.Reactive;
|
|
||||||
|
|
||||||
namespace ServiceLib.ViewModels
|
namespace ServiceLib.ViewModels
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
using ReactiveUI;
|
|
||||||
using ReactiveUI.Fody.Helpers;
|
|
||||||
using System.Reactive;
|
using System.Reactive;
|
||||||
|
using ReactiveUI;
|
||||||
|
using ReactiveUI.Fody.Helpers;
|
||||||
|
|
||||||
namespace ServiceLib.ViewModels
|
namespace ServiceLib.ViewModels
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
using ReactiveUI;
|
using System.Reactive;
|
||||||
|
using ReactiveUI;
|
||||||
using ReactiveUI.Fody.Helpers;
|
using ReactiveUI.Fody.Helpers;
|
||||||
using Splat;
|
using Splat;
|
||||||
using System.Reactive;
|
|
||||||
|
|
||||||
namespace ServiceLib.ViewModels
|
namespace ServiceLib.ViewModels
|
||||||
{
|
{
|
||||||
@@ -173,7 +173,7 @@ namespace ServiceLib.ViewModels
|
|||||||
var configDirZipTemp = Utils.GetTempPath($"v2rayN_{DateTime.Now:yyyyMMddHHmmss}");
|
var configDirZipTemp = Utils.GetTempPath($"v2rayN_{DateTime.Now:yyyyMMddHHmmss}");
|
||||||
var configDirTemp = Path.Combine(configDirZipTemp, _guiConfigs);
|
var configDirTemp = Path.Combine(configDirZipTemp, _guiConfigs);
|
||||||
|
|
||||||
FileManager.CopyDirectory(configDir, configDirTemp, false, "cache.db");
|
FileManager.CopyDirectory(configDir, configDirTemp, false, true, "");
|
||||||
var ret = FileManager.CreateFromDirectory(configDirZipTemp, fileName);
|
var ret = FileManager.CreateFromDirectory(configDirZipTemp, fileName);
|
||||||
Directory.Delete(configDirZipTemp, true);
|
Directory.Delete(configDirZipTemp, true);
|
||||||
return await Task.FromResult(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 DynamicData.Binding;
|
||||||
using ReactiveUI;
|
using ReactiveUI;
|
||||||
using ReactiveUI.Fody.Helpers;
|
using ReactiveUI.Fody.Helpers;
|
||||||
using Splat;
|
using Splat;
|
||||||
using System.Reactive;
|
|
||||||
using System.Runtime.InteropServices;
|
|
||||||
|
|
||||||
namespace ServiceLib.ViewModels
|
namespace ServiceLib.ViewModels
|
||||||
{
|
{
|
||||||
@@ -46,10 +46,14 @@ namespace ServiceLib.ViewModels
|
|||||||
if (RuntimeInformation.ProcessArchitecture != Architecture.X86)
|
if (RuntimeInformation.ProcessArchitecture != Architecture.X86)
|
||||||
{
|
{
|
||||||
_checkUpdateModel.Add(GetCheckUpdateModel(_v2rayN));
|
_checkUpdateModel.Add(GetCheckUpdateModel(_v2rayN));
|
||||||
|
//Not Windows and under Win10
|
||||||
|
if (!(Utils.IsWindows() && Environment.OSVersion.Version.Major < 10))
|
||||||
|
{
|
||||||
_checkUpdateModel.Add(GetCheckUpdateModel(ECoreType.Xray.ToString()));
|
_checkUpdateModel.Add(GetCheckUpdateModel(ECoreType.Xray.ToString()));
|
||||||
_checkUpdateModel.Add(GetCheckUpdateModel(ECoreType.mihomo.ToString()));
|
_checkUpdateModel.Add(GetCheckUpdateModel(ECoreType.mihomo.ToString()));
|
||||||
_checkUpdateModel.Add(GetCheckUpdateModel(ECoreType.sing_box.ToString()));
|
_checkUpdateModel.Add(GetCheckUpdateModel(ECoreType.sing_box.ToString()));
|
||||||
}
|
}
|
||||||
|
}
|
||||||
_checkUpdateModel.Add(GetCheckUpdateModel(_geo));
|
_checkUpdateModel.Add(GetCheckUpdateModel(_geo));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -79,7 +83,8 @@ namespace ServiceLib.ViewModels
|
|||||||
for (var k = _checkUpdateModel.Count - 1; k >= 0; k--)
|
for (var k = _checkUpdateModel.Count - 1; k >= 0; k--)
|
||||||
{
|
{
|
||||||
var item = _checkUpdateModel[k];
|
var item = _checkUpdateModel[k];
|
||||||
if (item.IsSelected != true) continue;
|
if (item.IsSelected != true)
|
||||||
|
continue;
|
||||||
|
|
||||||
UpdateView(item.CoreType, "...");
|
UpdateView(item.CoreType, "...");
|
||||||
if (item.CoreType == _geo)
|
if (item.CoreType == _geo)
|
||||||
@@ -248,7 +253,7 @@ namespace ServiceLib.ViewModels
|
|||||||
{
|
{
|
||||||
foreach (var subDir in dir.GetDirectories())
|
foreach (var subDir in dir.GetDirectories())
|
||||||
{
|
{
|
||||||
FileManager.CopyDirectory(subDir.FullName, toPath, false, null);
|
FileManager.CopyDirectory(subDir.FullName, toPath, false, true);
|
||||||
subDir.Delete(true);
|
subDir.Delete(true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -293,7 +298,8 @@ namespace ServiceLib.ViewModels
|
|||||||
public void UpdateViewResult(CheckUpdateModel model)
|
public void UpdateViewResult(CheckUpdateModel model)
|
||||||
{
|
{
|
||||||
var found = _checkUpdateModel.FirstOrDefault(t => t.CoreType == model.CoreType);
|
var found = _checkUpdateModel.FirstOrDefault(t => t.CoreType == model.CoreType);
|
||||||
if (found == null) return;
|
if (found == null)
|
||||||
|
return;
|
||||||
var itemCopy = JsonUtils.DeepCopy(found);
|
var itemCopy = JsonUtils.DeepCopy(found);
|
||||||
itemCopy.Remarks = model.Remarks;
|
itemCopy.Remarks = model.Remarks;
|
||||||
_checkUpdateModel.Replace(found, itemCopy);
|
_checkUpdateModel.Replace(found, itemCopy);
|
||||||
|
|||||||
@@ -1,9 +1,9 @@
|
|||||||
|
using System.Reactive;
|
||||||
|
using System.Reactive.Linq;
|
||||||
using DynamicData;
|
using DynamicData;
|
||||||
using DynamicData.Binding;
|
using DynamicData.Binding;
|
||||||
using ReactiveUI;
|
using ReactiveUI;
|
||||||
using ReactiveUI.Fody.Helpers;
|
using ReactiveUI.Fody.Helpers;
|
||||||
using System.Reactive;
|
|
||||||
using System.Reactive.Linq;
|
|
||||||
|
|
||||||
namespace ServiceLib.ViewModels
|
namespace ServiceLib.ViewModels
|
||||||
{
|
{
|
||||||
@@ -115,7 +115,8 @@ namespace ServiceLib.ViewModels
|
|||||||
|
|
||||||
lstModel.Add(model);
|
lstModel.Add(model);
|
||||||
}
|
}
|
||||||
if (lstModel.Count <= 0) { return; }
|
if (lstModel.Count <= 0)
|
||||||
|
{ return; }
|
||||||
|
|
||||||
_connectionItems.AddRange(lstModel);
|
_connectionItems.AddRange(lstModel);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,9 +1,9 @@
|
|||||||
|
using System.Reactive;
|
||||||
|
using System.Reactive.Linq;
|
||||||
using DynamicData;
|
using DynamicData;
|
||||||
using DynamicData.Binding;
|
using DynamicData.Binding;
|
||||||
using ReactiveUI;
|
using ReactiveUI;
|
||||||
using ReactiveUI.Fody.Helpers;
|
using ReactiveUI.Fody.Helpers;
|
||||||
using System.Reactive;
|
|
||||||
using System.Reactive.Linq;
|
|
||||||
using static ServiceLib.Models.ClashProviders;
|
using static ServiceLib.Models.ClashProviders;
|
||||||
using static ServiceLib.Models.ClashProxies;
|
using static ServiceLib.Models.ClashProxies;
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
|
using System.Reactive;
|
||||||
using ReactiveUI;
|
using ReactiveUI;
|
||||||
using ReactiveUI.Fody.Helpers;
|
using ReactiveUI.Fody.Helpers;
|
||||||
using System.Reactive;
|
|
||||||
|
|
||||||
namespace ServiceLib.ViewModels
|
namespace ServiceLib.ViewModels
|
||||||
{
|
{
|
||||||
@@ -31,14 +31,14 @@ namespace ServiceLib.ViewModels
|
|||||||
|
|
||||||
ImportDefConfig4V2rayCmd = ReactiveCommand.CreateFromTask(async () =>
|
ImportDefConfig4V2rayCmd = ReactiveCommand.CreateFromTask(async () =>
|
||||||
{
|
{
|
||||||
normalDNS = Utils.GetEmbedText(Global.DNSV2rayNormalFileName);
|
normalDNS = EmbedUtils.GetEmbedText(Global.DNSV2rayNormalFileName);
|
||||||
await Task.CompletedTask;
|
await Task.CompletedTask;
|
||||||
});
|
});
|
||||||
|
|
||||||
ImportDefConfig4SingboxCmd = ReactiveCommand.CreateFromTask(async () =>
|
ImportDefConfig4SingboxCmd = ReactiveCommand.CreateFromTask(async () =>
|
||||||
{
|
{
|
||||||
normalDNS2 = Utils.GetEmbedText(Global.DNSSingboxNormalFileName);
|
normalDNS2 = EmbedUtils.GetEmbedText(Global.DNSSingboxNormalFileName);
|
||||||
tunDNS2 = Utils.GetEmbedText(Global.TunSingboxDNSFileName);
|
tunDNS2 = EmbedUtils.GetEmbedText(Global.TunSingboxDNSFileName);
|
||||||
await Task.CompletedTask;
|
await Task.CompletedTask;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
65
v2rayN/ServiceLib/ViewModels/GlobalHotkeySettingViewModel.cs
Normal file
65
v2rayN/ServiceLib/ViewModels/GlobalHotkeySettingViewModel.cs
Normal file
@@ -0,0 +1,65 @@
|
|||||||
|
using System.Reactive;
|
||||||
|
using ReactiveUI;
|
||||||
|
|
||||||
|
namespace ServiceLib.ViewModels
|
||||||
|
{
|
||||||
|
public class GlobalHotkeySettingViewModel : MyReactiveObject
|
||||||
|
{
|
||||||
|
private readonly List<KeyEventItem> _globalHotkeys;
|
||||||
|
|
||||||
|
public ReactiveCommand<Unit, Unit> SaveCmd { get; }
|
||||||
|
|
||||||
|
public GlobalHotkeySettingViewModel(Func<EViewAction, object?, Task<bool>>? updateView)
|
||||||
|
{
|
||||||
|
_config = AppHandler.Instance.Config;
|
||||||
|
_updateView = updateView;
|
||||||
|
|
||||||
|
_globalHotkeys = JsonUtils.DeepCopy(_config.GlobalHotkeys);
|
||||||
|
|
||||||
|
SaveCmd = ReactiveCommand.CreateFromTask(async () =>
|
||||||
|
{
|
||||||
|
await SaveSettingAsync();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public KeyEventItem GetKeyEventItem(EGlobalHotkey eg)
|
||||||
|
{
|
||||||
|
var item = _globalHotkeys.FirstOrDefault((it) => it.EGlobalHotkey == eg);
|
||||||
|
if (item != null)
|
||||||
|
{
|
||||||
|
return item;
|
||||||
|
}
|
||||||
|
|
||||||
|
item = new()
|
||||||
|
{
|
||||||
|
EGlobalHotkey = eg,
|
||||||
|
Control = false,
|
||||||
|
Alt = false,
|
||||||
|
Shift = false,
|
||||||
|
KeyCode = null
|
||||||
|
};
|
||||||
|
_globalHotkeys.Add(item);
|
||||||
|
|
||||||
|
return item;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void ResetKeyEventItem()
|
||||||
|
{
|
||||||
|
_globalHotkeys.Clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
private async Task SaveSettingAsync()
|
||||||
|
{
|
||||||
|
_config.GlobalHotkeys = _globalHotkeys;
|
||||||
|
|
||||||
|
if (await ConfigHandler.SaveConfig(_config) == 0)
|
||||||
|
{
|
||||||
|
_updateView?.Invoke(EViewAction.CloseWindow, null);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
NoticeHandler.Instance.Enqueue(ResUI.OperationFailed);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,7 +1,7 @@
|
|||||||
|
using System.Reactive;
|
||||||
using ReactiveUI;
|
using ReactiveUI;
|
||||||
using ReactiveUI.Fody.Helpers;
|
using ReactiveUI.Fody.Helpers;
|
||||||
using Splat;
|
using Splat;
|
||||||
using System.Reactive;
|
|
||||||
|
|
||||||
namespace ServiceLib.ViewModels
|
namespace ServiceLib.ViewModels
|
||||||
{
|
{
|
||||||
@@ -287,14 +287,15 @@ namespace ServiceLib.ViewModels
|
|||||||
try
|
try
|
||||||
{
|
{
|
||||||
Logging.SaveLog("MyAppExitAsync Begin");
|
Logging.SaveLog("MyAppExitAsync Begin");
|
||||||
|
|
||||||
|
await SysProxyHandler.UpdateSysProxy(_config, true);
|
||||||
MessageBus.Current.SendMessage("", EMsgCommand.AppExit.ToString());
|
MessageBus.Current.SendMessage("", EMsgCommand.AppExit.ToString());
|
||||||
|
|
||||||
await ConfigHandler.SaveConfig(_config);
|
await ConfigHandler.SaveConfig(_config);
|
||||||
await SysProxyHandler.UpdateSysProxy(_config, true);
|
|
||||||
await ProfileExHandler.Instance.SaveTo();
|
await ProfileExHandler.Instance.SaveTo();
|
||||||
await StatisticsHandler.Instance.SaveTo();
|
await StatisticsHandler.Instance.SaveTo();
|
||||||
StatisticsHandler.Instance.Close();
|
|
||||||
await CoreHandler.Instance.CoreStop();
|
await CoreHandler.Instance.CoreStop();
|
||||||
|
StatisticsHandler.Instance.Close();
|
||||||
|
|
||||||
Logging.SaveLog("MyAppExitAsync End");
|
Logging.SaveLog("MyAppExitAsync End");
|
||||||
}
|
}
|
||||||
@@ -570,7 +571,8 @@ namespace ServiceLib.ViewModels
|
|||||||
{
|
{
|
||||||
Locator.Current.GetService<ClashProxiesViewModel>()?.ProxiesReload();
|
Locator.Current.GetService<ClashProxiesViewModel>()?.ProxiesReload();
|
||||||
}
|
}
|
||||||
else { TabMainSelectedIndex = 0; }
|
else
|
||||||
|
{ TabMainSelectedIndex = 0; }
|
||||||
}
|
}
|
||||||
|
|
||||||
private async Task LoadCore()
|
private async Task LoadCore()
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
using ReactiveUI;
|
|
||||||
using ReactiveUI.Fody.Helpers;
|
|
||||||
using System.Collections.Concurrent;
|
using System.Collections.Concurrent;
|
||||||
using System.Text.RegularExpressions;
|
using System.Text.RegularExpressions;
|
||||||
|
using ReactiveUI;
|
||||||
|
using ReactiveUI.Fody.Helpers;
|
||||||
|
|
||||||
namespace ServiceLib.ViewModels
|
namespace ServiceLib.ViewModels
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
using ReactiveUI;
|
|
||||||
using ReactiveUI.Fody.Helpers;
|
|
||||||
using System.Reactive;
|
using System.Reactive;
|
||||||
|
using ReactiveUI;
|
||||||
|
using ReactiveUI.Fody.Helpers;
|
||||||
|
|
||||||
namespace ServiceLib.ViewModels
|
namespace ServiceLib.ViewModels
|
||||||
{
|
{
|
||||||
@@ -63,7 +63,7 @@ namespace ServiceLib.ViewModels
|
|||||||
[Reactive] public int SpeedTestTimeout { get; set; }
|
[Reactive] public int SpeedTestTimeout { get; set; }
|
||||||
[Reactive] public string SpeedTestUrl { get; set; }
|
[Reactive] public string SpeedTestUrl { get; set; }
|
||||||
[Reactive] public string SpeedPingTestUrl { get; set; }
|
[Reactive] public string SpeedPingTestUrl { get; set; }
|
||||||
[Reactive] public int SpeedTestPageSize { get; set; }
|
[Reactive] public int MixedConcurrencyCount { get; set; }
|
||||||
[Reactive] public bool EnableHWA { get; set; }
|
[Reactive] public bool EnableHWA { get; set; }
|
||||||
[Reactive] public string SubConvertUrl { get; set; }
|
[Reactive] public string SubConvertUrl { get; set; }
|
||||||
[Reactive] public int MainGirdOrientation { get; set; }
|
[Reactive] public int MainGirdOrientation { get; set; }
|
||||||
@@ -178,7 +178,7 @@ namespace ServiceLib.ViewModels
|
|||||||
CurrentFontFamily = _config.UiItem.CurrentFontFamily;
|
CurrentFontFamily = _config.UiItem.CurrentFontFamily;
|
||||||
SpeedTestTimeout = _config.SpeedTestItem.SpeedTestTimeout;
|
SpeedTestTimeout = _config.SpeedTestItem.SpeedTestTimeout;
|
||||||
SpeedTestUrl = _config.SpeedTestItem.SpeedTestUrl;
|
SpeedTestUrl = _config.SpeedTestItem.SpeedTestUrl;
|
||||||
SpeedTestPageSize = _config.SpeedTestItem.SpeedTestPageSize;
|
MixedConcurrencyCount = _config.SpeedTestItem.MixedConcurrencyCount;
|
||||||
SpeedPingTestUrl = _config.SpeedTestItem.SpeedPingTestUrl;
|
SpeedPingTestUrl = _config.SpeedTestItem.SpeedPingTestUrl;
|
||||||
EnableHWA = _config.GuiItem.EnableHWA;
|
EnableHWA = _config.GuiItem.EnableHWA;
|
||||||
SubConvertUrl = _config.ConstItem.SubConvertUrl;
|
SubConvertUrl = _config.ConstItem.SubConvertUrl;
|
||||||
@@ -332,7 +332,7 @@ namespace ServiceLib.ViewModels
|
|||||||
_config.GuiItem.TrayMenuServersLimit = TrayMenuServersLimit;
|
_config.GuiItem.TrayMenuServersLimit = TrayMenuServersLimit;
|
||||||
_config.UiItem.CurrentFontFamily = CurrentFontFamily;
|
_config.UiItem.CurrentFontFamily = CurrentFontFamily;
|
||||||
_config.SpeedTestItem.SpeedTestTimeout = SpeedTestTimeout;
|
_config.SpeedTestItem.SpeedTestTimeout = SpeedTestTimeout;
|
||||||
_config.SpeedTestItem.SpeedTestPageSize = SpeedTestPageSize;
|
_config.SpeedTestItem.MixedConcurrencyCount = MixedConcurrencyCount;
|
||||||
_config.SpeedTestItem.SpeedTestUrl = SpeedTestUrl;
|
_config.SpeedTestItem.SpeedTestUrl = SpeedTestUrl;
|
||||||
_config.SpeedTestItem.SpeedPingTestUrl = SpeedPingTestUrl;
|
_config.SpeedTestItem.SpeedPingTestUrl = SpeedPingTestUrl;
|
||||||
_config.GuiItem.EnableHWA = EnableHWA;
|
_config.GuiItem.EnableHWA = EnableHWA;
|
||||||
|
|||||||
@@ -1,11 +1,11 @@
|
|||||||
|
using System.Reactive;
|
||||||
|
using System.Reactive.Linq;
|
||||||
|
using System.Text;
|
||||||
using DynamicData;
|
using DynamicData;
|
||||||
using DynamicData.Binding;
|
using DynamicData.Binding;
|
||||||
using ReactiveUI;
|
using ReactiveUI;
|
||||||
using ReactiveUI.Fody.Helpers;
|
using ReactiveUI.Fody.Helpers;
|
||||||
using Splat;
|
using Splat;
|
||||||
using System.Reactive;
|
|
||||||
using System.Reactive.Linq;
|
|
||||||
using System.Text;
|
|
||||||
|
|
||||||
namespace ServiceLib.ViewModels
|
namespace ServiceLib.ViewModels
|
||||||
{
|
{
|
||||||
@@ -16,6 +16,7 @@ namespace ServiceLib.ViewModels
|
|||||||
private List<ProfileItem> _lstProfile;
|
private List<ProfileItem> _lstProfile;
|
||||||
private string _serverFilter = string.Empty;
|
private string _serverFilter = string.Empty;
|
||||||
private Dictionary<string, bool> _dicHeaderSort = new();
|
private Dictionary<string, bool> _dicHeaderSort = new();
|
||||||
|
private SpeedtestService? _speedtestService;
|
||||||
|
|
||||||
#endregion private prop
|
#endregion private prop
|
||||||
|
|
||||||
@@ -78,6 +79,7 @@ namespace ServiceLib.ViewModels
|
|||||||
public ReactiveCommand<Unit, Unit> RealPingServerCmd { get; }
|
public ReactiveCommand<Unit, Unit> RealPingServerCmd { get; }
|
||||||
public ReactiveCommand<Unit, Unit> SpeedServerCmd { get; }
|
public ReactiveCommand<Unit, Unit> SpeedServerCmd { get; }
|
||||||
public ReactiveCommand<Unit, Unit> SortServerResultCmd { get; }
|
public ReactiveCommand<Unit, Unit> SortServerResultCmd { get; }
|
||||||
|
public ReactiveCommand<Unit, Unit> RemoveInvalidServerResultCmd { get; }
|
||||||
|
|
||||||
//servers export
|
//servers export
|
||||||
public ReactiveCommand<Unit, Unit> Export2ClientConfigCmd { get; }
|
public ReactiveCommand<Unit, Unit> Export2ClientConfigCmd { get; }
|
||||||
@@ -196,6 +198,10 @@ namespace ServiceLib.ViewModels
|
|||||||
{
|
{
|
||||||
await SortServer(EServerColName.DelayVal.ToString());
|
await SortServer(EServerColName.DelayVal.ToString());
|
||||||
});
|
});
|
||||||
|
RemoveInvalidServerResultCmd = ReactiveCommand.CreateFromTask(async () =>
|
||||||
|
{
|
||||||
|
await RemoveInvalidServerResult();
|
||||||
|
});
|
||||||
//servers export
|
//servers export
|
||||||
Export2ClientConfigCmd = ReactiveCommand.CreateFromTask(async () =>
|
Export2ClientConfigCmd = ReactiveCommand.CreateFromTask(async () =>
|
||||||
{
|
{
|
||||||
@@ -259,11 +265,6 @@ namespace ServiceLib.ViewModels
|
|||||||
Locator.Current.GetService<MainWindowViewModel>()?.Reload();
|
Locator.Current.GetService<MainWindowViewModel>()?.Reload();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void UpdateSpeedtestHandler(SpeedTestResult result)
|
|
||||||
{
|
|
||||||
_updateView?.Invoke(EViewAction.DispatcherSpeedTest, result);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void SetSpeedTestResult(SpeedTestResult result)
|
public void SetSpeedTestResult(SpeedTestResult result)
|
||||||
{
|
{
|
||||||
if (Utils.IsNullOrEmpty(result.IndexId))
|
if (Utils.IsNullOrEmpty(result.IndexId))
|
||||||
@@ -272,28 +273,30 @@ namespace ServiceLib.ViewModels
|
|||||||
NoticeHandler.Instance.Enqueue(result.Delay);
|
NoticeHandler.Instance.Enqueue(result.Delay);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
var item = _profileItems.Where(it => it.IndexId == result.IndexId).FirstOrDefault();
|
var item = _profileItems.FirstOrDefault(it => it.IndexId == result.IndexId);
|
||||||
if (item != null)
|
if (item == null)
|
||||||
{
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (Utils.IsNotEmpty(result.Delay))
|
if (Utils.IsNotEmpty(result.Delay))
|
||||||
{
|
{
|
||||||
int.TryParse(result.Delay, out int temp);
|
int.TryParse(result.Delay, out var temp);
|
||||||
item.Delay = temp;
|
item.Delay = temp;
|
||||||
item.DelayVal = $"{result.Delay} {Global.DelayUnit}";
|
item.DelayVal = result.Delay ?? string.Empty;
|
||||||
}
|
}
|
||||||
if (Utils.IsNotEmpty(result.Speed))
|
if (Utils.IsNotEmpty(result.Speed))
|
||||||
{
|
{
|
||||||
item.SpeedVal = $"{result.Speed} {Global.SpeedUnit}";
|
item.SpeedVal = result.Speed ?? string.Empty;
|
||||||
}
|
}
|
||||||
_profileItems.Replace(item, JsonUtils.DeepCopy(item));
|
_profileItems.Replace(item, JsonUtils.DeepCopy(item));
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
public void UpdateStatistics(ServerSpeedItem update)
|
public void UpdateStatistics(ServerSpeedItem update)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
var item = _profileItems.Where(it => it.IndexId == update.IndexId).FirstOrDefault();
|
var item = _profileItems.FirstOrDefault(it => it.IndexId == update.IndexId);
|
||||||
if (item != null)
|
if (item != null)
|
||||||
{
|
{
|
||||||
item.TodayDown = Utils.HumanFy(update.TodayDown);
|
item.TodayDown = Utils.HumanFy(update.TodayDown);
|
||||||
@@ -425,10 +428,11 @@ namespace ServiceLib.ViewModels
|
|||||||
Subid = t.Subid,
|
Subid = t.Subid,
|
||||||
SubRemarks = t.SubRemarks,
|
SubRemarks = t.SubRemarks,
|
||||||
IsActive = t.IndexId == _config.IndexId,
|
IsActive = t.IndexId == _config.IndexId,
|
||||||
Sort = t33 == null ? 0 : t33.Sort,
|
Sort = t33?.Sort ?? 0,
|
||||||
Delay = t33 == null ? 0 : t33.Delay,
|
Delay = t33?.Delay ?? 0,
|
||||||
DelayVal = t33?.Delay != 0 ? $"{t33?.Delay} {Global.DelayUnit}" : string.Empty,
|
Speed = t33?.Speed ?? 0,
|
||||||
SpeedVal = t33?.Speed != 0 ? $"{t33?.Speed} {Global.SpeedUnit}" : string.Empty,
|
DelayVal = t33?.Delay != 0 ? $"{t33?.Delay}" : string.Empty,
|
||||||
|
SpeedVal = t33?.Speed > 0 ? $"{t33?.Speed}" : t33?.Message ?? string.Empty,
|
||||||
TodayDown = t22 == null ? "" : Utils.HumanFy(t22.TodayDown),
|
TodayDown = t22 == null ? "" : Utils.HumanFy(t22.TodayDown),
|
||||||
TodayUp = t22 == null ? "" : Utils.HumanFy(t22.TodayUp),
|
TodayUp = t22 == null ? "" : Utils.HumanFy(t22.TodayUp),
|
||||||
TotalDown = t22 == null ? "" : Utils.HumanFy(t22.TotalDown),
|
TotalDown = t22 == null ? "" : Utils.HumanFy(t22.TotalDown),
|
||||||
@@ -516,7 +520,7 @@ namespace ServiceLib.ViewModels
|
|||||||
}
|
}
|
||||||
var exists = lstSelecteds.Exists(t => t.IndexId == _config.IndexId);
|
var exists = lstSelecteds.Exists(t => t.IndexId == _config.IndexId);
|
||||||
|
|
||||||
await ConfigHandler.RemoveServer(_config, lstSelecteds);
|
await ConfigHandler.RemoveServers(_config, lstSelecteds);
|
||||||
NoticeHandler.Instance.Enqueue(ResUI.OperationSuccess);
|
NoticeHandler.Instance.Enqueue(ResUI.OperationSuccess);
|
||||||
if (lstSelecteds.Count == _profileItems.Count)
|
if (lstSelecteds.Count == _profileItems.Count)
|
||||||
{
|
{
|
||||||
@@ -660,6 +664,13 @@ namespace ServiceLib.ViewModels
|
|||||||
RefreshServers();
|
RefreshServers();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public async Task RemoveInvalidServerResult()
|
||||||
|
{
|
||||||
|
var count = await ConfigHandler.RemoveInvalidServerResult(_config, _config.SubIndexId);
|
||||||
|
RefreshServers();
|
||||||
|
NoticeHandler.Instance.Enqueue(string.Format(ResUI.RemoveInvalidServerResultTip, count));
|
||||||
|
}
|
||||||
|
|
||||||
//move server
|
//move server
|
||||||
private async Task MoveToGroup(bool c)
|
private async Task MoveToGroup(bool c)
|
||||||
{
|
{
|
||||||
@@ -726,14 +737,14 @@ namespace ServiceLib.ViewModels
|
|||||||
{
|
{
|
||||||
return;
|
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()
|
public void ServerSpeedtestStop()
|
||||||
{
|
{
|
||||||
MessageBus.Current.SendMessage("", EMsgCommand.StopSpeedtest.ToString());
|
_speedtestService?.ExitLoop();
|
||||||
}
|
}
|
||||||
|
|
||||||
private async Task Export2ClientConfigAsync(bool blClipboard)
|
private async Task Export2ClientConfigAsync(bool blClipboard)
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
using ReactiveUI;
|
|
||||||
using ReactiveUI.Fody.Helpers;
|
|
||||||
using System.Reactive;
|
using System.Reactive;
|
||||||
|
using ReactiveUI;
|
||||||
|
using ReactiveUI.Fody.Helpers;
|
||||||
|
|
||||||
namespace ServiceLib.ViewModels
|
namespace ServiceLib.ViewModels
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -1,9 +1,9 @@
|
|||||||
using DynamicData.Binding;
|
|
||||||
using ReactiveUI;
|
|
||||||
using ReactiveUI.Fody.Helpers;
|
|
||||||
using System.Reactive;
|
using System.Reactive;
|
||||||
using System.Text.Json;
|
using System.Text.Json;
|
||||||
using System.Text.Json.Serialization;
|
using System.Text.Json.Serialization;
|
||||||
|
using DynamicData.Binding;
|
||||||
|
using ReactiveUI;
|
||||||
|
using ReactiveUI.Fody.Helpers;
|
||||||
|
|
||||||
namespace ServiceLib.ViewModels
|
namespace ServiceLib.ViewModels
|
||||||
{
|
{
|
||||||
@@ -257,7 +257,7 @@ namespace ServiceLib.ViewModels
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
var result = Utils.LoadResource(fileName);
|
var result = EmbedUtils.LoadResource(fileName);
|
||||||
if (Utils.IsNullOrEmpty(result))
|
if (Utils.IsNullOrEmpty(result))
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
using DynamicData.Binding;
|
using System.Reactive;
|
||||||
|
using DynamicData.Binding;
|
||||||
using ReactiveUI;
|
using ReactiveUI;
|
||||||
using ReactiveUI.Fody.Helpers;
|
using ReactiveUI.Fody.Helpers;
|
||||||
using System.Reactive;
|
|
||||||
|
|
||||||
namespace ServiceLib.ViewModels
|
namespace ServiceLib.ViewModels
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -1,9 +1,9 @@
|
|||||||
using DynamicData.Binding;
|
using System.Reactive;
|
||||||
|
using System.Text;
|
||||||
|
using DynamicData.Binding;
|
||||||
using ReactiveUI;
|
using ReactiveUI;
|
||||||
using ReactiveUI.Fody.Helpers;
|
using ReactiveUI.Fody.Helpers;
|
||||||
using Splat;
|
using Splat;
|
||||||
using System.Reactive;
|
|
||||||
using System.Text;
|
|
||||||
|
|
||||||
namespace ServiceLib.ViewModels
|
namespace ServiceLib.ViewModels
|
||||||
{
|
{
|
||||||
@@ -60,6 +60,9 @@ namespace ServiceLib.ViewModels
|
|||||||
[Reactive]
|
[Reactive]
|
||||||
public int SystemProxySelected { get; set; }
|
public int SystemProxySelected { get; set; }
|
||||||
|
|
||||||
|
[Reactive]
|
||||||
|
public bool BlSystemProxyPacVisible { get; set; }
|
||||||
|
|
||||||
#endregion System Proxy
|
#endregion System Proxy
|
||||||
|
|
||||||
#region UI
|
#region UI
|
||||||
@@ -96,6 +99,7 @@ namespace ServiceLib.ViewModels
|
|||||||
SelectedRouting = new();
|
SelectedRouting = new();
|
||||||
SelectedServer = new();
|
SelectedServer = new();
|
||||||
RunningServerToolTipText = "-";
|
RunningServerToolTipText = "-";
|
||||||
|
BlSystemProxyPacVisible = Utils.IsWindows();
|
||||||
|
|
||||||
if (_config.TunModeItem.EnableTun && AllowEnableTun())
|
if (_config.TunModeItem.EnableTun && AllowEnableTun())
|
||||||
{
|
{
|
||||||
@@ -225,19 +229,22 @@ namespace ServiceLib.ViewModels
|
|||||||
private async Task AddServerViaClipboard()
|
private async Task AddServerViaClipboard()
|
||||||
{
|
{
|
||||||
var service = Locator.Current.GetService<MainWindowViewModel>();
|
var service = Locator.Current.GetService<MainWindowViewModel>();
|
||||||
if (service != null) await service.AddServerViaClipboardAsync(null);
|
if (service != null)
|
||||||
|
await service.AddServerViaClipboardAsync(null);
|
||||||
}
|
}
|
||||||
|
|
||||||
private async Task AddServerViaScan()
|
private async Task AddServerViaScan()
|
||||||
{
|
{
|
||||||
var service = Locator.Current.GetService<MainWindowViewModel>();
|
var service = Locator.Current.GetService<MainWindowViewModel>();
|
||||||
if (service != null) await service.AddServerViaScanAsync();
|
if (service != null)
|
||||||
|
await service.AddServerViaScanAsync();
|
||||||
}
|
}
|
||||||
|
|
||||||
private async Task UpdateSubscriptionProcess(bool blProxy)
|
private async Task UpdateSubscriptionProcess(bool blProxy)
|
||||||
{
|
{
|
||||||
var service = Locator.Current.GetService<MainWindowViewModel>();
|
var service = Locator.Current.GetService<MainWindowViewModel>();
|
||||||
if (service != null) await service.UpdateSubscriptionProcess("", blProxy);
|
if (service != null)
|
||||||
|
await service.UpdateSubscriptionProcess("", blProxy);
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task RefreshServersBiz()
|
public async Task RefreshServersBiz()
|
||||||
@@ -308,11 +315,13 @@ namespace ServiceLib.ViewModels
|
|||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
await (new UpdateService()).RunAvailabilityCheck(async (bool success, string msg) =>
|
|
||||||
{
|
_updateView?.Invoke(EViewAction.DispatcherServerAvailability, ResUI.Speedtesting);
|
||||||
|
|
||||||
|
var msg = await (new UpdateService()).RunAvailabilityCheck();
|
||||||
|
|
||||||
NoticeHandler.Instance.SendMessageEx(msg);
|
NoticeHandler.Instance.SendMessageEx(msg);
|
||||||
_updateView?.Invoke(EViewAction.DispatcherServerAvailability, msg);
|
_updateView?.Invoke(EViewAction.DispatcherServerAvailability, msg);
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void TestServerAvailabilityResult(string msg)
|
public void TestServerAvailabilityResult(string msg)
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
using ReactiveUI;
|
|
||||||
using ReactiveUI.Fody.Helpers;
|
|
||||||
using System.Reactive;
|
using System.Reactive;
|
||||||
|
using ReactiveUI;
|
||||||
|
using ReactiveUI.Fody.Helpers;
|
||||||
|
|
||||||
namespace ServiceLib.ViewModels
|
namespace ServiceLib.ViewModels
|
||||||
{
|
{
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user