Skip to content

Commit e4a759f

Browse files
committed
fix:修改非选项1时的测速逻辑,区分中英文测速使用不同的节点逻辑
1 parent e5c4b0c commit e4a759f

File tree

5 files changed

+162
-54
lines changed

5 files changed

+162
-54
lines changed

.back/create_public_branch.py

Lines changed: 82 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -47,43 +47,104 @@ def modify_go_mod(filepath):
4747
print(f"✓ Removed privatespeedtest/security from {filepath}")
4848

4949

50-
def modify_speed_go(filepath):
50+
def remove_code_block(lines, start_marker, end_condition='empty_line'):
5151
"""
52-
Brutally remove privatespeedtest-related code from speed.go
53-
by deleting known blocks from upstream source.
52+
Remove code block from lines starting with start_marker.
53+
54+
Args:
55+
lines: List of file lines
56+
start_marker: String or list of strings to identify block start
57+
end_condition: 'empty_line' (default) or 'closing_brace' or custom function
58+
59+
Returns:
60+
Modified lines with the block removed
5461
"""
55-
content = read_file(filepath)
62+
if isinstance(start_marker, str):
63+
start_marker = [start_marker]
64+
65+
result = []
66+
skip_mode = False
67+
brace_depth = 0
68+
69+
i = 0
70+
while i < len(lines):
71+
line = lines[i]
72+
73+
# Check if we should start skipping
74+
if not skip_mode:
75+
for marker in start_marker:
76+
if marker in line:
77+
skip_mode = True
78+
if end_condition == 'closing_brace':
79+
# Count opening braces on the function declaration line
80+
brace_depth = line.count('{') - line.count('}')
81+
break
82+
83+
if not skip_mode:
84+
result.append(line)
85+
else:
86+
# We're in skip mode
87+
if end_condition == 'empty_line':
88+
# Skip until we find an empty line
89+
if line.strip() == '':
90+
skip_mode = False
91+
# Don't add the empty line, continue to next
92+
elif end_condition == 'closing_brace':
93+
# Track brace depth
94+
brace_depth += line.count('{') - line.count('}')
95+
if brace_depth == 0 and '}' in line:
96+
# Function ended, skip until next empty line
97+
end_condition = 'empty_line'
98+
99+
i += 1
100+
101+
return result
56102

57-
content = re.sub(
58-
r'\n\s*"time"\s*\n',
59-
'\n',
60-
content,
61-
flags=re.MULTILINE
62-
)
63103

104+
def modify_speed_go(filepath):
105+
"""
106+
Remove privatespeedtest-related code from speed.go.
107+
Uses line-by-line processing for reliability.
108+
"""
109+
content = read_file(filepath)
110+
lines = content.split('\n')
111+
112+
# Remove specific code blocks by their comment markers
113+
blocks_to_remove = [
114+
'// formatString 格式化字符串到指定宽度',
115+
'// printTableRow 打印表格行',
116+
'// privateSpeedTest 使用 privatespeedtest 进行单个运营商测速',
117+
'// privateSpeedTestWithFallback 使用私有测速,如果失败则回退到 global 节点',
118+
'// 对于三网测速(cmcc、cu、ct)和 other,优先使用 privatespeedtest 进行私有测速',
119+
]
120+
121+
for block_marker in blocks_to_remove:
122+
lines = remove_code_block(lines, block_marker)
123+
124+
# Reconstruct content
125+
content = '\n'.join(lines)
126+
127+
# Remove privatespeedtest import
64128
content = re.sub(
65129
r'\n\s*"github\.com/oneclickvirt/privatespeedtest/pst"\s*\n',
66130
'\n',
67131
content,
68132
flags=re.MULTILINE
69133
)
70-
71-
content = re.sub(
72-
r'// formatString 格式化字符串到指定宽度[\s\S]*?return nil\n}\n',
73-
'',
74-
content,
75-
flags=re.MULTILINE
76-
)
77-
134+
135+
# Remove time import (only used by privatespeedtest)
78136
content = re.sub(
79-
r'^[ \t]*// 对于三网测速(cmcc、cu、ct),优先使用 privatespeedtest 进行私有测速[\s\S]*?\n\s*\n',
137+
r'\n\s*"time"\s*\n',
80138
'\n',
81139
content,
82140
flags=re.MULTILINE
83141
)
84-
142+
143+
# Clean up multiple consecutive empty lines (optional)
144+
content = re.sub(r'\n{3,}', '\n\n', content)
145+
85146
write_file(filepath, content)
86-
print(f"✓ Cleanly removed privatespeedtest from {filepath}")
147+
print(f"✓ Removed privatespeedtest from {filepath}")
87148

