Compare commits

...

13 Commits

Author SHA1 Message Date
spiritlhl
0258be967d Fix: 去除头显示,使用md格式输出总结 2026-04-17 18:53:49 +08:00
github-actions[bot]
a1794da4e5 chore: update ECS_VERSION to 0.1.121 in goecs.sh 2026-04-17 05:28:46 +00:00
spiritlhl
85a0b30950 Fix: 优化总结 2026-04-17 13:13:10 +08:00
github-actions[bot]
21100fd949 chore: update ECS_VERSION to 0.1.120 in goecs.sh 2026-04-17 02:17:20 +00:00
spiritlhl
d2878dd705 fix:更新版本 2026-04-17 10:00:43 +08:00
spiritlhl
a80ce40739 fix:修复主界面选项 2026-04-17 10:00:19 +08:00
spiritlhl
a1b5691179 fix: 修复相关选项说明含义 2026-04-16 23:50:57 +08:00
github-actions[bot]
6cf35680d5 chore: update ECS_VERSION to 0.1.119 in goecs.sh 2026-04-16 14:07:07 +00:00
spiritlhl
7b74cbe1e7 fix: 增加参数设置和自动化评价总结功能 2026-04-16 21:51:37 +08:00
github-actions[bot]
8137a7ac6a chore: update ECS_VERSION to 0.1.118 in goecs.sh 2026-04-16 04:27:49 +00:00
spiritlhl
04725fef54 feat: 增加类GUI显示,增强参数解析 2026-04-16 12:13:06 +08:00
spiritlhl
4e868a384a fix: 修复readme的Action操作 2026-04-01 04:35:57 +00:00
github-actions[bot]
7a4885346b chore: update ECS_VERSION to 0.1.117 in goecs.sh 2026-04-01 04:24:16 +00:00
13 changed files with 2454 additions and 68 deletions

View File

@@ -40,7 +40,8 @@ jobs:
sed -i 's|security.*Enable/Disable security test (default true)|security Enable/Disable security test (default false)|g' README_EN.md
echo "已更新 README_EN.md"
fi
git add README.md README_EN.md
git add README.md
[ -f "README_EN.md" ] && git add README_EN.md || true
git commit -m "Auto update README files" || echo "No changes to commit"
git push origin ${{ github.ref_name }}
else

View File

@@ -32,8 +32,9 @@ jobs:
- name: Copy repository files
run: |
cp goecs.sh temp_repo/
cp README_EN.md temp_repo/
cp README.md temp_repo/
[ -f "README_EN.md" ] && cp README_EN.md temp_repo/ || true
[ -f "README_ZH.md" ] && cp README_ZH.md temp_repo/ || true
cp LICENSE temp_repo/
- name: Download release assets

View File

