Compare commits

..

31 Commits

Author SHA1 Message Date
spiritlhl
6d02103aba fix: 修复流媒体解锁的请求头参数设置 2026-01-30 05:57:44 +00:00
github-actions[bot]
5ffb48dcdc chore: update ECS_VERSION to 0.1.112 in goecs.sh 2026-01-16 06:16:27 +00:00
spiritlhl
7c19502950 fix:部分测速成功也输出,但补充节点测速 2026-01-16 14:02:42 +08:00
spiritlhl
3c434781f5 fix:修复私有测速节点可能存在部分上传下载测速失败的问题,自动轮换 2026-01-16 14:00:53 +08:00
spiritlhl
f62636ca3e fix:回退upx安装步骤,实际受限于编译的镜像不可直接进行安装 2026-01-13 20:00:59 +08:00
spiritlhl
c4b11ae37d fix: Install UPX in build workflow
Added step to install UPX for binary compression.
2026-01-13 19:57:55 +08:00
github-actions[bot]
8f2fe236d5 chore: update ECS_VERSION to 0.1.111 in goecs.sh 2026-01-13 11:56:25 +00:00
spiritlhl
347a0faa7a fix:添加UPX操作压缩减小产物大小 2026-01-13 19:42:41 +08:00
spiritlhl
74640e3066 fix:更新版本 2026-01-13 19:36:24 +08:00
spiritlhl
3b646eeeda fix:修复错误的格式化字符 2026-01-13 19:35:39 +08:00
github-actions[bot]
eaad433395 chore: update ECS_VERSION to 0.1.110 in goecs.sh 2026-01-13 04:28:12 +00:00
spiritlhl
03af7c423b Bump ecsVersion to v0.1.110 2026-01-13 12:12:40 +08:00
spiritlhl
0e96a6499b Update build_binary.yaml to disable certain options
Disable large packages, Docker images, and swap storage in the build workflow.
2026-01-13 12:03:44 +08:00
spiritlhl
5b44f5f651 fix:修复编译占用的磁盘过大的问题 2026-01-13 11:49:57 +08:00
spiritlhl
e4a759fceb fix:修改非选项1时的测速逻辑,区分中英文测速使用不同的节点逻辑 2026-01-13 11:23:21 +08:00
spiritlhl
e5c4b0ce8e Clean up newlines in create_public_branch.py
Remove unnecessary newlines around specific strings in content.
2026-01-12 23:48:03 +08:00
spiritsoul
188a1153e6 fix:删除对应的依赖 2026-01-12 23:40:58 +08:00
spiritsoul
4c4887f487 fix:以文本结构匹配避免正则匹配越界 2026-01-12 23:31:27 +08:00
spiritsoul
feac73a427 fix:修复正则匹配 2026-01-12 23:28:45 +08:00
spiritlhl
f3048d074c Clean up Go module cache and remove go.sum 2026-01-12 23:19:18 +08:00
spiritlhl
58702b54e7 Remove privatespeedtest code from speed.go
Brutally remove privatespeedtest-related code from speed.go, ensuring the file remains syntactically correct.
2026-01-12 23:16:49 +08:00
spiritlhl
1e4d63ef57 Update Go version to 1.25.4 in workflow 2026-01-12 23:08:23 +08:00
spiritlhl
9f3acacae0 Disable modify_go_mod function and related calls
Comment out the modify_go_mod function and its calls.
2026-01-12 23:07:43 +08:00
spiritlhl
e9755f0c20 Refine speed test description in README.md 2026-01-12 23:01:19 +08:00
GitHub Actions
d8b397b31b Auto update README files 2026-01-12 14:41:00 +00:00
github-actions[bot]
9e22d1bc23 chore: update ECS_VERSION to 0.1.108 in goecs.sh 2026-01-12 14:37:10 +00:00
spiritlhl
284f6b8ba7 fix: 修复误删除的md文件 2026-01-12 14:22:34 +00:00
spiritlhl
27203cf850 fix:修复公共分支生成的Action,使用更完善的python脚本完成修复 2026-01-12 14:21:43 +00:00
spiritlhl
9b6922f55a fix:升级回程测试的nexttrace核心版本 2026-01-12 14:15:13 +00:00
spiritlhl
447b25989e fix:修复预设 2026-01-12 14:13:29 +00:00
github-actions[bot]
a50b68d184 chore: update ECS_VERSION to 0.1.107 in goecs.sh 2026-01-12 13:36:44 +00:00
14 changed files with 552 additions and 151 deletions

310
.back/create_public_branch.py Executable file
View File

@@ -0,0 +1,310 @@
#!/usr/bin/env python3
"""
Script to create public branch by removing security dependencies and references.
This script properly handles Go file modifications to ensure the code can compile.
"""
import re
import os
import sys
import shutil
def read_file(filepath):
"""Read file content."""
with open(filepath, 'r', encoding='utf-8') as f:
return f.read()
def write_file(filepath, content):
"""Write content to file."""
with open(filepath, 'w', encoding='utf-8') as f:
f.write(content)
def modify_go_mod(filepath):
"""
Modify go.mod to remove privatespeedtest (and optional security) dependencies.
Automatically matches module names regardless of version or indirect comment.
"""
content = read_file(filepath)
# Modules to remove
remove_modules = [
r'github\.com/oneclickvirt/privatespeedtest',
r'github\.com/oneclickvirt/security',
]
for mod in remove_modules:
# Remove full require line (with or without // indirect)
content = re.sub(
rf'^[ \t]*{mod}[ \t]+v[^\s]+(?:[ \t]+// indirect)?[ \t]*\n',
'',
content,
flags=re.MULTILINE
)
write_file(filepath, content)
print(f"✓ Removed privatespeedtest/security from {filepath}")
def remove_code_block(lines, start_marker, end_condition='empty_line'):
"""
Remove code block from lines starting with start_marker.
Args:
lines: List of file lines
start_marker: String or list of strings to identify block start
end_condition: 'empty_line' (default) or 'closing_brace' or custom function
Returns:
Modified lines with the block removed
"""
if isinstance(start_marker, str):
start_marker = [start_marker]
result = []
skip_mode = False
brace_depth = 0
i = 0
while i < len(lines):
line = lines[i]
# Check if we should start skipping
if not skip_mode:
for marker in start_marker:
if marker in line:
skip_mode = True
if end_condition == 'closing_brace':
# Count opening braces on the function declaration line
brace_depth = line.count('{') - line.count('}')
break
if not skip_mode:
result.append(line)
else:
# We're in skip mode
if end_condition == 'empty_line':
# Skip until we find an empty line
if line.strip() == '':
skip_mode = False
# Don't add the empty line, continue to next
elif end_condition == 'closing_brace':
# Track brace depth
brace_depth += line.count('{') - line.count('}')
if brace_depth == 0 and '}' in line:
# Function ended, skip until next empty line
end_condition = 'empty_line'
i += 1
return result
def modify_speed_go(filepath):
"""
Remove privatespeedtest-related code from speed.go.
Uses line-by-line processing for reliability.
"""
content = read_file(filepath)
lines = content.split('\n')
# Remove specific code blocks by their comment markers
blocks_to_remove = [
'// formatString 格式化字符串到指定宽度',
'// printTableRow 打印表格行',
'// privateSpeedTest 使用 privatespeedtest 进行单个运营商测速',
'// privateSpeedTestWithFallback 使用私有测速,如果失败则回退到 global 节点',
'// 对于三网测速cmcc、cu、ct和 other优先使用 privatespeedtest 进行私有测速',
]
for block_marker in blocks_to_remove:
lines = remove_code_block(lines, block_marker)
# Reconstruct content
content = '\n'.join(lines)
# Remove privatespeedtest import
content = re.sub(
r'\n\s*"github\.com/oneclickvirt/privatespeedtest/pst"\s*\n',
'\n',
content,
flags=re.MULTILINE
)
# Remove time import (only used by privatespeedtest)
content = re.sub(
r'\n\s*"time"\s*\n',
'\n',
content,
flags=re.MULTILINE
)
# Clean up multiple consecutive empty lines (optional)
content = re.sub(r'\n{3,}', '\n\n', content)
write_file(filepath, content)
print(f"✓ Removed privatespeedtest from {filepath}")
def modify_utils_go(filepath):
"""
Modify utils/utils.go to:
1. Replace security/network import with basics/network
2. Replace SecurityUploadToken usage with hardcoded token
"""
content = read_file(filepath)
# Replace import
content = re.sub(
r'"github\.com/oneclickvirt/security/network"',
r'"github.com/oneclickvirt/basics/network"',
content
)
# Replace token usage - find the exact line and replace it
content = re.sub(
r'\ttoken := network\.SecurityUploadToken',
r'\ttoken := "OvwKx5qgJtf7PZgCKbtyojSU.MTcwMTUxNzY1MTgwMw"',
content
)
# Update title for public version
content = re.sub(
r'VPS融合怪测试',
r'VPS融合怪测试(非官方编译)',
content
)
content = re.sub(
r'VPS Fusion Monster Test',
r'VPS Fusion Monster Test (Unofficial)',
content
)
write_file(filepath, content)
print(f"✓ Modified {filepath}")
def modify_params_go(filepath):
"""
Modify internal/params/params.go to change security flag default to false.
"""
content = read_file(filepath)
# Change default value in struct initialization
content = re.sub(
r'(\s+SecurityTestStatus:\s+)true,',
r'\1false,',
content
)
# Change flag default value
content = re.sub(
r'(c\.GoecsFlag\.BoolVar\(&c\.SecurityTestStatus, "security", )true(, "Enable/Disable security test"\))',
r'\1false\2',
content
)
write_file(filepath, content)
print(f"✓ Modified {filepath}")
def modify_readme(filepath, is_english=False):
"""
Modify README files to update Go version and security status.
"""
content = read_file(filepath)
# Extract Go version from go.mod
go_mod_content = read_file('go.mod')
go_version_match = re.search(r'^go (\d+\.\d+(?:\.\d+)?)', go_mod_content, re.MULTILINE)
if not go_version_match:
print(f"⚠ Warning: Could not extract Go version from go.mod")
return
go_version = go_version_match.group(1)
if is_english:
# Update Go version in English README
content = re.sub(
r'Select go \d+\.\d+\.\d+ version to install',
f'Select go {go_version} version to install',
content
)
# Update security status
content = re.sub(
r'but binary files compiled in \[securityCheck\][^\)]*\)',
'but open sourced',
content
)
# Update help text for security flag
content = re.sub(
r'security\s+Enable/Disable security test \(default true\)',
'security Enable/Disable security test (default false)',
content
)
else:
# Update Go version in Chinese README
content = re.sub(
r'选择 go \d+\.\d+\.\d+ 的版本进行安装',
f'选择 go {go_version} 的版本进行安装',
content
)
# Update security status
content = re.sub(
r'但二进制文件编译至 \[securityCheck\][^\)]*\)',
'但已开源',
content
)
# Update help text for security flag
content = re.sub(
r'security\s+Enable/Disable security test \(default true\)',
'security Enable/Disable security test (default false)',
content
)
write_file(filepath, content)
print(f"✓ Modified {filepath}")
def main():
"""Main function to process all files."""
print("Starting public branch creation process...")
print()
# Check if we're in the right directory
if not os.path.exists('go.mod'):
print("Error: go.mod not found. Please run this script from the project root.")
sys.exit(1)
# Modify Go source files
print("Modifying Go source files...")
modify_speed_go('internal/tests/speed.go')
modify_utils_go('utils/utils.go')
modify_params_go('internal/params/params.go')
print()
# Modify go.mod
print("Modifying go.mod...")
modify_go_mod('go.mod')
print()
# Modify README files
print("Modifying README files...")
modify_readme('README.md', is_english=False)
modify_readme('README_EN.md', is_english=True)
print()
print("✓ All modifications completed successfully!")
print()
print("Next steps:")
print("1. Run 'go mod tidy' to clean up dependencies")
print("2. Run 'go build -o maintest' to verify compilation")
print("3. Test the binary with: ./maintest -menu=false -l en -security=false -upload=false")
if __name__ == '__main__':
main()