88149
def modify_utils_go(filepath):
89150
"""

README_NEW_USER.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -482,6 +482,8 @@ Abuser 或 Abuse 的滥用得分会直接影响机器的正常使用(中国境
482482

483483
先测的官方推荐的测速点,然后测有代表性的国际测速点,最后测国内三大运营商ping值最低的测速点。
484484

485+
由于 speedtest.net 和 speedtest.cn 平台公开的测速节点被刷BTPT的刷烂了(他们为了对等上传PCDN的流量狂刷下载),所以这块本人独家融合的境内私有测速节点不再公开,优先使用私有的境内运营商测速节点进行测速,且写死限制每个IP每日仅支持获取测速数据10次,超限自动降级为使用公共测速节点进行测速
486+
485487
境内使用为主就看境内测速即可,境外使用看境外测速,官方测速点可以代表受测的宿主机本地带宽基准。
486488

487489
一般来说中国境外的服务器的带宽100Mbps起步,中国境内的服务器1Mbps带宽起步,具体看线路优劣,带宽特别大有时候未必用得上,够用就行了。

goecs.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ import (
2727
)
2828

2929
var (
30-
ecsVersion = "v0.1.108" // 融合怪版本号
30+
ecsVersion = "v0.1.109" // 融合怪版本号
3131
configs = params.NewConfig(ecsVersion) // 全局配置实例
3232
userSetFlags = make(map[string]bool) // 用于跟踪哪些参数是用户显式设置的
3333
)

internal/runner/runner.go

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -348,7 +348,17 @@ func RunSpeedTests(config *params.Config, output, tempOutput string, outputMutex
348348
tests.CustomSP("net", "ct", config.SpNum, config.Language)
349349
tests.CustomSP("net", "cmcc", config.SpNum, config.Language)
350350
} else if config.Choice == "2" || config.Choice == "3" || config.Choice == "4" || config.Choice == "5" {
351-
tests.CustomSP("net", "global", 4, config.Language)
351+
// 中文模式:就近测速 + 三网各1个 + Other 1个(带回退)
352+
if config.Language == "zh" {
353+
tests.NearbySP()
354+
tests.CustomSP("net", "other", 1, config.Language)
355+
tests.CustomSP("net", "cu", 1, config.Language)
356+
tests.CustomSP("net", "ct", 1, config.Language)
357+
tests.CustomSP("net", "cmcc", 1, config.Language)
358+
} else {
359+
// 英文模式:保持原有逻辑,测4个global节点
360+
tests.CustomSP("net", "global", 4, config.Language)
361+
}
352362
} else if config.Choice == "6" {
353363
tests.CustomSP("net", "global", 11, config.Language)
354364
}
@@ -442,7 +452,7 @@ func HandleSignalInterrupt(sig chan os.Signal, config *params.Config, startTime
442452
// 使用context来控制上传goroutine
443453
uploadCtx, uploadCancel := context.WithTimeout(context.Background(), 30*time.Second)
444454
defer uploadCancel()
445-
455+
446456
go func() {
447457
httpURL, httpsURL := utils.ProcessAndUpload(finalOutput, config.FilePath, config.EnableUpload)
448458
select {
@@ -455,7 +465,7 @@ func HandleSignalInterrupt(sig chan os.Signal, config *params.Config, startTime
455465
return
456466
}
457467
}()
458-
468+
459469
select {
460470
case result := <-resultChan:
461471
uploadCancel() // 成功完成,取消context

internal/tests/speed.go

Lines changed: 64 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -69,7 +69,7 @@ func printTableRow(result pst.SpeedTestResult) {
6969
}
7070
latency := fmt.Sprintf("%.2f ms", result.PingLatency.Seconds()*1000)
7171
packetLoss := "N/A"
72-
fmt.Print(formatString(location, 16))
72+
fmt.Print(formatString(location, 15))
7373
fmt.Print(formatString(upload, 16))
7474
fmt.Print(formatString(download, 16))
7575
fmt.Print(formatString(latency, 16))
@@ -78,25 +78,26 @@ func printTableRow(result pst.SpeedTestResult) {
7878
}
7979

8080
// privateSpeedTest 使用 privatespeedtest 进行单个运营商测速
81-
// operator 参数:只支持 "cmcc"、"cu"、"ct"
82-
func privateSpeedTest(num int, operator string) error {
81+
// operator 参数:只支持 "cmcc"、"cu"、"ct"、"other"
82+
// 返回值:实际测试的节点数量和错误信息
83+
func privateSpeedTest(num int, operator string) (int, error) {
8384
defer func() {
8485
if r := recover(); r != nil {
8586
fmt.Fprintf(os.Stderr, "[WARN] privateSpeedTest panic: %v\n", r)
8687
}
8788
}()
8889
*pst.NoProgress = true
89-
*pst.Quiet = true
90-
*pst.NoHeader = true
91-
*pst.NoProjectURL = true
90+
*pst.Quiet = true
91+
*pst.NoHeader = true
92+
*pst.NoProjectURL = true
9293
// 加载服务器列表
9394
serverList, err := pst.LoadServerList()
9495
if err != nil {
95-
return fmt.Errorf("加载自定义服务器列表失败")
96+
return 0, fmt.Errorf("加载自定义服务器列表失败")
9697
}
9798
// 使用三网测速模式(每个运营商选择指定数量的最低延迟节点)
9899
serversPerISP := num
99-
if serversPerISP <= 0 || serversPerISP > 5{
100+
if serversPerISP <= 0 || serversPerISP > 5 {
100101
serversPerISP = 2
101102
}
102103
// 单个运营商测速:先过滤服务器列表
@@ -108,8 +109,10 @@ func privateSpeedTest(num int, operator string) error {
108109
carrierType = "Unicom"
109110
case "ct":
110111
carrierType = "Telecom"
112+
case "other":
113+
carrierType = "Other"
111114
default:
112-
return fmt.Errorf("不支持的运营商类型: %s", operator)
115+
return 0, fmt.Errorf("不支持的运营商类型: %s", operator)
113116
}
114117
// 过滤出指定运营商的服务器
115118
filteredServers := pst.FilterServersByISP(serverList.Servers, carrierType)
@@ -121,13 +124,13 @@ func privateSpeedTest(num int, operator string) error {
121124
// 使用 FindBestServers 选择最佳服务器
122125
candidateServers, err := pst.FindBestServers(
123126
filteredServers,
124-
candidateCount, // 选择更多候选节点用于去重
125-
5*time.Second, // ping 超时
126-
true, // 显示进度条
127-
true, // 静默
127+
candidateCount, // 选择更多候选节点用于去重
128+
5*time.Second, // ping 超时
129+
true, // 显示进度条
130+
true, // 静默
128131
)
129132
if err != nil {
130-
return fmt.Errorf("分组查找失败")
133+
return 0, fmt.Errorf("分组查找失败")
131134
}
132135
// 去重:确保同一运营商内城市不重复
133136
seenCities := make(map[string]bool)
@@ -147,18 +150,18 @@ func privateSpeedTest(num int, operator string) error {
147150
}
148151
}
149152
if len(bestServers) == 0 {
150-
return fmt.Errorf("去重后没有可用的服务器")
153+
return 0, fmt.Errorf("去重后没有可用的服务器")
151154
}
152155
// 执行测速并逐个打印结果(不打印表头)
153156
for i, serverInfo := range bestServers {
154157
result := pst.RunSpeedTest(
155158
serverInfo.Server,
156-
false, // 不禁用下载测试
157-
false, // 不禁用上传测试
158-
6, // 并发线程数
159-
12*time.Second, // 超时时间
159+
false, // 不禁用下载测试
160+
false, // 不禁用上传测试
161+
6, // 并发线程数
162+
12*time.Second, // 超时时间
160163
&serverInfo,
161-
false, // 不显示进度条
164+
false, // 不显示进度条
162165
)
163166
if result.Success {
164167
printTableRow(result)
@@ -168,7 +171,31 @@ func privateSpeedTest(num int, operator string) error {
168171
time.Sleep(1 * time.Second)
169172
}
170173
}
171-
return nil
174+
// 返回实际测试的节点数量
175+
return len(bestServers), nil
176+
}
177+
178+
// privateSpeedTestWithFallback 使用私有测速,如果失败则回退到 global 节点
179+
// 主要用于 Other 类型的测速
180+
func privateSpeedTestWithFallback(num int, operator, language string) {
181+
defer func() {
182+
if r := recover(); r != nil {
183+
fmt.Fprintf(os.Stderr, "[WARN] privateSpeedTestWithFallback panic: %v\n", r)
184+
}
185+
}()
186+
// 先尝试私有节点测速
187+
testedCount, err := privateSpeedTest(num, operator)
188+
if err != nil || testedCount == 0 {
189+
// 私有节点失败,回退到 global 节点
190+
var url, parseType string
191+
url = model.NetGlobal
192+
parseType = "id"
193+
if runtime.GOOS == "windows" || sp.OfficialAvailableTest() != nil {
194+
sp.CustomSpeedTest(url, parseType, num, language)
195+
} else {
196+
sp.OfficialCustomSpeedTest(url, parseType, num, language)
197+
}
198+
}
172199
}
173200

174201
func CustomSP(platform, operator string, num int, language string) {
@@ -177,16 +204,23 @@ func CustomSP(platform, operator string, num int, language string) {
177204
fmt.Fprintf(os.Stderr, "[WARN] CustomSP panic: %v\n", r)
178205
}
179206
}()
180-
// 对于三网测速(cmcc、cu、ct),优先使用 privatespeedtest 进行私有测速
207+
// 对于三网测速(cmcc、cu、ct)和 other,优先使用 privatespeedtest 进行私有测速
181208
opLower := strings.ToLower(operator)
182-
if opLower == "cmcc" || opLower == "cu" || opLower == "ct" {
183-
err := privateSpeedTest(num, opLower)
209+
if opLower == "cmcc" || opLower == "cu" || opLower == "ct" || opLower == "other" {
210+
testedCount, err := privateSpeedTest(num, opLower)
184211
if err != nil {
185-
fmt.Fprintf(os.Stderr, "[WARN] privatespeedtest failed\n")
186-
// 继续使用原有的兜底方案
187-
} else {
188-
// 测速成功,直接返回
212+
fmt.Fprintf(os.Stderr, "[WARN] privatespeedtest failed: %v\n", err)
213+
// 全部失败,继续使用原有的公共节点兜底方案
214+
} else if testedCount >= num {
215+
// 私有节点测速成功且数量达标,直接返回
189216
return
217+
} else if testedCount > 0 {
218+
// 部分私有节点测速成功,但数量不足,用公共节点补充
219+
fmt.Fprintf(os.Stderr, "[INFO] 私有节点仅测试了 %d 个,补充 %d 个公共节点\n", testedCount, num-testedCount)
220+
num = num - testedCount // 只测剩余数量的公共节点
221+
// 继续执行下面的公共节点测速逻辑
222+
} else {
223+
// testedCount == 0,继续使用公共节点
190224
}
191225
}
192226

@@ -223,7 +257,8 @@ func CustomSP(platform, operator string, num int, language string) {
223257
url = model.NetJP
224258
} else if strings.ToLower(operator) == "sg" {
225259
url = model.NetSG
226-
} else if strings.ToLower(operator) == "global" {
260+
} else if strings.ToLower(operator) == "global" || strings.ToLower(operator) == "other" {
261+
// other 类型回退到 global 节点
227262
url = model.NetGlobal
228263
}
229264
parseType = "id"

0 commit comments

Comments
 (0)