@@ -102,6 +102,13 @@ func WithEnableUpload(enable bool) ConfigOption {
}
}
// WithAnalyzeResult 设置是否启用测试后结果总结分析
func WithAnalyzeResult(enable bool) ConfigOption {
return func(c *Config) {
c.AnalyzeResult = enable
}
}
// WithEnableLogger 设置是否启用日志
func WithEnableLogger(enable bool) ConfigOption {
return func(c *Config) {

View File

@@ -28,12 +28,12 @@ func RunAllTests(preCheck utils.NetCheckResult, config *Config) *RunResult {
outputMutex sync.Mutex
infoMutex sync.Mutex
)
startTime := time.Now()
switch config.Language {
case "zh":
runner.RunChineseTests(preCheck, config, &wg1, &wg2, &wg3,
runner.RunChineseTests(preCheck, config, &wg1, &wg2, &wg3,
&basicInfo, &securityInfo, &emailInfo, &mediaInfo, &ptInfo,
&output, tempOutput, startTime, &outputMutex, &infoMutex)
case "en":
@@ -45,9 +45,12 @@ func RunAllTests(preCheck utils.NetCheckResult, config *Config) *RunResult {
&basicInfo, &securityInfo, &emailInfo, &mediaInfo, &ptInfo,
&output, tempOutput, startTime, &outputMutex, &infoMutex)
}
if config.AnalyzeResult {
output = runner.AppendAnalysisSummary(config, output, tempOutput, &outputMutex)
}
endTime := time.Now()
return &RunResult{
Output: output,
Duration: endTime.Sub(startTime),

21
go.mod
View File

@@ -3,6 +3,9 @@ module github.com/oneclickvirt/ecs
go 1.25.4
require (
github.com/charmbracelet/bubbles v1.0.0
github.com/charmbracelet/bubbletea v1.3.10
github.com/charmbracelet/lipgloss v1.1.0
github.com/imroc/req/v3 v3.54.0
github.com/oneclickvirt/UnlockTests v0.0.35-20260207053956
github.com/oneclickvirt/backtrace v0.0.8-20251109090457
@@ -25,8 +28,18 @@ require (
github.com/StackExchange/wmi v1.2.1 // indirect
github.com/andybalholm/brotli v1.2.0 // indirect
github.com/andybalholm/cascadia v1.3.2 // indirect
github.com/atotto/clipboard v0.1.4 // indirect
github.com/aymanbagabas/go-osc52/v2 v2.0.1 // indirect
github.com/charmbracelet/colorprofile v0.4.1 // indirect
github.com/charmbracelet/x/ansi v0.11.6 // indirect
github.com/charmbracelet/x/cellbuf v0.0.15 // indirect
github.com/charmbracelet/x/term v0.2.2 // indirect
github.com/clipperhouse/displaywidth v0.9.0 // indirect
github.com/clipperhouse/stringish v0.1.1 // indirect
github.com/clipperhouse/uax29/v2 v2.5.0 // indirect
github.com/cloudflare/circl v1.6.1 // indirect
github.com/ebitengine/purego v0.8.4 // indirect
github.com/erikgeiser/coninput v0.0.0-20211004153227-1c3628e74d0f // indirect
github.com/fatih/color v1.18.0 // indirect
github.com/fsnotify/fsnotify v1.9.0 // indirect
github.com/go-ole/go-ole v1.3.0 // indirect
@@ -48,15 +61,20 @@ require (
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/lucasb-eyer/go-colorful v1.3.0 // 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
github.com/mattn/go-runewidth v0.0.16 // indirect
github.com/mattn/go-localereader v0.0.1 // indirect
github.com/mattn/go-runewidth v0.0.19 // indirect
github.com/miekg/dns v1.1.61 // indirect
github.com/mitchellh/colorstring v0.0.0-20190213212951-d06e56a500db // indirect
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/muesli/ansi v0.0.0-20230316100256-276c6243b2f6 // indirect
github.com/muesli/cancelreader v0.2.2 // indirect
github.com/muesli/termenv v0.16.0 // 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
@@ -94,6 +112,7 @@ require (
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/xo/terminfo v0.0.0-20220910002029-abceb7e1c41e // indirect
github.com/yusufpapurcu/wmi v1.2.4 // indirect
go.uber.org/multierr v1.11.0 // indirect
go.uber.org/zap v1.27.0 // indirect

53
go.sum
View File

@@ -6,8 +6,40 @@ 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/atotto/clipboard v0.1.4 h1:EH0zSVneZPSuFR11BlR9YppQTVDbh5+16AmcJi4g1z4=
github.com/atotto/clipboard v0.1.4/go.mod h1:ZY9tmq7sm5xIbd9bOK4onWV4S6X0u6GY7Vn0Yu86PYI=
github.com/aymanbagabas/go-osc52/v2 v2.0.1 h1:HwpRHbFMcZLEVr42D4p7XBqjyuxQH5SMiErDT4WkJ2k=
github.com/aymanbagabas/go-osc52/v2 v2.0.1/go.mod h1:uYgXzlJ7ZpABp8OJ+exZzJJhRNQ2ASbcXHWsFqH8hp8=
github.com/charmbracelet/bubbles v1.0.0 h1:12J8/ak/uCZEMQ6KU7pcfwceyjLlWsDLAxB5fXonfvc=
github.com/charmbracelet/bubbles v1.0.0/go.mod h1:9d/Zd5GdnauMI5ivUIVisuEm3ave1XwXtD1ckyV6r3E=
github.com/charmbracelet/bubbletea v1.3.10 h1:otUDHWMMzQSB0Pkc87rm691KZ3SWa4KUlvF9nRvCICw=
github.com/charmbracelet/bubbletea v1.3.10/go.mod h1:ORQfo0fk8U+po9VaNvnV95UPWA1BitP1E0N6xJPlHr4=
github.com/charmbracelet/colorprofile v0.2.3-0.20250311203215-f60798e515dc h1:4pZI35227imm7yK2bGPcfpFEmuY1gc2YSTShr4iJBfs=
github.com/charmbracelet/colorprofile v0.2.3-0.20250311203215-f60798e515dc/go.mod h1:X4/0JoqgTIPSFcRA/P6INZzIuyqdFY5rm8tb41s9okk=
github.com/charmbracelet/colorprofile v0.4.1 h1:a1lO03qTrSIRaK8c3JRxJDZOvhvIeSco3ej+ngLk1kk=
github.com/charmbracelet/colorprofile v0.4.1/go.mod h1:U1d9Dljmdf9DLegaJ0nGZNJvoXAhayhmidOdcBwAvKk=
github.com/charmbracelet/lipgloss v1.1.0 h1:vYXsiLHVkK7fp74RkV7b2kq9+zDLoEU4MZoFqR/noCY=
github.com/charmbracelet/lipgloss v1.1.0/go.mod h1:/6Q8FR2o+kj8rz4Dq0zQc3vYf7X+B0binUUBwA0aL30=
github.com/charmbracelet/x/ansi v0.10.1 h1:rL3Koar5XvX0pHGfovN03f5cxLbCF2YvLeyz7D2jVDQ=
github.com/charmbracelet/x/ansi v0.10.1/go.mod h1:3RQDQ6lDnROptfpWuUVIUG64bD2g2BgntdxH0Ya5TeE=
github.com/charmbracelet/x/ansi v0.11.6 h1:GhV21SiDz/45W9AnV2R61xZMRri5NlLnl6CVF7ihZW8=
github.com/charmbracelet/x/ansi v0.11.6/go.mod h1:2JNYLgQUsyqaiLovhU2Rv/pb8r6ydXKS3NIttu3VGZQ=
github.com/charmbracelet/x/cellbuf v0.0.13-0.20250311204145-2c3ea96c31dd h1:vy0GVL4jeHEwG5YOXDmi86oYw2yuYUGqz6a8sLwg0X8=
github.com/charmbracelet/x/cellbuf v0.0.13-0.20250311204145-2c3ea96c31dd/go.mod h1:xe0nKWGd3eJgtqZRaN9RjMtK7xUYchjzPr7q6kcvCCs=
github.com/charmbracelet/x/cellbuf v0.0.15 h1:ur3pZy0o6z/R7EylET877CBxaiE1Sp1GMxoFPAIztPI=
github.com/charmbracelet/x/cellbuf v0.0.15/go.mod h1:J1YVbR7MUuEGIFPCaaZ96KDl5NoS0DAWkskup+mOY+Q=
github.com/charmbracelet/x/term v0.2.1 h1:AQeHeLZ1OqSXhrAWpYUtZyX1T3zVxfpZuEQMIQaGIAQ=
github.com/charmbracelet/x/term v0.2.1/go.mod h1:oQ4enTYFV7QN4m0i9mzHrViD7TQKvNEEkHUMCmsxdUg=
github.com/charmbracelet/x/term v0.2.2 h1:xVRT/S2ZcKdhhOuSP4t5cLi5o+JxklsoEObBSgfgZRk=
github.com/charmbracelet/x/term v0.2.2/go.mod h1:kF8CY5RddLWrsgVwpw4kAa6TESp6EB5y3uxGLeCqzAI=
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/clipperhouse/displaywidth v0.9.0 h1:Qb4KOhYwRiN3viMv1v/3cTBlz3AcAZX3+y9OLhMtAtA=
github.com/clipperhouse/displaywidth v0.9.0/go.mod h1:aCAAqTlh4GIVkhQnJpbL0T/WfcrJXHcj8C0yjYcjOZA=
github.com/clipperhouse/stringish v0.1.1 h1:+NSqMOr3GR6k1FdRhhnXrLfztGzuG+VuFDfatpWHKCs=
github.com/clipperhouse/stringish v0.1.1/go.mod h1:v/WhFtE1q0ovMta2+m+UbpZ+2/HEXNWYXQgCt4hdOzA=
github.com/clipperhouse/uax29/v2 v2.5.0 h1:x7T0T4eTHDONxFJsL94uKNKPHrclyFI0lm7+w94cO8U=
github.com/clipperhouse/uax29/v2 v2.5.0/go.mod h1:Wn1g7MK6OoeDT0vL+Q0SQLDz/KpfsVRgg6W7ihQeh4g=
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=
@@ -16,6 +48,8 @@ github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/ebitengine/purego v0.8.4 h1:CF7LEKg5FFOsASUj0+QwaXf8Ht6TlFxg09+S9wz0omw=
github.com/ebitengine/purego v0.8.4/go.mod h1:iIjxzd6CiRiOG0UyXP+V1+jWqUXVjPKLAI0mRfJZTmQ=
github.com/erikgeiser/coninput v0.0.0-20211004153227-1c3628e74d0f h1:Y/CXytFA4m6baUTXGLOoWe4PQhGxaX0KpnayAqC48p4=
github.com/erikgeiser/coninput v0.0.0-20211004153227-1c3628e74d0f/go.mod h1:vw97MGsxSvLiUE2X8qFplwetxpGLQrlU1Q9AUEIzCaM=
github.com/fatih/color v1.18.0 h1:S8gINlzdQ840/4pfAwic/ZE0djQEH3wM94VfqLTZcOM=
github.com/fatih/color v1.18.0/go.mod h1:4FelSpRwEGDpQ12mAdzqdOukCy4u8WUtOY6lkT/6HfU=
github.com/frankban/quicktest v1.14.6 h1:7Xjx+VpznH+oBnejlPUj8oUpdxnVs4f8XU8WnHkI4W8=
@@ -75,14 +109,22 @@ 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/lucasb-eyer/go-colorful v1.2.0 h1:1nnpGOrhyZZuNyfu1QjKiUICQ74+3FNCN69Aj6K7nkY=
github.com/lucasb-eyer/go-colorful v1.2.0/go.mod h1:R4dSotOR9KMtayYi1e77YzuveK+i7ruzyGqttikkLy0=
github.com/lucasb-eyer/go-colorful v1.3.0 h1:2/yBRLdWBZKrf7gB40FoiKfAWYQ0lqNcbuQwVHXptag=
github.com/lucasb-eyer/go-colorful v1.3.0/go.mod h1:R4dSotOR9KMtayYi1e77YzuveK+i7ruzyGqttikkLy0=
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=
github.com/mattn/go-colorable v0.1.14/go.mod h1:6LmQG8QLFO4G5z1gPvYEzlUgJ2wF+stgPZH1UqBm1s8=
github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY=
github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
github.com/mattn/go-localereader v0.0.1 h1:ygSAOl7ZXTx4RdPYinUpg6W99U8jWvWi9Ye2JC/oIi4=
github.com/mattn/go-localereader v0.0.1/go.mod h1:8fBrzywKY7BI3czFoHkuzRoWE9C+EiG4R1k4Cjx5p88=
github.com/mattn/go-runewidth v0.0.16 h1:E5ScNMtiwvlvB5paMFdw9p4kSQzbXFikJ5SQO6TULQc=
github.com/mattn/go-runewidth v0.0.16/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w=
github.com/mattn/go-runewidth v0.0.19 h1:v++JhqYnZuu5jSKrk9RbgF5v4CGUjqRfBm05byFGLdw=
github.com/mattn/go-runewidth v0.0.19/go.mod h1:XBkDxAl56ILZc9knddidhrOlY5R/pDhgLpndooCuJAs=
github.com/miekg/dns v1.1.61 h1:nLxbwF3XxhwVSm8g9Dghm9MHPaUZuqhPiGL+675ZmEs=
github.com/miekg/dns v1.1.61/go.mod h1:mnAarhS3nWaW+NVP2wTkYVIZyHNJ098SJZUki3eykwQ=
github.com/mitchellh/colorstring v0.0.0-20190213212951-d06e56a500db h1:62I3jR2EmQ4l5rM/4FEfDWcRD+abF5XlKShorW5LRoQ=
@@ -94,6 +136,12 @@ 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/muesli/ansi v0.0.0-20230316100256-276c6243b2f6 h1:ZK8zHtRHOkbHy6Mmr5D264iyp3TiX5OmNcI5cIARiQI=
github.com/muesli/ansi v0.0.0-20230316100256-276c6243b2f6/go.mod h1:CJlz5H+gyd6CUWT45Oy4q24RdLyn7Md9Vj2/ldJBSIo=
github.com/muesli/cancelreader v0.2.2 h1:3I4Kt4BQjOR54NavqnDogx/MIoWBFa0StPA8ELUXHmA=
github.com/muesli/cancelreader v0.2.2/go.mod h1:3XuTXfFS2VjM+HTLZY9Ak0l6eUKfijIfMUZ4EgX0QYo=
github.com/muesli/termenv v0.16.0 h1:S5AlUN9dENB57rsbnkPyfdGuWIlkmzJjbFf0Tf5FWUc=
github.com/muesli/termenv v0.16.0/go.mod h1:ZRfOIKPFDYQoDFF4Olj7/QJbW60Ol/kL1pU3VfY/Cnk=
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.35-20260207053956 h1:yccGrw/sYOHZMaFJghPVN3Xn6JyTOXsEQc9v0I92k3M=
@@ -216,6 +264,8 @@ github.com/tsosunchia/powclient v0.2.0 h1:BDrI3O69CbzarbD+CnnY10Kuwn8xlmtQR0m5tB
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=
github.com/xjasonlyu/windivert-go v0.0.0-20201010013527-4239d0afa76f/go.mod h1:gh//RKyt2Gesx3eOj3ulzrSQ60ySj2UA4qnOdrtarvg=
github.com/xo/terminfo v0.0.0-20220910002029-abceb7e1c41e h1:JVG44RsyaB9T2KIHavMF/ppJZNG9ZpyihvCd0w101no=
github.com/xo/terminfo v0.0.0-20220910002029-abceb7e1c41e/go.mod h1:RbqR21r5mrJuqunuUZ/Dhy/avygyECGrLceyNeo4LiM=
github.com/xyproto/randomstring v1.0.5 h1:YtlWPoRdgMu3NZtP45drfy1GKoojuR7hmRcnhZqKjWU=
github.com/xyproto/randomstring v1.0.5/go.mod h1:rgmS5DeNXLivK7YprL0pY+lTuhNQW3iGxZ18UQApw/E=
github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
@@ -238,6 +288,8 @@ 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.45.0 h1:jMBrvKuj23MTlT0bQEOBcAE0mjg8mK9RXFhRH6nyF3Q=
golang.org/x/crypto v0.45.0/go.mod h1:XTGrrkGJve7CYK7J8PEww4aY7gM3qMCElcJQ8n8JdX4=
golang.org/x/exp v0.0.0-20240613232115-7f521ea00fb8 h1:yixxcjnhBmY0nkL253HFVIm0JsFHwrHdT3Yh6szTnfY=
golang.org/x/exp v0.0.0-20240613232115-7f521ea00fb8/go.mod h1:jj3sYF3dwk5D+ghuXyeI3r5MFf+NT2An6/9dOA95KSI=
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=
@@ -267,6 +319,7 @@ golang.org/x/sys v0.0.0-20201008064518-c1f3e3309c71/go.mod h1:h1NjWce9XRLGQEsW7w
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20201204225414-ed752295db88/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20210809222454-d867a43fc93e/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=

View File

@@ -27,7 +27,7 @@ import (
)
var (
ecsVersion = "v0.1.117" // 融合怪版本号
ecsVersion = "v0.1.122" // 融合怪版本号
configs = params.NewConfig(ecsVersion) // 全局配置实例
userSetFlags = make(map[string]bool) // 用于跟踪哪些参数是用户显式设置的
)
@@ -99,6 +99,9 @@ func main() {
default:
fmt.Println("Unsupported language")
}
if configs.AnalyzeResult {
output = runner.AppendAnalysisSummary(configs, output, tempOutput, &outputMutex)
}
if preCheck.Connected {
runner.HandleUploadResults(configs, output)
}

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.116"
ECS_VERSION="0.1.121"
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.116"
ECS_VERSION="0.1.116"
_yellow "Unable to get version info, using default version 0.1.121"
ECS_VERSION="0.1.121"
fi
version_output=""
for cmd_path in "goecs" "./goecs" "/usr/bin/goecs" "/usr/local/bin/goecs"; do

1077
internal/analysis/summary.go Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -21,7 +21,7 @@ func GetMenuChoice(language string) string {
sigChan := make(chan os.Signal, 1)
signal.Notify(sigChan, os.Interrupt, syscall.SIGINT, syscall.SIGTERM)
defer signal.Stop(sigChan)
go func() {
select {
case <-sigChan:
@@ -35,7 +35,7 @@ func GetMenuChoice(language string) string {
return
}
}()
for {
var input string
if language == "zh" {
@@ -46,7 +46,7 @@ func GetMenuChoice(language string) string {
fmt.Scanln(&input)
input = strings.TrimSpace(input)
input = strings.TrimRight(input, "\n")
re := regexp.MustCompile(`^\d+$`)
if re.MatchString(input) {
inChoice := input
@@ -125,13 +125,13 @@ func PrintMenuOptions(preCheck utils.NetCheckResult, config *params.Config) {
}
fmt.Printf("使用统计: %s\n", statsInfo)
}
fmt.Println("1. 融合怪完全体(能测全测)")
fmt.Println("2. 极简版(系统信息+CPU+内存+磁盘+测速节点5个)")
fmt.Println("3. 精简版(系统信息+CPU+内存+磁盘+跨国平台解锁+路由+测速节点5个)")
fmt.Println("4. 精简网络版(系统信息+CPU+内存+磁盘+回程+路由+测速节点5个)")
fmt.Println("5. 精简解锁版(系统信息+CPU+内存+磁盘IO+跨国平台解锁+测速节点5个)")
fmt.Println("6. 网络单项(IP质量检测+上游及三网回程+广州三网回程详细路由+全国延迟+TGDC+网站延迟+测速节点11个)")
fmt.Println("7. 解锁单项(跨国平台解锁)")
fmt.Println("1. 融合怪完全体(能测全测)")
fmt.Println("2. 极简版(系统信息+CPU+内存+磁盘+测速节点5个)")
fmt.Println("3. 精简版(系统信息+CPU+内存+磁盘+跨国平台解锁+路由+测速节点5个)")
fmt.Println("4. 精简网络版(系统信息+CPU+内存+磁盘+回程+路由+测速节点5个)")
fmt.Println("5. 精简解锁版(系统信息+CPU+内存+磁盘IO+跨国平台解锁+测速节点5个)")
fmt.Println("6. 网络单项(IP质量检测+上游及三网回程+广州三网回程详细路由+全国延迟+TGDC+网站延迟+测速节点11个)")
fmt.Println("7. 解锁单项(跨国平台解锁)")
fmt.Println("8. 硬件单项(系统信息+CPU+dd磁盘测试+fio磁盘测试)")
fmt.Println("9. IP质量检测(15个数据库的IP质量检测+邮件端口检测)")
fmt.Println("10. 三网回程线路检测+三网回程详细路由(北京上海广州成都)+全国延迟+TGDC+网站延迟")
@@ -145,20 +145,20 @@ func PrintMenuOptions(preCheck utils.NetCheckResult, config *params.Config) {
}
fmt.Printf("%s\n", statsInfo)
}
fmt.Println("1. VPS Fusion Monster Test (Full Test)")
fmt.Println("2. Minimal Test Suite (System Info + CPU + Memory + Disk + 5 Speed Test Nodes)")
fmt.Println("3. Standard Test Suite (System Info + CPU + Memory + Disk + International Platform Unlock + Routing + 5 Speed Test Nodes)")
fmt.Println("4. Network-Focused Test Suite (System Info + CPU + Memory + Disk + Backtrace + Routing + 5 Speed Test Nodes)")
fmt.Println("5. Unlock-Focused Test Suite (System Info + CPU + Memory + Disk IO + International Platform Unlock + 5 Speed Test Nodes)")
fmt.Println("6. Network-Only Test (IP Quality Test + Upstream & 3-Network Backtrace + Guangzhou 3-Network Detailed Routing + National Latency + TGDC + Websites + 11 Speed Test Nodes)")
fmt.Println("7. Unlock-Only Test (International Platform Unlock)")
fmt.Println("8. Hardware-Only Test (System Info + CPU + Memory + dd Disk Test + fio Disk Test)")
fmt.Println("9. IP Quality Test (IP Test with 15 Databases + Email Port Test)")
fmt.Println("0. Exit Program")
fmt.Println("1. VPS Fusion Monster Test (Full Test)")
fmt.Println("2. Minimal Test Suite (System Info + CPU + Memory + Disk + 5 Speed Test Nodes)")
fmt.Println("3. Standard Test Suite (System Info + CPU + Memory + Disk + International Platform Unlock + Routing + 5 Speed Test Nodes)")
fmt.Println("4. Network-Focused Test Suite (System Info + CPU + Memory + Disk + Backtrace + Routing + 5 Speed Test Nodes)")
fmt.Println("5. Unlock-Focused Test Suite (System Info + CPU + Memory + Disk IO + International Platform Unlock + 5 Speed Test Nodes)")
fmt.Println("6. Network-Only Test (IP Quality Test + Upstream & 3-Network Backtrace + Guangzhou 3-Network Detailed Routing + National Latency + TGDC + Websites + 11 Speed Test Nodes)")
fmt.Println("7. Unlock-Only Test (International Platform Unlock)")
fmt.Println("8. Hardware-Only Test (System Info + CPU + Memory + dd Disk Test + fio Disk Test)")
fmt.Println("9. IP Quality Test (IP Test with 15 Databases + Email Port Test)")
fmt.Println("0. Exit Program")
}
}
// HandleMenuMode handles menu selection
// HandleMenuMode handles menu selection using the interactive TUI
func HandleMenuMode(preCheck utils.NetCheckResult, config *params.Config) {
savedParams := config.SaveUserSetParams()
config.BasicStatus = false
@@ -174,64 +174,52 @@ func HandleMenuMode(preCheck utils.NetCheckResult, config *params.Config) {
config.TgdcTestStatus = false
config.WebTestStatus = false
config.AutoChangeDiskMethod = true
PrintMenuOptions(preCheck, config)
Loop:
for {
config.Choice = GetMenuChoice(config.Language)
switch config.Choice {
result := RunTuiMenu(preCheck, config)
if result.quit {
os.Exit(0)
}
// Update language if changed by TUI selection
config.Language = result.language
if result.custom {
config.Choice = "custom"
applyCustomResult(result, preCheck, config)
if config.SpeedTestStatus {
config.OnlyChinaTest = utils.CheckChina(config.EnableLogger, config.Language)
}
} else {
config.Choice = result.choice
switch result.choice {
case "0":
os.Exit(0)
case "1":
SetFullTestStatus(preCheck, config)
config.OnlyChinaTest = utils.CheckChina(config.EnableLogger, config.Language)
break Loop
case "2":
SetMinimalTestStatus(preCheck, config)
break Loop
case "3":
SetStandardTestStatus(preCheck, config)
break Loop
case "4":
SetNetworkFocusedTestStatus(preCheck, config)
break Loop
case "5":
SetUnlockFocusedTestStatus(preCheck, config)
break Loop
case "6":
if !preCheck.Connected {
fmt.Println("Can not test without network connection!")
return
}
SetNetworkOnlyTestStatus(config)
break Loop
case "7":
if !preCheck.Connected {
fmt.Println("Can not test without network connection!")
return
}
SetUnlockOnlyTestStatus(config)
break Loop
case "8":
SetHardwareOnlyTestStatus(preCheck, config)
break Loop
case "9":
if !preCheck.Connected {
fmt.Println("Can not test without network connection!")
return
}
SetIPQualityTestStatus(config)
break Loop
case "10":
if !preCheck.Connected {
fmt.Println("Can not test without network connection!")
return
}
config.Nt3Location = "ALL"
SetRouteTestStatus(config)
break Loop
default:
PrintInvalidChoice(config.Language)
}
// Apply quick options set on the main menu page
config.AnalyzeResult = result.mainAnalyze
config.EnableUpload = result.mainUpload
}
config.RestoreUserSetParams(savedParams)
}

1151
internal/menu/tui.go Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -3,6 +3,7 @@ package params
import (
"flag"
"fmt"
"strings"
)
// Config holds all configuration parameters
@@ -41,6 +42,7 @@ type Config struct {
AutoChangeDiskMethod bool
FilePath string
EnableUpload bool
AnalyzeResult bool
OnlyIpInfoCheck bool
Help bool
Finish bool
@@ -64,7 +66,7 @@ func NewConfig(version string) *Config {
MemoryTestMethod: "stream",
DiskTestMethod: "fio",
DiskTestPath: "",
DiskMultiCheck: false,
DiskMultiCheck: false,
Nt3CheckType: "ipv4",
SpNum: 2,
Width: 82,
@@ -84,6 +86,7 @@ func NewConfig(version string) *Config {
AutoChangeDiskMethod: true,
FilePath: "goecs.txt",
EnableUpload: true,
AnalyzeResult: false,
OnlyIpInfoCheck: false,
Help: false,
Finish: false,
@@ -92,8 +95,57 @@ func NewConfig(version string) *Config {
}
}
// normalizeBoolArgs preprocesses args so that bool flags written as
// "-flag true" or "-flag false" (space-separated) are converted to
// "-flag=true" / "-flag=false" that the standard flag package understands.
// This also strips any duplicate spaces that may appear between tokens when
// args have been assembled by shell scripts or other callers.
func normalizeBoolArgs(args []string) []string {
// All known boolean flag names (without leading dash).
boolFlags := map[string]bool{
"h": true, "help": true, "v": true, "version": true,
"menu": true, "basic": true, "cpu": true, "memory": true,
"disk": true, "ut": true, "security": true, "email": true,
"backtrace": true, "nt3": true, "speed": true, "ping": true,
"tgdc": true, "web": true, "log": true, "upload": true,
"analysis": true, "analyze": true,
"diskmc": true,
}
out := make([]string, 0, len(args))
i := 0
for i < len(args) {
arg := args[i]
// Skip empty tokens that can appear from split on multiple spaces.
if arg == "" {
i++
continue
}
// Detect flag tokens: -flag or --flag (without embedded =).
if strings.HasPrefix(arg, "-") && !strings.Contains(arg, "=") {
name := strings.TrimLeft(arg, "-")
if boolFlags[name] {
// Peek at next token: if it is "true" or "false", merge.
if i+1 < len(args) {
next := strings.ToLower(strings.TrimSpace(args[i+1]))
if next == "true" || next == "false" {
out = append(out, arg+"="+next)
i += 2
continue
}
}
}
}
out = append(out, arg)
i++
}
return out
}
// ParseFlags parses command line flags
func (c *Config) ParseFlags(args []string) {
args = normalizeBoolArgs(args)
c.GoecsFlag.BoolVar(&c.Help, "h", false, "Show help information")
c.GoecsFlag.BoolVar(&c.Help, "help", false, "Show help information")
c.GoecsFlag.BoolVar(&c.ShowVersion, "v", false, "Display version information")
@@ -131,6 +183,8 @@ func (c *Config) ParseFlags(args []string) {
c.GoecsFlag.IntVar(&c.SpNum, "spnum", 2, "Set the number of servers per operator for speed test")
c.GoecsFlag.BoolVar(&c.EnableLogger, "log", false, "Enable/Disable logging in the current path")
c.GoecsFlag.BoolVar(&c.EnableUpload, "upload", true, "Enable/Disable upload the result")
c.GoecsFlag.BoolVar(&c.AnalyzeResult, "analysis", false, "Enable/Disable post-test concise summary analysis")
c.GoecsFlag.BoolVar(&c.AnalyzeResult, "analyze", false, "Enable/Disable post-test concise summary analysis")
c.GoecsFlag.Parse(args)
c.GoecsFlag.Visit(func(f *flag.Flag) {
@@ -222,6 +276,9 @@ func (c *Config) SaveUserSetParams() map[string]interface{} {
if c.UserSetFlags["spnum"] {
saved["spnum"] = c.SpNum
}
if c.UserSetFlags["analysis"] || c.UserSetFlags["analyze"] {
saved["analysis"] = c.AnalyzeResult
}
return saved
}
@@ -340,6 +397,11 @@ func (c *Config) RestoreUserSetParams(saved map[string]interface{}) {
c.SpNum = intVal
}
}
if val, ok := saved["analysis"]; ok {
if boolVal, ok := val.(bool); ok {
c.AnalyzeResult = boolVal
}
}
c.ValidateParams()
}

View File

@@ -10,6 +10,7 @@ import (
"sync"
"time"
"github.com/oneclickvirt/ecs/internal/analysis"
"github.com/oneclickvirt/ecs/internal/params"
"github.com/oneclickvirt/ecs/internal/tests"
"github.com/oneclickvirt/ecs/utils"
@@ -153,7 +154,7 @@ func RunBasicTests(preCheck utils.NetCheckResult, config *params.Config, basicIn
}
if config.BasicStatus {
fmt.Printf("%s", *basicInfo)
} else if (config.Input == "6" || config.Input == "9") && config.SecurityTestStatus {
} else if (config.Choice == "6" || config.Choice == "9") && config.SecurityTestStatus {
scanner := bufio.NewScanner(strings.NewReader(*basicInfo))
for scanner.Scan() {
line := scanner.Text()
@@ -363,6 +364,12 @@ func RunSpeedTests(config *params.Config, output, tempOutput string, outputMutex
}
} else if config.Choice == "6" {
tests.CustomSP("net", "global", 11, config.Language)
} else {
// Custom menu mode and any other fallback choices.
tests.NearbySP()
tests.CustomSP("net", "cu", config.SpNum, config.Language)
tests.CustomSP("net", "ct", config.SpNum, config.Language)
tests.CustomSP("net", "cmcc", config.SpNum, config.Language)
}
// 等待第三方库的输出完全刷新到标准输出
time.Sleep(500 * time.Millisecond)
@@ -427,6 +434,20 @@ func AppendTimeInfo(config *params.Config, output, tempOutput string, startTime
}, tempOutput, output)
}
// AppendAnalysisSummary appends a concise bilingual summary for easier interpretation.
func AppendAnalysisSummary(config *params.Config, output, tempOutput string, outputMutex *sync.Mutex) string {
outputMutex.Lock()
defer outputMutex.Unlock()
finalOutput := output
return utils.PrintAndCapture(func() {
summary := analysis.GenerateSummary(config, finalOutput)
if strings.TrimSpace(summary) == "" {
return
}
fmt.Println(summary)
}, tempOutput, output)
}
// HandleSignalInterrupt handles interrupt signals
func HandleSignalInterrupt(sig chan os.Signal, config *params.Config, startTime *time.Time, output *string, tempOutput string, uploadDone chan bool, outputMutex *sync.Mutex) {
select {