View File

@@ -19,11 +19,31 @@ jobs:
with:
fetch-depth: 0
- name: Free Disk Space (Ubuntu)
uses: jlumbroso/free-disk-space@main
with:
# this might remove tools that are actually needed,
# if set to "true" but frees about 6 GB
tool-cache: false
# all of these default to true, but feel free to set to
# "false" if necessary for your workflow
android: true
dotnet: true
haskell: true
large-packages: false
docker-images: false
swap-storage: false
- name: Set up Go
uses: actions/setup-go@v4
with:
go-version: 1.25.3
go-version: 1.25.4
# - name: Install UPX
# run: |
# apk add --no-cache upx
- name: Configure Git for Private Modules
run: |
git config --global url."https://${{ secrets.GHT }}@github.com/".insteadOf "https://github.com/"
@@ -31,13 +51,18 @@ jobs:
env:
GITHUB_TOKEN: ${{ secrets.GHT }}
- name: Clean Go cache before build
run: |
go clean -cache -modcache -testcache
df -h
- name: Run GoReleaser
uses: goreleaser/goreleaser-action@v6
with:
distribution: goreleaser
# version: latest
version: '~> v2'
args: release
args: release --clean
env:
GITHUB_TOKEN: ${{ secrets.GHT }}
GOPRIVATE: github.com/oneclickvirt/security,github.com/oneclickvirt/privatespeedtest

View File

@@ -16,7 +16,7 @@ jobs:
- name: Set up Go
uses: actions/setup-go@v5
with:
go-version: '1.25.3'
go-version: '1.25.4'
- name: Update master branch README files
run: |
@@ -61,46 +61,15 @@ jobs:
- name: Remove security package references
run: |
find . -type f -name "*.go" -exec sed -i 's|"github.com/oneclickvirt/security/network"|"github.com/oneclickvirt/basics/network"|g' {} +
sed -i '/SecurityUploadToken/d' utils/utils.go
sed -i 's|"github.com/oneclickvirt/security/network"|"github.com/oneclickvirt/basics/network"|g' utils/utils.go
sed -i '/^import/,/^)/{/^)/a\'$'\n''const token = "OvwKx5qgJtf7PZgCKbtyojSU.MTcwMTUxNzY1MTgwMw"'$'\n''}' utils/utils.go
sed -i '/github.com\/oneclickvirt\/security/d' go.mod
sed -i '/github.com\/oneclickvirt\/privatespeedtest/d' go.mod
sed -i 's|var securityFlag = flag.Bool("security", true,|var securityFlag = flag.Bool("security", false,|g' goecs.go
sed -i 's|"github.com/oneclickvirt/privatespeedtest/pst"|// "github.com/oneclickvirt/privatespeedtest/pst"|g' internal/tests/speed.go
sed -i '/^\/\/ privateSpeedTest.*使用 privatespeedtest/,/^func [A-Z]/{/^func [A-Z]/!s/^/\/\/ /}' internal/tests/speed.go
sed -i '/err := privateSpeedTest(num, opLower)/,/return/{/return/!s/^/\/\/ /; s/return$/\/\/ return/}' internal/tests/speed.go
sed -i 's|VPS融合怪测试|VPS融合怪测试(非官方编译)|g' utils/utils.go
sed -i 's|VPS Fusion Monster Test|VPS Fusion Monster Test (Unofficial)|g' utils/utils.go
python3 .back/create_public_branch.py
rm -f go.sum
go clean -modcache
go clean -cache -testcache -fuzzcache
go mod tidy
sed -i 's|但二进制文件编译至 \[securityCheck\].*)|但已开源|g' README.md
sed -i 's|but binary files compiled in \[securityCheck\].*)|but open sourced|g' README_EN.md
sed -i 's|security.*Enable/Disable security test (default true)|security Enable/Disable security test (default false)|g' README.md
sed -i 's|security.*Enable/Disable security test (default true)|security Enable/Disable security test (default false)|g' README_EN.md
- name: Update Go version in README files
run: |
if [ -f "go.mod" ]; then
GO_VERSION=$(grep "^go " go.mod | head -n 1 | awk '{print $2}')
echo "提取到的 Go 版本: $GO_VERSION"
if [ -n "$GO_VERSION" ] && [[ "$GO_VERSION" =~ ^[0-9]+\.[0-9]+(\.[0-9]+)?$ ]]; then
echo "版本验证成功,开始替换..."
if [ -f "README.md" ]; then
sed -i "s/选择 go [0-9]\+\.[0-9]\+\.[0-9]\+ 的版本进行安装/选择 go $GO_VERSION 的版本进行安装/g" README.md
echo "已更新 README.md"
fi
if [ -f "README_EN.md" ]; then
sed -i "s/Select go [0-9]\+\.[0-9]\+\.[0-9]\+ version to install/Select go $GO_VERSION version to install/g" README_EN.md
echo "已更新 README_EN.md"
fi
else
echo "错误:未能提取到有效的 Go 版本号或版本号格式不正确"
exit 1
fi
else
echo "错误:未找到 go.mod 文件"
exit 1
fi
# This step is now handled by the Python script
echo "README files already updated by create_public_branch.py"
- name: Build and Test
run: |
go build -o maintest

View File

@@ -1,6 +1,10 @@
before:
hooks:
- go mod tidy -v
- go clean -cache
project_name: goecs
builds:
- id: universal
env:
@@ -31,6 +35,7 @@ builds:
goarch: arm
main: ./
binary: goecs
- id: darwin-amd64
env:
- CGO_ENABLED=1
@@ -44,6 +49,7 @@ builds:
- amd64
main: ./
binary: goecs
- id: darwin-arm64
env:
- CGO_ENABLED=1
@@ -57,18 +63,23 @@ builds:
- arm64
main: ./
binary: goecs
universal_binaries:
- name_template: "goecs"
replace: false
checksum:
name_template: "checksums.txt"
snapshot:
name_template: "goecs"
archives:
- name_template: "goecs_{{ .Os }}_{{ .Arch }}"
format: zip
files:
- none*
changelog:
sort: asc
filters:
@@ -79,4 +90,18 @@ changelog:
- Merge pull request
- Merge branch
- go mod tidy
- New translations
- New translations
upx:
- enabled: true
brute: true
goos:
- linux
- windows
goarch:
- amd64
- 386
- arm64
- ppc64le
- s390x
- riscv64

View File

@@ -60,7 +60,7 @@ Shell 版本:[https://github.com/spiritLHLS/ecs](https://github.com/spiritLHLS
- 邮件端口测试:[portchecker](https://github.com/oneclickvirt/portchecker)
- 上游及回程路由线路检测:借鉴 [zhanghanyun/backtrace](https://github.com/zhanghanyun/backtrace),二次开发至 [oneclickvirt/backtrace](https://github.com/oneclickvirt/backtrace)
- 三网路由测试:基于 [NTrace-core](https://github.com/nxtrace/NTrace-core),二次开发至 [nt3](https://github.com/oneclickvirt/nt3)
- 网速测试:基于 [speedtest.net](https://github.com/spiritLHLS/speedtest.net-CN-ID) 和 [speedtest.cn](https://github.com/spiritLHLS/speedtest.cn-CN-ID) 数据,开发 [oneclickvirt/speedtest](https://github.com/oneclickvirt/speedtest),同时融合私有国内测速平台
- 网速测试:基于 [speedtest.net](https://github.com/spiritLHLS/speedtest.net-CN-ID) 和 [speedtest.cn](https://github.com/spiritLHLS/speedtest.cn-CN-ID) 数据,开发 [oneclickvirt/speedtest](https://github.com/oneclickvirt/speedtest),同时融合私有国内测速节点
- 三网 Ping 值测试:借鉴 [ecsspeed](https://github.com/spiritLHLS/ecsspeed),二次开发至 [pingtest](https://github.com/oneclickvirt/pingtest)
- 支持root或admin环境下测试支持非root或非admin环境下测试支持离线环境下进行测试**暂未**支持无DNS的在线环境下进行测试
@@ -333,7 +333,7 @@ cd ecs
2. 安装 Go 环境(如已安装可跳过)
选择 go 1.25.3 的版本进行安装
选择 go 1.25.4 的版本进行安装
```bash
curl -L https://cdn.spiritlhl.net/https://raw.githubusercontent.com/spiritLHLS/one-click-installation-script/main/install_scripts/go.sh -o go.sh && chmod +x go.sh && bash go.sh

View File

@@ -330,7 +330,7 @@ cd ecs
2. Install Go environment (skip if already installed)
Select go 1.25.3 version to install
Select go 1.25.4 version to install
```bash
curl -L https://cdn.spiritlhl.net/https://raw.githubusercontent.com/spiritLHLS/one-click-installation-script/main/install_scripts/go.sh -o go.sh && chmod +x go.sh && bash go.sh

View File

@@ -482,6 +482,8 @@ Abuser 或 Abuse 的滥用得分会直接影响机器的正常使用(中国境
先测的官方推荐的测速点然后测有代表性的国际测速点最后测国内三大运营商ping值最低的测速点。
由于 speedtest.net 和 speedtest.cn 平台公开的测速节点被刷BTPT的刷烂了(他们为了对等上传PCDN的流量狂刷下载)所以这块本人独家融合的境内私有测速节点不再公开优先使用私有的境内运营商测速节点进行测速且写死限制每个IP每日仅支持获取测速数据10次超限自动降级为使用公共测速节点进行测速
境内使用为主就看境内测速即可,境外使用看境外测速,官方测速点可以代表受测的宿主机本地带宽基准。
一般来说中国境外的服务器的带宽100Mbps起步中国境内的服务器1Mbps带宽起步具体看线路优劣带宽特别大有时候未必用得上够用就行了。

42
go.mod
View File

@@ -1,10 +1,10 @@
module github.com/oneclickvirt/ecs
go 1.25.3
go 1.25.4
require (
github.com/imroc/req/v3 v3.54.0
github.com/oneclickvirt/UnlockTests v0.0.33-20251126065725
github.com/oneclickvirt/UnlockTests v0.0.34-20260130055000
github.com/oneclickvirt/backtrace v0.0.8-20251109090457
github.com/oneclickvirt/basics v0.0.16-20251112033526
github.com/oneclickvirt/cputest v0.0.12-20251111095842
@@ -12,10 +12,11 @@ require (
github.com/oneclickvirt/disktest v0.0.10-20250924030424
github.com/oneclickvirt/gostun v0.0.5-20250727155022
github.com/oneclickvirt/memorytest v0.0.10-20251218032900
github.com/oneclickvirt/nt3 v0.0.10-20251111095706
github.com/oneclickvirt/nt3 v0.0.11-20260112140912
github.com/oneclickvirt/pingtest v0.0.9-20251104112920
github.com/oneclickvirt/portchecker v0.0.3-20250728015900
github.com/oneclickvirt/security v0.0.8-20251112080734
github.com/oneclickvirt/privatespeedtest v0.0.1-20260112130218
github.com/oneclickvirt/security v0.0.8-20260104113003
github.com/oneclickvirt/speedtest v0.0.11-20251102151740
)
@@ -28,7 +29,7 @@ require (
github.com/ebitengine/purego v0.8.4 // indirect
github.com/fatih/color v1.18.0 // indirect
github.com/fsnotify/fsnotify v1.9.0 // indirect
github.com/go-ole/go-ole v1.2.6 // indirect
github.com/go-ole/go-ole v1.3.0 // indirect
github.com/go-viper/mapstructure/v2 v2.4.0 // indirect
github.com/gofrs/uuid/v5 v5.2.0 // indirect
github.com/google/gopacket v1.1.19 // indirect
@@ -41,12 +42,12 @@ require (
github.com/jackpal/go-nat-pmp v1.0.2 // indirect
github.com/jaypipes/ghw v0.17.0 // indirect
github.com/jaypipes/pcidb v1.0.1 // indirect
github.com/jsdelivr/globalping-cli v1.5.1 // indirect
github.com/json-iterator/go v1.1.12 // indirect
github.com/klauspost/compress v1.18.0 // indirect
github.com/koron/go-ssdp v0.0.4 // indirect
github.com/libp2p/go-nat v0.2.0 // indirect
github.com/libp2p/go-netroute v0.2.1 // indirect
github.com/lionsoul2014/ip2region v2.11.2+incompatible // indirect
github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0 // indirect
github.com/mattn/go-colorable v0.1.14 // indirect
github.com/mattn/go-isatty v0.0.20 // indirect
@@ -56,11 +57,10 @@ require (
github.com/mitchellh/go-homedir v1.1.0 // indirect
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
github.com/modern-go/reflect2 v1.0.2 // indirect
github.com/nxtrace/NTrace-core v1.4.3-rc.1 // indirect
github.com/nxtrace/NTrace-core v1.5.0 // indirect
github.com/oneclickvirt/dd v0.0.2-20250808062818 // indirect
github.com/oneclickvirt/fio v0.0.2-20250808045755 // indirect
github.com/oneclickvirt/mbw v0.0.1-20250808061222 // indirect
github.com/oneclickvirt/privatespeedtest v0.0.1-20260112130218 // indirect
github.com/oneclickvirt/stream v0.0.2-20250924154001 // indirect
github.com/oschwald/maxminddb-golang v1.13.1 // indirect
github.com/pelletier/go-toml/v2 v2.2.4 // indirect
@@ -73,41 +73,39 @@ require (
github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c // indirect
github.com/prometheus-community/pro-bing v0.4.1 // indirect
github.com/quic-go/qpack v0.5.1 // indirect
github.com/quic-go/quic-go v0.53.0 // indirect
github.com/quic-go/quic-go v0.55.0 // indirect
github.com/refraction-networking/utls v1.7.3 // indirect
github.com/rivo/uniseg v0.4.7 // indirect
github.com/rodaine/table v1.3.0 // indirect
github.com/sagikazarmark/locafero v0.11.0 // indirect
github.com/sagikazarmark/locafero v0.12.0 // indirect
github.com/schollz/progressbar/v3 v3.17.1 // indirect
github.com/shirou/gopsutil v3.21.11+incompatible // indirect
github.com/shirou/gopsutil/v4 v4.25.6 // indirect
github.com/showwin/speedtest-go v1.7.10 // indirect
github.com/sourcegraph/conc v0.3.1-0.20240121214520-5f936abd7ae8 // indirect
github.com/spf13/afero v1.15.0 // indirect
github.com/spf13/cast v1.10.0 // indirect
github.com/spf13/pflag v1.0.10 // indirect
github.com/spf13/viper v1.21.0 // indirect
github.com/subosito/gotenv v1.6.0 // indirect
github.com/tidwall/gjson v1.18.0 // indirect
github.com/tidwall/match v1.1.1 // indirect
github.com/tidwall/match v1.2.0 // indirect
github.com/tidwall/pretty v1.2.1 // indirect
github.com/tklauser/go-sysconf v0.3.14 // indirect
github.com/tklauser/numcpus v0.8.0 // indirect
github.com/tklauser/numcpus v0.9.0 // indirect
github.com/tsosunchia/powclient v0.2.0 // indirect
github.com/xjasonlyu/windivert-go v0.0.0-20201010013527-4239d0afa76f // indirect
github.com/yusufpapurcu/wmi v1.2.4 // indirect
go.uber.org/mock v0.5.2 // indirect
go.uber.org/multierr v1.11.0 // indirect
go.uber.org/zap v1.27.0 // indirect
go.yaml.in/yaml/v3 v3.0.4 // indirect
golang.org/x/crypto v0.42.0 // indirect
golang.org/x/mod v0.27.0 // indirect
golang.org/x/net v0.44.0 // indirect
golang.org/x/sync v0.17.0 // indirect
golang.org/x/sys v0.36.0 // indirect
golang.org/x/term v0.35.0 // indirect
golang.org/x/text v0.29.0 // indirect
golang.org/x/tools v0.36.0 // indirect
golang.org/x/crypto v0.45.0 // indirect
golang.org/x/mod v0.29.0 // indirect
golang.org/x/net v0.47.0 // indirect
golang.org/x/sync v0.18.0 // indirect
golang.org/x/sys v0.38.0 // indirect
golang.org/x/term v0.37.0 // indirect
golang.org/x/text v0.31.0 // indirect
golang.org/x/tools v0.38.0 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect
howett.net/plist v1.0.0 // indirect
)

86
go.sum
View File

@@ -6,6 +6,8 @@ github.com/andybalholm/brotli v1.2.0 h1:ukwgCxwYrmACq68yiUqwIWnGY0cTPox/M94sVwTo
github.com/andybalholm/brotli v1.2.0/go.mod h1:rzTDkvFWvIrjDXZHkuS16NPggd91W3kUSvPlQ1pLaKY=
github.com/andybalholm/cascadia v1.3.2 h1:3Xi6Dw5lHF15JtdcmAHD3i1+T8plmv7BQ/nsViSLyss=
github.com/andybalholm/cascadia v1.3.2/go.mod h1:7gtRlve5FxPPgIgX36uWBX58OdBsSS6lUvCFb+h7KvU=
github.com/chengxilo/virtualterm v1.0.4 h1:Z6IpERbRVlfB8WkOmtbHiDbBANU7cimRIof7mk9/PwM=
github.com/chengxilo/virtualterm v1.0.4/go.mod h1:DyxxBZz/x1iqJjFxTFcr6/x+jSpqN0iwWCOK1q10rlY=
github.com/cloudflare/circl v1.6.1 h1:zqIqSPIndyBh1bjLVVDHMPpVKqp8Su/V+6MeDzzQBQ0=
github.com/cloudflare/circl v1.6.1/go.mod h1:uddAzsPgqdMAYatqJ0lsjX1oECcQLIlRpzZh3pJrofs=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
@@ -21,8 +23,9 @@ github.com/frankban/quicktest v1.14.6/go.mod h1:4ptaffx2x8+WTWXmUCuVU6aPUX1/Mz7z
github.com/fsnotify/fsnotify v1.9.0 h1:2Ml+OJNzbYCTzsxtv8vKSFD9PbJjmhYF14k/jKC7S9k=
github.com/fsnotify/fsnotify v1.9.0/go.mod h1:8jBTzvmWwFyi3Pb8djgCCO5IBqzKJ/Jwo8TRcHyHii0=
github.com/go-ole/go-ole v1.2.5/go.mod h1:pprOEPIfldk/42T2oK7lQ4v4JSDwmV0As9GaiUsvbm0=
github.com/go-ole/go-ole v1.2.6 h1:/Fpf6oFPoeFik9ty7siob0G6Ke8QvQEuVcuChpwXzpY=
github.com/go-ole/go-ole v1.2.6/go.mod h1:pprOEPIfldk/42T2oK7lQ4v4JSDwmV0As9GaiUsvbm0=
github.com/go-ole/go-ole v1.3.0 h1:Dt6ye7+vXGIKZ7Xtk4s6/xVdGDQynvom7xCFEdWr6uE=
github.com/go-ole/go-ole v1.3.0/go.mod h1:5LS6F96DhAwUc7C+1HLexzMXY1xGRSryjyPPKW6zv78=
github.com/go-viper/mapstructure/v2 v2.4.0 h1:EBsztssimR/CONLSZZ04E8qAkxNYq4Qp9LvH92wZUgs=
github.com/go-viper/mapstructure/v2 v2.4.0/go.mod h1:oJDH3BJKyqBA2TXFhDsKDGDTlndYOZ6rGS0BRZIxGhM=
github.com/gofrs/uuid/v5 v5.2.0 h1:qw1GMx6/y8vhVsx626ImfKMuS5CvJmhIKKtuyvfajMM=
@@ -56,9 +59,10 @@ github.com/jaypipes/ghw v0.17.0/go.mod h1:In8SsaDqlb1oTyrbmTC14uy+fbBMvp+xdqX51M
github.com/jaypipes/pcidb v1.0.1 h1:WB2zh27T3nwg8AE8ei81sNRb9yWBii3JGNJtT7K9Oic=
github.com/jaypipes/pcidb v1.0.1/go.mod h1:6xYUz/yYEyOkIkUt2t2J2folIuZ4Yg6uByCGFXMCeE4=
github.com/jessevdk/go-flags v1.4.0/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI=
github.com/jsdelivr/globalping-cli v1.5.1 h1:7RZNmIljSBXe0xBeOoGQHXZNwHo6zDuQ0BI9hF12gLY=
github.com/jsdelivr/globalping-cli v1.5.1/go.mod h1:Gw70OWvN6hIt0t4hftyUhcHuJQMTn4CvoobJiaTU0qg=
github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM=
github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo=
github.com/k0kubun/go-ansi v0.0.0-20180517002512-3bf9e2903213/go.mod h1:vNUNkEQ1e29fT/6vq2aBdFsgNPmy8qMdSay1npru+Sw=
github.com/klauspost/compress v1.18.0 h1:c/Cqfb0r+Yi+JtIEq73FWXVkRonBlf0CRNYc8Zttxdo=
github.com/klauspost/compress v1.18.0/go.mod h1:2Pp+KzxcywXVXMr50+X0Q/Lsb43OQHYWRCY2AiWywWQ=
github.com/koron/go-ssdp v0.0.4 h1:1IDwrghSKYM7yLf7XCzbByg2sJ/JcNOZRXS2jczTwz0=
@@ -71,8 +75,6 @@ github.com/libp2p/go-nat v0.2.0 h1:Tyz+bUFAYqGyJ/ppPPymMGbIgNRH+WqC5QrT5fKrrGk=
github.com/libp2p/go-nat v0.2.0/go.mod h1:3MJr+GRpRkyT65EpVPBstXLvOlAPzUVlG6Pwg9ohLJk=
github.com/libp2p/go-netroute v0.2.1 h1:V8kVrpD8GK0Riv15/7VN6RbUQ3URNZVosw7H2v9tksU=
github.com/libp2p/go-netroute v0.2.1/go.mod h1:hraioZr0fhBjG0ZRXJJ6Zj2IVEVNx6tDTFQfSmcq7mQ=
github.com/lionsoul2014/ip2region v2.11.2+incompatible h1:+VRsGcrHz8ewXI/2UzTptJlACsxD/p4xCxuql4u2nKU=
github.com/lionsoul2014/ip2region v2.11.2+incompatible/go.mod h1:+ZBN7PBoh5gG6/y0ZQ85vJDBe21WnfbRrQQwTfliJJI=
github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0 h1:6E+4a0GO5zZEnZ81pIr0yLvtUWk2if982qA3F3QD6H4=
github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0/go.mod h1:zJYVVT2jmtg6P3p1VtQj7WsuWi/y4VnjVBn7F8KPB3I=
github.com/mattn/go-colorable v0.1.14 h1:9A9LHSqF/7dyVVX6g0U9cwm9pG3kP9gSzcuIPHPsaIE=
@@ -92,10 +94,10 @@ github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M=
github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk=
github.com/nxtrace/NTrace-core v1.4.3-rc.1 h1:V19tkw3kKAMQOOh7Ibb/jZFBk4kMUfQYmpxxtsOfYWo=
github.com/nxtrace/NTrace-core v1.4.3-rc.1/go.mod h1:lGhfZ916pEUJh+VzWZTYu7bKBo06pAn+/gXb0A/7gGg=
github.com/oneclickvirt/UnlockTests v0.0.33-20251126065725 h1:VaaK2v17nLGU8FQmJRXPe2bEESzRePbGws0bfq7s/2o=
github.com/oneclickvirt/UnlockTests v0.0.33-20251126065725/go.mod h1:oOa6wj/qECtRMxwBO6D7o0L0F0Q/5sQ747OCnFQqoGE=
github.com/nxtrace/NTrace-core v1.5.0 h1:n+a/FObw/+CcqvhuSQiWcm1q+ODtfo7Wt3VmaIx504I=
github.com/nxtrace/NTrace-core v1.5.0/go.mod h1:/jME48iJ7QaVTzsrTPQyTJ+yExhjeWjax2L6uBd4ckk=
github.com/oneclickvirt/UnlockTests v0.0.34-20260130055000 h1:amgZH8QyTmgZ09t6j0Fi0SbSU03vhZIFjW/1/sOT70M=
github.com/oneclickvirt/UnlockTests v0.0.34-20260130055000/go.mod h1:oOa6wj/qECtRMxwBO6D7o0L0F0Q/5sQ747OCnFQqoGE=
github.com/oneclickvirt/backtrace v0.0.8-20251109090457 h1:599/R/qMAtfPCPG1bPoi6KbjNJzVkKtxm8dvVIdtn5o=
github.com/oneclickvirt/backtrace v0.0.8-20251109090457/go.mod h1:mj9TSow7FNszBb3bQj2Hhm41LwBo7HQP6sgaPtovKdM=
github.com/oneclickvirt/basics v0.0.16-20251112033526 h1:bgoLaqStV3a6mbPiM++0mYizd278GVa6J6yeIiusV+A=
@@ -116,18 +118,16 @@ github.com/oneclickvirt/mbw v0.0.1-20250808061222 h1:WGXOe6QvHiDRhPVMI0VcctjzW08
github.com/oneclickvirt/mbw v0.0.1-20250808061222/go.mod h1:0Vq6NRpyLmGUdfHfL3uDcFsuZhi7KlG+OCs5ky2757Y=
github.com/oneclickvirt/memorytest v0.0.10-20251218032900 h1:SmRFfPLyGfTVWIgC50lEGgOpbqahtMHIlyOMSbrhj9Y=
github.com/oneclickvirt/memorytest v0.0.10-20251218032900/go.mod h1:4kiHsEWkW9r3/1ZcV5xIweU0smiKP0IRfQj74AUIiVI=
github.com/oneclickvirt/nt3 v0.0.10-20251111095706 h1:GEdgL6oAWXY80NIq23mLjcTR3gvLGh9iusFzJK6SoDo=
github.com/oneclickvirt/nt3 v0.0.10-20251111095706/go.mod h1:yo1ufkduFt9QjqG7nqSUf1D3YlQOmFpdlTYniJfclQI=
github.com/oneclickvirt/nt3 v0.0.11-20260112140912 h1:e3tgkEmydsML6ziOdWwsVGwysTRYS82SuWrP0HnIw9g=
github.com/oneclickvirt/nt3 v0.0.11-20260112140912/go.mod h1:u/y3sMhyt4wiQlR7yS68CudwjXCa/4V6ozWI7awsCws=
github.com/oneclickvirt/pingtest v0.0.9-20251104112920 h1:j3Fjhy0YHT/VF7iuAVVELaRXkquvRd64tWWfFLJs01o=
github.com/oneclickvirt/pingtest v0.0.9-20251104112920/go.mod h1:gxwsxxwitNQiGq2OI0ZogYoOLwc8DtuOdSRe6/EvRqs=
github.com/oneclickvirt/portchecker v0.0.3-20250728015900 h1:AomzdppSOFB70AJESQhlp0IPbsHTTJGimAWDk2TzCWM=
github.com/oneclickvirt/portchecker v0.0.3-20250728015900/go.mod h1:9sjMDPCd4Z40wkYB0S9gQPGH8YPtnNE1ZJthVIuHUzA=
github.com/oneclickvirt/privatespeedtest v0.0.1-20260112095218 h1:VcglFz85LVPo8wE8AkBhgXHHUUVI2Ae9ng6+hY6ewx4=
github.com/oneclickvirt/privatespeedtest v0.0.1-20260112095218/go.mod h1:IXOlKKX4DUNqxOaW/K9bcdrBiWxo0jGSLXeBeo7NrTo=
github.com/oneclickvirt/privatespeedtest v0.0.1-20260112130218 h1:h2k2fHtrsIIP/x/apEWkQGlTKuIumz8GrUR/df41YhE=
github.com/oneclickvirt/privatespeedtest v0.0.1-20260112130218/go.mod h1:IXOlKKX4DUNqxOaW/K9bcdrBiWxo0jGSLXeBeo7NrTo=
github.com/oneclickvirt/security v0.0.8-20251112080734 h1:WpwdGbwpiBP2YA1lNsymati5uvBbWFlN9CXHYgd3/fE=
github.com/oneclickvirt/security v0.0.8-20251112080734/go.mod h1:aPMIwqsz7wiUH1cqvtRr9+QcQRkKzlUWecDM6SGVddc=
github.com/oneclickvirt/security v0.0.8-20260104113003 h1:NfmI83E+BAla+6ruFVDJIM5wsIi3ENH7FIcdn/kRhUI=
github.com/oneclickvirt/security v0.0.8-20260104113003/go.mod h1:aPMIwqsz7wiUH1cqvtRr9+QcQRkKzlUWecDM6SGVddc=
github.com/oneclickvirt/speedtest v0.0.11-20251102151740 h1:1NUrNt5ay6/xVNC5x62UrQjPqK8jgbKtyjBml/3boZg=
github.com/oneclickvirt/speedtest v0.0.11-20251102151740/go.mod h1:fy0II2Wo7kDWVBKTwcHdodZwyfmJo0g8N9V02EwQDZE=
github.com/oneclickvirt/stream v0.0.2-20250924154001 h1:GuJWdiPkoK84+y/+oHKr2Ghl3c/MzS9Z5m1nM+lMmy4=
@@ -157,8 +157,8 @@ github.com/prometheus-community/pro-bing v0.4.1 h1:aMaJwyifHZO0y+h8+icUz0xbToHbi
github.com/prometheus-community/pro-bing v0.4.1/go.mod h1:aLsw+zqCaDoa2RLVVSX3+UiCkBBXTMtZC3c7EkfWnAE=
github.com/quic-go/qpack v0.5.1 h1:giqksBPnT/HDtZ6VhtFKgoLOWmlyo9Ei6u9PqzIMbhI=
github.com/quic-go/qpack v0.5.1/go.mod h1:+PC4XFrEskIVkcLzpEkbLqq1uCoxPhQuvK5rH1ZgaEg=
github.com/quic-go/quic-go v0.53.0 h1:QHX46sISpG2S03dPeZBgVIZp8dGagIaiu2FiVYvpCZI=
github.com/quic-go/quic-go v0.53.0/go.mod h1:e68ZEaCdyviluZmy44P6Iey98v/Wfz6HCjQEm+l8zTY=
github.com/quic-go/quic-go v0.55.0 h1:zccPQIqYCXDt5NmcEabyYvOnomjs8Tlwl7tISjJh9Mk=
github.com/quic-go/quic-go v0.55.0/go.mod h1:DR51ilwU1uE164KuWXhinFcKWGlEjzys2l8zUl5Ss1U=
github.com/refraction-networking/utls v1.7.3 h1:L0WRhHY7Oq1T0zkdzVZMR6zWZv+sXbHB9zcuvsAEqCo=
github.com/refraction-networking/utls v1.7.3/go.mod h1:TUhh27RHMGtQvjQq+RyO11P6ZNQNBb3N0v7wsEjKAIQ=
github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc=
@@ -168,10 +168,8 @@ github.com/rodaine/table v1.3.0 h1:4/3S3SVkHnVZX91EHFvAMV7K42AnJ0XuymRR2C5HlGE=
github.com/rodaine/table v1.3.0/go.mod h1:47zRsHar4zw0jgxGxL9YtFfs7EGN6B/TaS+/Dmk4WxU=
github.com/rogpeppe/go-internal v1.14.1 h1:UQB4HGPB6osV0SQTLymcB4TgvyWu6ZyliaW0tI/otEQ=
github.com/rogpeppe/go-internal v1.14.1/go.mod h1:MaRKkUm5W0goXpeCfT7UZI6fk/L7L7so1lCWt35ZSgc=
github.com/sagikazarmark/locafero v0.11.0 h1:1iurJgmM9G3PA/I+wWYIOw/5SyBtxapeHDcg+AAIFXc=
github.com/sagikazarmark/locafero v0.11.0/go.mod h1:nVIGvgyzw595SUSUE6tvCp3YYTeHs15MvlmU87WwIik=
github.com/schollz/progressbar/v3 v3.14.4 h1:W9ZrDSJk7eqmQhd3uxFNNcTr0QL+xuGNI9dEMrw0r74=
github.com/schollz/progressbar/v3 v3.14.4/go.mod h1:aT3UQ7yGm+2ZjeXPqsjTenwL3ddUiuZ0kfQ/2tHlyNI=
github.com/sagikazarmark/locafero v0.12.0 h1:/NQhBAkUb4+fH1jivKHWusDYFjMOOKU88eegjfxfHb4=
github.com/sagikazarmark/locafero v0.12.0/go.mod h1:sZh36u/YSZ918v0Io+U9ogLYQJ9tLLBmM4eneO6WwsI=
github.com/schollz/progressbar/v3 v3.17.1 h1:bI1MTaoQO+v5kzklBjYNRQLoVpe0zbyRZNK6DFkVC5U=
github.com/schollz/progressbar/v3 v3.17.1/go.mod h1:RzqpnsPQNjUyIgdglUjRLgD7sVnxN1wpmBMV+UiEbL4=
github.com/shirou/gopsutil v3.21.11+incompatible h1:+1+c1VGhc88SSonWP6foOcLhvnKlUeu/erjjvaPEYiI=
@@ -180,8 +178,6 @@ github.com/shirou/gopsutil/v4 v4.25.6 h1:kLysI2JsKorfaFPcYmcJqbzROzsBWEOAtw6A7dI
github.com/shirou/gopsutil/v4 v4.25.6/go.mod h1:PfybzyydfZcN+JMMjkF6Zb8Mq1A/VcogFFg7hj50W9c=
github.com/showwin/speedtest-go v1.7.10 h1:9o5zb7KsuzZKn+IE2//z5btLKJ870JwO6ETayUkqRFw=
github.com/showwin/speedtest-go v1.7.10/go.mod h1:Ei7OCTmNPdWofMadzcfgq1rUO7mvJy9Jycj//G7vyfA=
github.com/sourcegraph/conc v0.3.1-0.20240121214520-5f936abd7ae8 h1:+jumHNA0Wrelhe64i8F6HNlS8pkoyMv5sreGx2Ry5Rw=
github.com/sourcegraph/conc v0.3.1-0.20240121214520-5f936abd7ae8/go.mod h1:3n1Cwaq1E1/1lhQhtRK2ts/ZwZEhjcQeJQ1RuC6Q/8U=
github.com/spf13/afero v1.15.0 h1:b/YBCLWAJdFWJTN9cLhiXXcD7mzKn9Dm86dNnfyQw1I=
github.com/spf13/afero v1.15.0/go.mod h1:NC2ByUVxtQs4b3sIUphxK0NioZnmxgyCrfzeuq8lxMg=
github.com/spf13/cast v1.10.0 h1:h2x0u2shc1QuLHfxi+cTJvs30+ZAHOGRic8uyGTDWxY=
@@ -206,15 +202,16 @@ github.com/subosito/gotenv v1.6.0 h1:9NlTDc1FTs4qu0DDq7AEtTPNw6SVm7uBMsUCUjABIf8
github.com/subosito/gotenv v1.6.0/go.mod h1:Dk4QP5c2W3ibzajGcXpNraDfq2IrhjMIvMSWPKKo0FU=
github.com/tidwall/gjson v1.18.0 h1:FIDeeyB800efLX89e5a8Y0BNH+LOngJyGrIWxG2FKQY=
github.com/tidwall/gjson v1.18.0/go.mod h1:/wbyibRr2FHMks5tjHJ5F8dMZh3AcwJEMf5vlfC0lxk=
github.com/tidwall/match v1.1.1 h1:+Ho715JplO36QYgwN9PGYNhgZvoUSc9X2c80KVTi+GA=
github.com/tidwall/match v1.1.1/go.mod h1:eRSPERbgtNPcGhD8UCthc6PmLEQXEWd3PRB5JTxsfmM=
github.com/tidwall/match v1.2.0 h1:0pt8FlkOwjN2fPt4bIl4BoNxb98gGHN2ObFEDkrfZnM=
github.com/tidwall/match v1.2.0/go.mod h1:eRSPERbgtNPcGhD8UCthc6PmLEQXEWd3PRB5JTxsfmM=
github.com/tidwall/pretty v1.2.0/go.mod h1:ITEVvHYasfjBbM0u2Pg8T2nJnzm8xPwvNhhsoaGGjNU=
github.com/tidwall/pretty v1.2.1 h1:qjsOFOWWQl+N3RsoF5/ssm1pHmJJwhjlSbZ51I6wMl4=
github.com/tidwall/pretty v1.2.1/go.mod h1:ITEVvHYasfjBbM0u2Pg8T2nJnzm8xPwvNhhsoaGGjNU=
github.com/tklauser/go-sysconf v0.3.14 h1:g5vzr9iPFFz24v2KZXs/pvpvh8/V9Fw6vQK5ZZb78yU=
github.com/tklauser/go-sysconf v0.3.14/go.mod h1:1ym4lWMLUOhuBOPGtRcJm7tEGX4SCYNEEEtghGG/8uY=
github.com/tklauser/numcpus v0.8.0 h1:Mx4Wwe/FjZLeQsK/6kt2EOepwwSl7SmJrK5bV/dXYgY=
github.com/tklauser/numcpus v0.8.0/go.mod h1:ZJZlAY+dmR4eut8epnzf0u/VwodKmryxR8txiloSqBE=
github.com/tklauser/numcpus v0.9.0 h1:lmyCHtANi8aRUgkckBgoDk1nHCux3n2cgkJLXdQGPDo=
github.com/tklauser/numcpus v0.9.0/go.mod h1:SN6Nq1O3VychhC1npsWostA+oW+VOQTxZrS604NSRyI=
github.com/tsosunchia/powclient v0.2.0 h1:BDrI3O69CbzarbD+CnnY10Kuwn8xlmtQR0m5tBp+BG8=
github.com/tsosunchia/powclient v0.2.0/go.mod h1:fkb7tTW+HMH3ZWZzQUgwvvFKMj/8Ys+C8Sm/uGQzDA0=
github.com/xjasonlyu/windivert-go v0.0.0-20201010013527-4239d0afa76f h1:glX3VZCYwW1/OmFxOjazfCtBLxXB3YNZk9LF2lYx+Lw=
@@ -226,8 +223,8 @@ github.com/yusufpapurcu/wmi v1.2.4 h1:zFUKzehAFReQwLys1b/iSMl+JQGSCSjtVqQn9bBrPo
github.com/yusufpapurcu/wmi v1.2.4/go.mod h1:SBZ9tNy3G9/m5Oi98Zks0QjeHVDvuK0qfxQmPyzfmi0=
go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto=
go.uber.org/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE=
go.uber.org/mock v0.5.2 h1:LbtPTcP8A5k9WPXj54PPPbjcI4Y6lhyOZXn+VS7wNko=
go.uber.org/mock v0.5.2/go.mod h1:wLlUxC2vVTPTaE3UD51E0BGOAElKrILxhVSDYQLld5o=
go.uber.org/mock v0.6.0 h1:hyF9dfmbgIX5EfOdasqLsWD6xqpNZlXblLB/Dbnwv3Y=
go.uber.org/mock v0.6.0/go.mod h1:KiVJ4BqZJaMj4svdfmHM0AUx4NJYO8ZNpPnZn1Z+BBU=
go.uber.org/multierr v1.11.0 h1:blXXJkSxSSfBVBlC76pxqeO+LN3aDfLQo+309xJstO0=
go.uber.org/multierr v1.11.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y=
go.uber.org/zap v1.27.0 h1:aJMhYGrd5QSmlpLMr2MftRKl7t8J8PTZPA732ud/XR8=
@@ -239,14 +236,14 @@ golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8U
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
golang.org/x/crypto v0.8.0/go.mod h1:mRqEX+O9/h5TFCrQhkgjo2yKi0yYA+9ecGkdQoHrywE=
golang.org/x/crypto v0.12.0/go.mod h1:NF0Gs7EO5K4qLn+Ylc+fih8BSTeIjAP05siRnAh98yw=
golang.org/x/crypto v0.42.0 h1:chiH31gIWm57EkTXpwnqf8qeuMUi0yekh6mT2AvFlqI=
golang.org/x/crypto v0.42.0/go.mod h1:4+rDnOTJhQCx2q7/j6rAN5XDw8kPjeaXEUR2eL94ix8=
golang.org/x/crypto v0.45.0 h1:jMBrvKuj23MTlT0bQEOBcAE0mjg8mK9RXFhRH6nyF3Q=
golang.org/x/crypto v0.45.0/go.mod h1:XTGrrkGJve7CYK7J8PEww4aY7gM3qMCElcJQ8n8JdX4=
golang.org/x/lint v0.0.0-20200302205851-738671d3881b/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY=
golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg=
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
golang.org/x/mod v0.27.0 h1:kb+q2PyFnEADO2IEF935ehFUXlWiNjJWtRNgBLSfbxQ=
golang.org/x/mod v0.27.0/go.mod h1:rWI627Fq0DEoudcK+MBkNkCe0EetEaDSwJJkCcjpazc=
golang.org/x/mod v0.29.0 h1:HV8lRxZC4l2cr3Zq1LvtOsi/ThTgWnUk/y64QSs8GwA=
golang.org/x/mod v0.29.0/go.mod h1:NyhrlYXJ2H4eJiRy/WDBO6HMqZQ6q9nk4JzS3NuCK+w=
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
@@ -255,14 +252,14 @@ golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs=
golang.org/x/net v0.9.0/go.mod h1:d48xBJpPfHeWQsugry2m+kC02ZBRGRgulfHnEXEuWns=
golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg=
golang.org/x/net v0.14.0/go.mod h1:PpSgVXXLK0OxS0F31C1/tv6XNguvCrnXIDrFMspZIUI=
golang.org/x/net v0.44.0 h1:evd8IRDyfNBMBTTY5XRF1vaZlD+EmWx6x8PkhR04H/I=
golang.org/x/net v0.44.0/go.mod h1:ECOoLqd5U3Lhyeyo/QDCEVQ4sNgYsqvCZ722XogGieY=
golang.org/x/net v0.47.0 h1:Mx+4dIFzqraBXUugkia1OOvlD6LemFo1ALMHjrXDOhY=
golang.org/x/net v0.47.0/go.mod h1:/jNxtkgq5yWUGYkaZGqo27cfGZ1c5Nen03aYrrKpVRU=
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.17.0 h1:l60nONMj9l5drqw6jlhIELNv9I0A4OFgRsG9k2oT9Ug=
golang.org/x/sync v0.17.0/go.mod h1:9KTHXmSnoGruLpwFjVSX0lNNA75CykiMECbovNTZqGI=
golang.org/x/sync v0.18.0 h1:kr88TuHDroi+UVf+0hZnirlk8o8T+4MrK6mr60WkH/I=
golang.org/x/sync v0.18.0/go.mod h1:9KTHXmSnoGruLpwFjVSX0lNNA75CykiMECbovNTZqGI=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190916202348-b4ddaad3f8a3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
@@ -272,38 +269,37 @@ golang.org/x/sys v0.0.0-20201204225414-ed752295db88/go.mod h1:h1NjWce9XRLGQEsW7w
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.7.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.11.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.20.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/sys v0.36.0 h1:KVRy2GtZBrk1cBYA7MKu5bEZFxQk4NIDV6RLVcC8o0k=
golang.org/x/sys v0.36.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks=
golang.org/x/sys v0.38.0 h1:3yZWxaJjBmCWXqhN1qh02AkOnCQ1poK6oF+a7xWL6Gc=
golang.org/x/sys v0.38.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k=
golang.org/x/term v0.7.0/go.mod h1:P32HKFT3hSsZrRxla30E9HqToFYAQPCMs/zFMBUFqPY=
golang.org/x/term v0.8.0/go.mod h1:xPskH00ivmX89bAKVGSKKtLOWNx2+17Eiy94tnKShWo=
golang.org/x/term v0.11.0/go.mod h1:zC9APTIj3jG3FdV/Ons+XE1riIZXG4aZ4GTHiPZJPIU=
golang.org/x/term v0.20.0/go.mod h1:8UkIAJTvZgivsXaD6/pH6U9ecQzZ45awqEOzuCvwpFY=
golang.org/x/term v0.35.0 h1:bZBVKBudEyhRcajGcNc3jIfWPqV4y/Kt2XcoigOWtDQ=
golang.org/x/term v0.35.0/go.mod h1:TPGtkTLesOwf2DE8CgVYiZinHAOuy5AYUYT1lENIZnA=
golang.org/x/term v0.37.0 h1:8EGAD0qCmHYZg6J17DvsMy9/wJ7/D/4pV/wfnld5lTU=
golang.org/x/term v0.37.0/go.mod h1:5pB4lxRNYYVZuTLmy8oR2BH8dflOR+IbTYFD8fi3254=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8=
golang.org/x/text v0.12.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE=
golang.org/x/text v0.29.0 h1:1neNs90w9YzJ9BocxfsQNHKuAT4pkghyXc4nhZ6sJvk=
golang.org/x/text v0.29.0/go.mod h1:7MhJOA9CD2qZyOKYazxdYMF85OwPdEr9jTtBpO7ydH4=
golang.org/x/text v0.31.0 h1:aC8ghyu4JhP8VojJ2lEHBnochRno1sgL6nEi9WGFGMM=
golang.org/x/text v0.31.0/go.mod h1:tKRAlv61yKIjGGHX/4tP1LTbc13YSec1pxVEWXzfoeM=
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20200130002326-2f3ba24bd6e7/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU=
golang.org/x/tools v0.36.0 h1:kWS0uv/zsvHEle1LbV5LE8QujrxB3wfQyxHfhOk0Qkg=
golang.org/x/tools v0.36.0/go.mod h1:WBDiHKJK8YgLHlcQPYQzNCkUxUypCaa5ZegCVutKm+s=
golang.org/x/tools v0.38.0 h1:Hx2Xv8hISq8Lm16jvBZ2VQf+RLmbd7wVUsALibYI/IQ=
golang.org/x/tools v0.38.0/go.mod h1:yEsQ/d/YK8cjh0L6rZlY8tgtlKiBNTL14pGDJPJpYQs=
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=

View File

@@ -27,7 +27,7 @@ import (
)
var (
ecsVersion = "v0.1.107" // 融合怪版本号
ecsVersion = "v0.1.113" // 融合怪版本号
configs = params.NewConfig(ecsVersion) // 全局配置实例
userSetFlags = make(map[string]bool) // 用于跟踪哪些参数是用户显式设置的
)

View File

@@ -152,7 +152,7 @@ goecs_check() {
os=$(uname -s 2>/dev/null || echo "Unknown")
arch=$(uname -m 2>/dev/null || echo "Unknown")
check_china
ECS_VERSION="0.1.106"
ECS_VERSION="0.1.112"
for api in \
"https://api.github.com/repos/oneclickvirt/ecs/releases/latest" \
"https://githubapi.spiritlhl.workers.dev/repos/oneclickvirt/ecs/releases/latest" \
@@ -164,8 +164,8 @@ goecs_check() {
sleep 1
done
if [ -z "$ECS_VERSION" ]; then
_yellow "Unable to get version info, using default version 0.1.106"
ECS_VERSION="0.1.106"
_yellow "Unable to get version info, using default version 0.1.112"
ECS_VERSION="0.1.112"
fi
version_output=""
for cmd_path in "goecs" "./goecs" "/usr/bin/goecs" "/usr/local/bin/goecs"; do

View File

@@ -330,6 +330,8 @@ func RunNetworkTests(config *params.Config, wg3 *sync.WaitGroup, ptInfo *string,
fmt.Println(pt.WebsiteTest())
}
}
// 等待第三方库的输出完全刷新到标准输出
time.Sleep(300 * time.Millisecond)
}, tempOutput, output)
}
@@ -348,10 +350,22 @@ func RunSpeedTests(config *params.Config, output, tempOutput string, outputMutex
tests.CustomSP("net", "ct", config.SpNum, config.Language)
tests.CustomSP("net", "cmcc", config.SpNum, config.Language)
} else if config.Choice == "2" || config.Choice == "3" || config.Choice == "4" || config.Choice == "5" {
tests.CustomSP("net", "global", 4, config.Language)
// 中文模式:就近测速 + 三网各1个 + Other 1个带回退
if config.Language == "zh" {
tests.NearbySP()
tests.CustomSP("net", "other", 1, config.Language)
tests.CustomSP("net", "cu", 1, config.Language)
tests.CustomSP("net", "ct", 1, config.Language)
tests.CustomSP("net", "cmcc", 1, config.Language)
} else {
// 英文模式保持原有逻辑测4个global节点
tests.CustomSP("net", "global", 4, config.Language)
}
} else if config.Choice == "6" {
tests.CustomSP("net", "global", 11, config.Language)
}
// 等待第三方库的输出完全刷新到标准输出
time.Sleep(500 * time.Millisecond)
}
}, tempOutput, output)
}
@@ -370,6 +384,8 @@ func RunEnglishNetworkTests(config *params.Config, wg3 *sync.WaitGroup, ptInfo *
fmt.Println(pt.WebsiteTest())
}
}
// 等待第三方库的输出完全刷新到标准输出
time.Sleep(300 * time.Millisecond)
}, tempOutput, output)
}
@@ -383,6 +399,8 @@ func RunEnglishSpeedTests(config *params.Config, output, tempOutput string, outp
tests.ShowHead(config.Language)
tests.NearbySP()
tests.CustomSP("net", "global", -1, config.Language)
// 等待第三方库的输出完全刷新到标准输出
time.Sleep(500 * time.Millisecond)
}
}, tempOutput, output)
}
@@ -442,7 +460,7 @@ func HandleSignalInterrupt(sig chan os.Signal, config *params.Config, startTime
// 使用context来控制上传goroutine
uploadCtx, uploadCancel := context.WithTimeout(context.Background(), 30*time.Second)
defer uploadCancel()
go func() {
httpURL, httpsURL := utils.ProcessAndUpload(finalOutput, config.FilePath, config.EnableUpload)
select {
@@ -455,7 +473,7 @@ func HandleSignalInterrupt(sig chan os.Signal, config *params.Config, startTime
return
}
}()
select {
case result := <-resultChan:
uploadCancel() // 成功完成取消context

View File

@@ -56,8 +56,8 @@ func printTableRow(result pst.SpeedTestResult) {
}
location = fmt.Sprintf("%s%s", carrier, result.City)
}
if len(location) > 14 {
location = location[:14] + "..."
if len(location) > 15 {
location = location[:15]
}
upload := "N/A"
if result.UploadMbps > 0 {
@@ -69,7 +69,7 @@ func printTableRow(result pst.SpeedTestResult) {
}
latency := fmt.Sprintf("%.2f ms", result.PingLatency.Seconds()*1000)
packetLoss := "N/A"
fmt.Print(formatString(location, 16))
fmt.Print(formatString(location, 15))
fmt.Print(formatString(upload, 16))
fmt.Print(formatString(download, 16))
fmt.Print(formatString(latency, 16))
@@ -78,21 +78,26 @@ func printTableRow(result pst.SpeedTestResult) {
}
// privateSpeedTest 使用 privatespeedtest 进行单个运营商测速
// operator 参数:只支持 "cmcc"、"cu"、"ct"
func privateSpeedTest(num int, operator string) error {
// operator 参数:只支持 "cmcc"、"cu"、"ct"、"other"
// 返回值:实际测试的节点数量和错误信息
func privateSpeedTest(num int, operator string) (int, error) {
defer func() {
if r := recover(); r != nil {
fmt.Fprintf(os.Stderr, "[WARN] privateSpeedTest panic: %v\n", r)
}
}()
*pst.NoProgress = true
*pst.Quiet = true
*pst.NoHeader = true
*pst.NoProjectURL = true
// 加载服务器列表
serverList, err := pst.LoadServerList()
if err != nil {
return fmt.Errorf("加载自定义服务器列表失败")
return 0, fmt.Errorf("加载自定义服务器列表失败")
}
// 使用三网测速模式(每个运营商选择指定数量的最低延迟节点)
serversPerISP := num
if serversPerISP <= 0 || serversPerISP > 5{
if serversPerISP <= 0 || serversPerISP > 5 {
serversPerISP = 2
}
// 单个运营商测速:先过滤服务器列表
@@ -104,8 +109,10 @@ func privateSpeedTest(num int, operator string) error {
carrierType = "Unicom"
case "ct":
carrierType = "Telecom"
case "other":
carrierType = "Other"
default:
return fmt.Errorf("不支持的运营商类型: %s", operator)
return 0, fmt.Errorf("不支持的运营商类型: %s", operator)
}
// 过滤出指定运营商的服务器
filteredServers := pst.FilterServersByISP(serverList.Servers, carrierType)
@@ -117,17 +124,19 @@ func privateSpeedTest(num int, operator string) error {
// 使用 FindBestServers 选择最佳服务器
candidateServers, err := pst.FindBestServers(
filteredServers,
candidateCount, // 选择更多候选节点用于去重
5*time.Second, // ping 超时
true, // 显示进度条
true, // 静默
candidateCount, // 选择更多候选节点用于去重
5*time.Second, // ping 超时
true, // 显示进度条
true, // 静默
)
if err != nil {
return fmt.Errorf("分组查找失败")
return 0, fmt.Errorf("分组查找失败")
}
// 去重:确保同一运营商内城市不重复
seenCities := make(map[string]bool)
var bestServers []pst.ServerWithLatencyInfo
// 保留更多备用节点,以应对测速失败的情况(保留 serversPerISP * 2 个备用节点)
maxBackupServers := serversPerISP * 2
for _, serverInfo := range candidateServers {
city := serverInfo.Server.City
if city == "" {
@@ -136,35 +145,70 @@ func privateSpeedTest(num int, operator string) error {
if !seenCities[city] {
seenCities[city] = true
bestServers = append(bestServers, serverInfo)
// 去重后取前 serversPerISP 个
if len(bestServers) >= serversPerISP {
// 去重后保留足够的备用节点
if len(bestServers) >= maxBackupServers {
break
}
}
}
if len(bestServers) == 0 {
return fmt.Errorf("去重后没有可用的服务器")
return 0, fmt.Errorf("去重后没有可用的服务器")
}
// 执行测速并逐个打印结果(不打印表头)
// 统计成功输出的节点数
successCount := 0
for i, serverInfo := range bestServers {
// 如果已经成功输出了足够的节点,则停止测试
if successCount >= serversPerISP {
break
}
result := pst.RunSpeedTest(
serverInfo.Server,
false, // 不禁用下载测试
false, // 不禁用上传测试
6, // 并发线程数
12*time.Second, // 超时时间
false, // 不禁用下载测试
false, // 不禁用上传测试
6, // 并发线程数
12*time.Second, // 超时时间
&serverInfo,
false, // 不显示进度条
false, // 不显示进度条
)
if result.Success {
// 只要测试成功且有任意一个速度值有效,就输出结果(部分成功也显示)
if result.Success && (result.UploadMbps > 0 || result.DownloadMbps > 0) {
printTableRow(result)
// 只有上传和下载都成功时才计入成功数
if result.UploadMbps > 0 && result.DownloadMbps > 0 {
successCount++
}
}
// 在测试之间暂停(除了最后一个
if i < len(bestServers)-1 {
// 在测试之间暂停(如果还需要继续测试的话
if successCount < serversPerISP && i < len(bestServers)-1 {
time.Sleep(1 * time.Second)
}
}
return nil
// 返回实际成功输出的节点数量
return successCount, nil
}
// privateSpeedTestWithFallback 使用私有测速,如果失败则回退到 global 节点
// 主要用于 Other 类型的测速
func privateSpeedTestWithFallback(num int, operator, language string) {
defer func() {
if r := recover(); r != nil {
fmt.Fprintf(os.Stderr, "[WARN] privateSpeedTestWithFallback panic: %v\n", r)
}
}()
// 先尝试私有节点测速
testedCount, err := privateSpeedTest(num, operator)
if err != nil || testedCount == 0 {
// 私有节点失败,回退到 global 节点
var url, parseType string
url = model.NetGlobal
parseType = "id"
if runtime.GOOS == "windows" || sp.OfficialAvailableTest() != nil {
sp.CustomSpeedTest(url, parseType, num, language)
} else {
sp.OfficialCustomSpeedTest(url, parseType, num, language)
}
}
}
func CustomSP(platform, operator string, num int, language string) {
@@ -173,18 +217,26 @@ func CustomSP(platform, operator string, num int, language string) {
fmt.Fprintf(os.Stderr, "[WARN] CustomSP panic: %v\n", r)
}
}()
// 对于三网测速cmcc、cu、ct优先使用 privatespeedtest 进行私有测速
// 对于三网测速cmcc、cu、ct和 other,优先使用 privatespeedtest 进行私有测速
opLower := strings.ToLower(operator)
if opLower == "cmcc" || opLower == "cu" || opLower == "ct" {
err := privateSpeedTest(num, opLower)
if opLower == "cmcc" || opLower == "cu" || opLower == "ct" || opLower == "other" {
testedCount, err := privateSpeedTest(num, opLower)
if err != nil {
fmt.Fprintf(os.Stderr, "[WARN] privatespeedtest failed\n")
// 继续使用原有的兜底方案
} else {
// 测速成功,直接返回
fmt.Fprintf(os.Stderr, "[WARN] privatespeedtest failed: %v\n", err)
// 全部失败,继续使用原有的公共节点兜底方案
} else if testedCount >= num {
// 私有节点测速成功且数量达标,直接返回
return
} else if testedCount > 0 {
// 部分私有节点测速成功,但数量不足,用公共节点补充
fmt.Fprintf(os.Stderr, "[INFO] 私有节点仅测试了 %d 个,补充 %d 个公共节点\n", testedCount, num-testedCount)
num = num - testedCount // 只测剩余数量的公共节点
// 继续执行下面的公共节点测速逻辑
} else {
// testedCount == 0继续使用公共节点
}
}
var url, parseType string
if strings.ToLower(platform) == "cn" {
if strings.ToLower(operator) == "cmcc" {
@@ -218,7 +270,8 @@ func CustomSP(platform, operator string, num int, language string) {
url = model.NetJP
} else if strings.ToLower(operator) == "sg" {
url = model.NetSG
} else if strings.ToLower(operator) == "global" {
} else if strings.ToLower(operator) == "global" || strings.ToLower(operator) == "other" {
// other 类型回退到 global 节点
url = model.NetGlobal
}
parseType = "id"

View File

@@ -219,6 +219,11 @@ func CaptureOutput(f func()) string {
}()
// 执行函数
f()
// 确保所有输出都已经刷新
os.Stdout.Sync()
os.Stderr.Sync()
// 等待一小段时间确保后台goroutine的输出完成
time.Sleep(100 * time.Millisecond)
// 关闭管道写入端,让管道读取端可以读取所有数据
stdoutPipeW.Close()
stderrPipeW.Close()