From 40f63e6cb13e241605d85ee58d62fe4b06e5f51d Mon Sep 17 00:00:00 2001 From: spiritlhl <103393591+spiritLHLS@users.noreply.github.com> Date: Sun, 2 Nov 2025 16:37:07 +0000 Subject: [PATCH] =?UTF-8?q?fix=EF=BC=9A=E6=8B=86=E5=88=86=E5=8D=95?= =?UTF-8?q?=E6=96=87=E4=BB=B6=E9=87=8D=E6=9E=84=E7=BB=84=E7=BB=87=E5=BD=A2?= =?UTF-8?q?=E5=BC=8F=EF=BC=8C=E4=BE=BF=E4=BA=8E=E5=90=8E=E7=BB=AD=E7=BB=B4?= =?UTF-8?q?=E6=8A=A4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .gitignore | 5 +- README.md | 16 +- README_EN.md | 16 +- goecs.go | 1163 +------------------------------------ internal/menu/menu.go | 365 ++++++++++++ internal/params/params.go | 369 ++++++++++++ internal/runner/runner.go | 489 ++++++++++++++++ 7 files changed, 1275 insertions(+), 1148 deletions(-) create mode 100644 internal/menu/menu.go create mode 100644 internal/params/params.go create mode 100644 internal/runner/runner.go diff --git a/.gitignore b/.gitignore index 9f33dd5..9507581 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,5 @@ vendor/ -.idea/ \ No newline at end of file +.idea/ +ecs +goecs.txt +*.log \ No newline at end of file diff --git a/README.md b/README.md index 03ba303..b049c25 100644 --- a/README.md +++ b/README.md @@ -205,6 +205,8 @@ Usage: goecs [options] -email Enable/Disable email port test (default true) -h Show help information + -help + Show help information -l string Set language (supported: en, zh) (default "zh") -log @@ -212,28 +214,34 @@ Usage: goecs [options] -memory Enable/Disable memory test (default true) -memorym string - Set memory test method (supported: sysbench, dd, winsat) (default "sysbench") + Set memory test method (supported: stream, sysbench, dd, winsat, auto) (default "stream") -menu Enable/Disable menu mode, disable example: -menu=false (default true) -nt3 Enable/Disable NT3 test (in 'en' language or on windows it always false) (default true) -nt3loc string - Specify NT3 test location (supported: GZ, SH, BJ, CD for Guangzhou, Shanghai, Beijing, Chengdu) (default "GZ") + Specify NT3 test location (supported: GZ, SH, BJ, CD, ALL for Guangzhou, Shanghai, Beijing, Chengdu and all) (default "GZ") -nt3t string Set NT3 test type (supported: both, ipv4, ipv6) (default "ipv4") + -ping + Enable/Disable ping test -security Enable/Disable security test (default true) -speed Enable/Disable speed test (default true) - -ping - Enable/Disable ping test (default false) -spnum int Set the number of servers per operator for speed test (default 2) + -tgdc + Enable/Disable Telegram DC test -upload Enable/Disable upload the result (default true) -ut Enable/Disable unlock media test (default true) -v Display version information + -version + Display version information + -web + Enable/Disable popular websites test ``` diff --git a/README_EN.md b/README_EN.md index 16e6dbc..96aa637 100644 --- a/README_EN.md +++ b/README_EN.md @@ -204,6 +204,8 @@ Usage: goecs [options] -email Enable/Disable email port test (default true) -h Show help information + -help + Show help information -l string Set language (supported: en, zh) (default "zh") -log @@ -211,28 +213,34 @@ Usage: goecs [options] -memory Enable/Disable memory test (default true) -memorym string - Set memory test method (supported: sysbench, dd, winsat) (default "sysbench") + Set memory test method (supported: stream, sysbench, dd, winsat, auto) (default "stream") -menu Enable/Disable menu mode, disable example: -menu=false (default true) -nt3 Enable/Disable NT3 test (in 'en' language or on windows it always false) (default true) -nt3loc string - Specify NT3 test location (supported: GZ, SH, BJ, CD for Guangzhou, Shanghai, Beijing, Chengdu) (default "GZ") + Specify NT3 test location (supported: GZ, SH, BJ, CD, ALL for Guangzhou, Shanghai, Beijing, Chengdu and all) (default "GZ") -nt3t string Set NT3 test type (supported: both, ipv4, ipv6) (default "ipv4") + -ping + Enable/Disable ping test -security Enable/Disable security test (default true) -speed Enable/Disable speed test (default true) - -ping - Enable/Disable ping test (default false) -spnum int Set the number of servers per operator for speed test (default 2) + -tgdc + Enable/Disable Telegram DC test -upload Enable/Disable upload the result (default true) -ut Enable/Disable unlock media test (default true) -v Display version information + -version + Display version information + -web + Enable/Disable popular websites test ``` diff --git a/goecs.go b/goecs.go index 6528272..b135a8e 100644 --- a/goecs.go +++ b/goecs.go @@ -1,16 +1,11 @@ package main import ( - "bufio" - "context" - "flag" "fmt" "net/http" "os" "os/signal" - "regexp" "runtime" - "strings" "sync" "syscall" "time" @@ -21,162 +16,25 @@ import ( basicmodel "github.com/oneclickvirt/basics/model" cputestmodel "github.com/oneclickvirt/cputest/model" disktestmodel "github.com/oneclickvirt/disktest/disk" - "github.com/oneclickvirt/ecs/cputest" - "github.com/oneclickvirt/ecs/disktest" - "github.com/oneclickvirt/ecs/memorytest" - "github.com/oneclickvirt/ecs/nexttrace" - "github.com/oneclickvirt/ecs/speedtest" - "github.com/oneclickvirt/ecs/unlocktest" - "github.com/oneclickvirt/ecs/upstreams" + menu "github.com/oneclickvirt/ecs/internal/menu" + params "github.com/oneclickvirt/ecs/internal/params" + "github.com/oneclickvirt/ecs/internal/runner" "github.com/oneclickvirt/ecs/utils" gostunmodel "github.com/oneclickvirt/gostun/model" memorytestmodel "github.com/oneclickvirt/memorytest/memory" nt3model "github.com/oneclickvirt/nt3/model" ptmodel "github.com/oneclickvirt/pingtest/model" - "github.com/oneclickvirt/pingtest/pt" - "github.com/oneclickvirt/portchecker/email" speedtestmodel "github.com/oneclickvirt/speedtest/model" ) var ( - ecsVersion = "v0.1.95" - menuMode bool - onlyChinaTest bool - input, choice string - showVersion bool - enableLogger bool - language string - cpuTestMethod, cpuTestThreadMode string - memoryTestMethod string - diskTestMethod, diskTestPath string - diskMultiCheck bool - nt3CheckType, nt3Location string - spNum int - width = 82 - basicStatus, cpuTestStatus, memoryTestStatus, diskTestStatus bool - commTestStatus, utTestStatus, securityTestStatus, emailTestStatus bool - backtraceStatus, nt3Status, speedTestStatus, pingTestStatus bool - tgdcTestStatus, webTestStatus bool - autoChangeDiskTestMethod = true - filePath = "goecs.txt" - enabelUpload = true - onlyIpInfoCheckStatus, help bool - goecsFlag = flag.NewFlagSet("goecs", flag.ContinueOnError) - finish bool - // 用于跟踪哪些参数是用户显式设置的 - userSetFlags = make(map[string]bool) + ecsVersion = "v0.1.96" + configs = params.NewConfig(ecsVersion) // 全局配置实例 + userSetFlags = make(map[string]bool) // 用于跟踪哪些参数是用户显式设置的 ) -func getMenuChoice(language string) string { - ctx, cancel := context.WithCancel(context.Background()) - defer cancel() - sigChan := make(chan os.Signal, 1) - signal.Notify(sigChan, os.Interrupt, syscall.SIGINT, syscall.SIGTERM) - defer signal.Stop(sigChan) - inputChan := make(chan string, 1) - go func() { - select { - case <-sigChan: - fmt.Println("\n程序在选择过程中被用户中断") - os.Exit(0) - case <-ctx.Done(): - return - } - }() - for { - go func() { - var input string - fmt.Print("请输入选项 / Please enter your choice: ") - fmt.Scanln(&input) - input = strings.TrimSpace(input) - input = strings.TrimRight(input, "\n") - select { - case inputChan <- input: - case <-ctx.Done(): - return - } - }() - select { - case input := <-inputChan: - re := regexp.MustCompile(`^\d+$`) - if re.MatchString(input) { - inChoice := input - switch inChoice { - case "0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "10": - return inChoice - default: - if language == "zh" { - fmt.Println("无效的选项") - } else { - fmt.Println("Invalid choice") - } - } - } else { - if language == "zh" { - fmt.Println("输入错误,请输入一个纯数字") - } else { - fmt.Println("Invalid input, please enter a number") - } - } - case <-ctx.Done(): - return "" - } - } -} - -func parseFlags() { - goecsFlag.BoolVar(&help, "h", false, "Show help information") - goecsFlag.BoolVar(&showVersion, "v", false, "Display version information") - goecsFlag.BoolVar(&menuMode, "menu", true, "Enable/Disable menu mode, disable example: -menu=false") // true 默认启用菜单栏模式 - goecsFlag.StringVar(&language, "l", "zh", "Set language (supported: en, zh)") - goecsFlag.BoolVar(&basicStatus, "basic", true, "Enable/Disable basic test") - goecsFlag.BoolVar(&cpuTestStatus, "cpu", true, "Enable/Disable CPU test") - goecsFlag.BoolVar(&memoryTestStatus, "memory", true, "Enable/Disable memory test") - goecsFlag.BoolVar(&diskTestStatus, "disk", true, "Enable/Disable disk test") - goecsFlag.BoolVar(&commTestStatus, "comm", true, "Enable/Disable common media test") - goecsFlag.BoolVar(&utTestStatus, "ut", true, "Enable/Disable unlock media test") - goecsFlag.BoolVar(&securityTestStatus, "security", true, "Enable/Disable security test") - goecsFlag.BoolVar(&emailTestStatus, "email", true, "Enable/Disable email port test") - goecsFlag.BoolVar(&backtraceStatus, "backtrace", true, "Enable/Disable backtrace test (in 'en' language or on windows it always false)") - goecsFlag.BoolVar(&nt3Status, "nt3", true, "Enable/Disable NT3 test (in 'en' language or on windows it always false)") - goecsFlag.BoolVar(&speedTestStatus, "speed", true, "Enable/Disable speed test") - goecsFlag.BoolVar(&pingTestStatus, "ping", false, "Enable/Disable ping test") - goecsFlag.BoolVar(&tgdcTestStatus, "tgdc", false, "Enable/Disable Telegram DC test") - goecsFlag.BoolVar(&webTestStatus, "web", false, "Enable/Disable popular websites test") - goecsFlag.StringVar(&cpuTestMethod, "cpum", "sysbench", "Set CPU test method (supported: sysbench, geekbench, winsat)") - goecsFlag.StringVar(&cpuTestThreadMode, "cput", "multi", "Set CPU test thread mode (supported: single, multi)") - goecsFlag.StringVar(&memoryTestMethod, "memorym", "stream", "Set memory test method (supported: stream, sysbench, dd, winsat, auto)") - goecsFlag.StringVar(&diskTestMethod, "diskm", "fio", "Set disk test method (supported: fio, dd, winsat)") - goecsFlag.StringVar(&diskTestPath, "diskp", "", "Set disk test path, e.g., -diskp /root") - goecsFlag.BoolVar(&diskMultiCheck, "diskmc", false, "Enable/Disable multiple disk checks, e.g., -diskmc=false") - goecsFlag.StringVar(&nt3Location, "nt3loc", "GZ", "Specify NT3 test location (supported: GZ, SH, BJ, CD, ALL for Guangzhou, Shanghai, Beijing, Chengdu and all)") - goecsFlag.StringVar(&nt3CheckType, "nt3t", "ipv4", "Set NT3 test type (supported: both, ipv4, ipv6)") - goecsFlag.IntVar(&spNum, "spnum", 2, "Set the number of servers per operator for speed test") - goecsFlag.BoolVar(&enableLogger, "log", false, "Enable/Disable logging in the current path") - goecsFlag.BoolVar(&enabelUpload, "upload", true, "Enable/Disable upload the result") - goecsFlag.Parse(os.Args[1:]) - - // 记录用户显式设置的参数 - goecsFlag.Visit(func(f *flag.Flag) { - userSetFlags[f.Name] = true - }) -} - -func handleHelpAndVersion() bool { - if help { - fmt.Printf("Usage: %s [options]\n", os.Args[0]) - goecsFlag.PrintDefaults() - return true - } - if showVersion { - fmt.Println(ecsVersion) - return true - } - return false -} - func initLogger() { - if enableLogger { + if configs.EnableLogger { gostunmodel.EnableLoger = true basicmodel.EnableLoger = true cputestmodel.EnableLoger = true @@ -191,992 +49,19 @@ func initLogger() { } } -// saveUserSetParams 保存用户通过命令行显式设置的参数值 -func saveUserSetParams() map[string]interface{} { - saved := make(map[string]interface{}) - - if userSetFlags["basic"] { - saved["basic"] = basicStatus - } - if userSetFlags["cpu"] { - saved["cpu"] = cpuTestStatus - } - if userSetFlags["memory"] { - saved["memory"] = memoryTestStatus - } - if userSetFlags["disk"] { - saved["disk"] = diskTestStatus - } - if userSetFlags["comm"] { - saved["comm"] = commTestStatus - } - if userSetFlags["ut"] { - saved["ut"] = utTestStatus - } - if userSetFlags["security"] { - saved["security"] = securityTestStatus - } - if userSetFlags["email"] { - saved["email"] = emailTestStatus - } - if userSetFlags["backtrace"] { - saved["backtrace"] = backtraceStatus - } - if userSetFlags["nt3"] { - saved["nt3"] = nt3Status - } - if userSetFlags["speed"] { - saved["speed"] = speedTestStatus - } - if userSetFlags["ping"] { - saved["ping"] = pingTestStatus - } - if userSetFlags["tgdc"] { - saved["tgdc"] = tgdcTestStatus - } - if userSetFlags["web"] { - saved["web"] = webTestStatus - } - if userSetFlags["cpum"] { - saved["cpum"] = cpuTestMethod - } - if userSetFlags["cput"] { - saved["cput"] = cpuTestThreadMode - } - if userSetFlags["memorym"] { - saved["memorym"] = memoryTestMethod - } - if userSetFlags["diskm"] { - saved["diskm"] = diskTestMethod - } - if userSetFlags["diskp"] { - saved["diskp"] = diskTestPath - } - if userSetFlags["diskmc"] { - saved["diskmc"] = diskMultiCheck - } - if userSetFlags["nt3loc"] { - saved["nt3loc"] = nt3Location - } - if userSetFlags["nt3t"] { - saved["nt3t"] = nt3CheckType - } - if userSetFlags["spnum"] { - saved["spnum"] = spNum - } - - return saved -} - -// restoreUserSetParams 恢复用户通过命令行显式设置的参数值,覆盖菜单的默认值 -func restoreUserSetParams(saved map[string]interface{}) { - if val, ok := saved["basic"]; ok { - basicStatus = val.(bool) - } - if val, ok := saved["cpu"]; ok { - cpuTestStatus = val.(bool) - } - if val, ok := saved["memory"]; ok { - memoryTestStatus = val.(bool) - } - if val, ok := saved["disk"]; ok { - diskTestStatus = val.(bool) - } - if val, ok := saved["comm"]; ok { - commTestStatus = val.(bool) - } - if val, ok := saved["ut"]; ok { - utTestStatus = val.(bool) - } - if val, ok := saved["security"]; ok { - securityTestStatus = val.(bool) - } - if val, ok := saved["email"]; ok { - emailTestStatus = val.(bool) - } - if val, ok := saved["backtrace"]; ok { - backtraceStatus = val.(bool) - } - if val, ok := saved["nt3"]; ok { - nt3Status = val.(bool) - } - if val, ok := saved["speed"]; ok { - speedTestStatus = val.(bool) - } - if val, ok := saved["ping"]; ok { - pingTestStatus = val.(bool) - } - if val, ok := saved["tgdc"]; ok { - tgdcTestStatus = val.(bool) - } - if val, ok := saved["web"]; ok { - webTestStatus = val.(bool) - } - if val, ok := saved["cpum"]; ok { - cpuTestMethod = val.(string) - } - if val, ok := saved["cput"]; ok { - cpuTestThreadMode = val.(string) - } - if val, ok := saved["memorym"]; ok { - memoryTestMethod = val.(string) - } - if val, ok := saved["diskm"]; ok { - diskTestMethod = val.(string) - } - if val, ok := saved["diskp"]; ok { - diskTestPath = val.(string) - } - if val, ok := saved["diskmc"]; ok { - diskMultiCheck = val.(bool) - } - if val, ok := saved["nt3loc"]; ok { - // 如果用户没有在菜单中选择选项10,才恢复用户设置的nt3Location - // 选项10会强制设置 nt3Location = "ALL" - if choice != "10" { - nt3Location = val.(string) - } - } - if val, ok := saved["nt3t"]; ok { - nt3CheckType = val.(string) - } - if val, ok := saved["spnum"]; ok { - spNum = val.(int) - } - - // 验证参数的有效性 - validateParams() -} - -// validateParams 验证参数的有效性,如果无效则使用默认值 -func validateParams() { - // 验证 cpuTestMethod - validCpuMethods := map[string]bool{"sysbench": true, "geekbench": true, "winsat": true} - if !validCpuMethods[cpuTestMethod] { - if language == "zh" { - fmt.Printf("警告: CPU测试方法 '%s' 无效,使用默认值 'sysbench'\n", cpuTestMethod) - } else { - fmt.Printf("Warning: Invalid CPU test method '%s', using default 'sysbench'\n", cpuTestMethod) - } - cpuTestMethod = "sysbench" - } - - // 验证 cpuTestThreadMode - validThreadModes := map[string]bool{"single": true, "multi": true} - if !validThreadModes[cpuTestThreadMode] { - if language == "zh" { - fmt.Printf("警告: CPU线程模式 '%s' 无效,使用默认值 'multi'\n", cpuTestThreadMode) - } else { - fmt.Printf("Warning: Invalid CPU thread mode '%s', using default 'multi'\n", cpuTestThreadMode) - } - cpuTestThreadMode = "multi" - } - - // 验证 memoryTestMethod - validMemoryMethods := map[string]bool{"stream": true, "sysbench": true, "dd": true, "winsat": true, "auto": true} - if !validMemoryMethods[memoryTestMethod] { - if language == "zh" { - fmt.Printf("警告: 内存测试方法 '%s' 无效,使用默认值 'stream'\n", memoryTestMethod) - } else { - fmt.Printf("Warning: Invalid memory test method '%s', using default 'stream'\n", memoryTestMethod) - } - memoryTestMethod = "stream" - } - - // 验证 diskTestMethod - validDiskMethods := map[string]bool{"fio": true, "dd": true, "winsat": true} - if !validDiskMethods[diskTestMethod] { - if language == "zh" { - fmt.Printf("警告: 磁盘测试方法 '%s' 无效,使用默认值 'fio'\n", diskTestMethod) - } else { - fmt.Printf("Warning: Invalid disk test method '%s', using default 'fio'\n", diskTestMethod) - } - diskTestMethod = "fio" - } - - // 验证 nt3Location - validNt3Locations := map[string]bool{"GZ": true, "SH": true, "BJ": true, "CD": true, "ALL": true} - if !validNt3Locations[nt3Location] { - if language == "zh" { - fmt.Printf("警告: NT3测试位置 '%s' 无效,使用默认值 'GZ'\n", nt3Location) - } else { - fmt.Printf("Warning: Invalid NT3 location '%s', using default 'GZ'\n", nt3Location) - } - nt3Location = "GZ" - } - - // 验证 nt3CheckType - validNt3Types := map[string]bool{"both": true, "ipv4": true, "ipv6": true} - if !validNt3Types[nt3CheckType] { - if language == "zh" { - fmt.Printf("警告: NT3测试类型 '%s' 无效,使用默认值 'ipv4'\n", nt3CheckType) - } else { - fmt.Printf("Warning: Invalid NT3 check type '%s', using default 'ipv4'\n", nt3CheckType) - } - nt3CheckType = "ipv4" - } - - // 验证 spNum (应该是正数) - if spNum < 0 { - if language == "zh" { - fmt.Printf("警告: 测速节点数量 '%d' 无效,使用默认值 2\n", spNum) - } else { - fmt.Printf("Warning: Invalid speed test node count '%d', using default 2\n", spNum) - } - spNum = 2 - } - - // 验证 language - validLanguages := map[string]bool{"zh": true, "en": true} - if !validLanguages[language] { - fmt.Printf("Warning: Invalid language '%s', using default 'zh'\n", language) - language = "zh" - } -} - -func handleMenuMode(preCheck utils.NetCheckResult) { - // 保存用户显式设置的参数值 - savedParams := saveUserSetParams() - - basicStatus, cpuTestStatus, memoryTestStatus, diskTestStatus = false, false, false, false - commTestStatus, utTestStatus, securityTestStatus, emailTestStatus = false, false, false, false - backtraceStatus, nt3Status, speedTestStatus = false, false, false - tgdcTestStatus, webTestStatus = false, false - autoChangeDiskTestMethod = true - printMenuOptions(preCheck) -Loop: - for { - choice = getMenuChoice(language) - switch choice { - case "0": - os.Exit(0) - case "1": - setFullTestStatus(preCheck) - onlyChinaTest = utils.CheckChina(enableLogger) - break Loop - case "2": - setMinimalTestStatus(preCheck) - break Loop - case "3": - setStandardTestStatus(preCheck) - break Loop - case "4": - setNetworkFocusedTestStatus(preCheck) - break Loop - case "5": - setUnlockFocusedTestStatus(preCheck) - break Loop - case "6": - if !preCheck.Connected { - fmt.Println("Can not test without network connection!") - return - } - setNetworkOnlyTestStatus() - break Loop - case "7": - if !preCheck.Connected { - fmt.Println("Can not test without network connection!") - return - } - setUnlockOnlyTestStatus() - break Loop - case "8": - setHardwareOnlyTestStatus(preCheck) - break Loop - case "9": - if !preCheck.Connected { - fmt.Println("Can not test without network connection!") - return - } - setIPQualityTestStatus() - break Loop - case "10": - if !preCheck.Connected { - fmt.Println("Can not test without network connection!") - return - } - nt3Location = "ALL" - setRouteTestStatus() - break Loop - default: - printInvalidChoice() - } - } - - // 恢复用户显式设置的参数,覆盖菜单的默认值 - restoreUserSetParams(savedParams) -} - -func printMenuOptions(preCheck utils.NetCheckResult) { - var stats *utils.StatsResponse - var statsErr error - var githubInfo *utils.GitHubRelease - var githubErr error - // 只有在网络连接正常时才获取统计信息和版本信息 - if preCheck.Connected { - var pwg sync.WaitGroup - pwg.Add(2) - go func() { - defer pwg.Done() - stats, statsErr = utils.GetGoescStats() - }() - go func() { - defer pwg.Done() - githubInfo, githubErr = utils.GetLatestEcsRelease() - }() - pwg.Wait() - } else { - statsErr = fmt.Errorf("network not connected") - githubErr = fmt.Errorf("network not connected") - } - var statsInfo string - var cmp int - if preCheck.Connected { - // 网络连接正常时处理统计信息和版本比较 - if statsErr != nil { - statsInfo = "NULL" - } else { - switch language { - case "zh": - statsInfo = fmt.Sprintf("总使用量: %s | 今日使用: %s", - utils.FormatGoecsNumber(stats.Total), - utils.FormatGoecsNumber(stats.Daily)) - case "en": - statsInfo = fmt.Sprintf("Total Usage: %s | Daily Usage: %s", - utils.FormatGoecsNumber(stats.Total), - utils.FormatGoecsNumber(stats.Daily)) - } - } - if githubErr == nil { - cmp = utils.CompareVersions(ecsVersion, githubInfo.TagName) - } else { - cmp = 0 - } - } - switch language { - case "zh": - fmt.Printf("VPS融合怪版本: %s\n", ecsVersion) - if preCheck.Connected { - switch cmp { - case -1: - fmt.Printf("检测到新版本 %s 如有必要请更新!\n", githubInfo.TagName) - } - 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("8. 硬件单项(系统信息+CPU+dd磁盘测试+fio磁盘测试)") - fmt.Println("9. IP质量检测(15个数据库的IP质量检测+邮件端口检测)") - fmt.Println("10. 三网回程线路检测+三网回程详细路由(北京上海广州成都)+全国延迟+TGDC+网站延迟") - fmt.Println("0. 退出程序") - case "en": - fmt.Printf("VPS Fusion Monster Test Version: %s\n", ecsVersion) - if preCheck.Connected { - switch cmp { - case -1: - fmt.Printf("New version detected %s update if necessary!\n", githubInfo.TagName) - } - 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 + Basic Unlock Tests + 5 Speed Test Nodes)") - fmt.Println("4. Network-Focused Test Suite (System Info + CPU + Memory + Disk + 5 Speed Test Nodes)") - fmt.Println("5. Unlock-Focused Test Suite (System Info + CPU + Memory + Disk IO + Basic Unlock Tests + Common Streaming Services + 5 Speed Test Nodes)") - fmt.Println("6. Network-Only Test (IP Quality Test + TGDC + Websites + 11 Speed Test Nodes)") - fmt.Println("7. Unlock-Only Test (Basic Unlock Tests + Common Streaming Services 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") - } -} - -func setFullTestStatus(preCheck utils.NetCheckResult) { - basicStatus = true - cpuTestStatus = true - memoryTestStatus = true - diskTestStatus = true - if preCheck.Connected { - commTestStatus = true - utTestStatus = true - securityTestStatus = true - emailTestStatus = true - backtraceStatus = true - nt3Status = true - speedTestStatus = true - tgdcTestStatus = true - webTestStatus = true - } -} - -func setMinimalTestStatus(preCheck utils.NetCheckResult) { - basicStatus = true - cpuTestStatus = true - memoryTestStatus = true - diskTestStatus = true - if preCheck.Connected { - speedTestStatus = true - } -} - -func setStandardTestStatus(preCheck utils.NetCheckResult) { - basicStatus = true - cpuTestStatus = true - memoryTestStatus = true - diskTestStatus = true - if preCheck.Connected { - utTestStatus = true - nt3Status = true - speedTestStatus = true - } -} - -func setNetworkFocusedTestStatus(preCheck utils.NetCheckResult) { - basicStatus = true - cpuTestStatus = true - memoryTestStatus = true - diskTestStatus = true - if preCheck.Connected { - backtraceStatus = true - nt3Status = true - speedTestStatus = true - } -} - -func setUnlockFocusedTestStatus(preCheck utils.NetCheckResult) { - basicStatus = true - cpuTestStatus = true - memoryTestStatus = true - diskTestStatus = true - if preCheck.Connected { - commTestStatus = true - utTestStatus = true - speedTestStatus = true - } -} - -func setNetworkOnlyTestStatus() { - onlyIpInfoCheckStatus = true - securityTestStatus = true - speedTestStatus = true - backtraceStatus = true - nt3Status = true - pingTestStatus = true - tgdcTestStatus = true - webTestStatus = true -} - -func setUnlockOnlyTestStatus() { - onlyIpInfoCheckStatus = true - commTestStatus = true - utTestStatus = true -} - -func setHardwareOnlyTestStatus(preCheck utils.NetCheckResult) { - _ = preCheck - basicStatus = true - cpuTestStatus = true - memoryTestStatus = true - diskTestStatus = true - securityTestStatus = false - autoChangeDiskTestMethod = false -} - -func setIPQualityTestStatus() { - onlyIpInfoCheckStatus = true - securityTestStatus = true - emailTestStatus = true -} - -func setRouteTestStatus() { - onlyIpInfoCheckStatus = true - backtraceStatus = true - nt3Status = true - pingTestStatus = true - tgdcTestStatus = true - webTestStatus = true -} - -func printInvalidChoice() { - if language == "zh" { - fmt.Println("无效的选项") - } else { - fmt.Println("Invalid choice") - } -} - func handleLanguageSpecificSettings() { - if language == "en" { - backtraceStatus = false - nt3Status = false + if configs.Language == "en" { + configs.BacktraceStatus = false + configs.Nt3Status = false } - if !enabelUpload { - securityTestStatus = false - } -} - -func handleSignalInterrupt(sig chan os.Signal, startTime *time.Time, output *string, _ string, uploadDone chan bool, outputMutex *sync.Mutex) { - select { - case <-sig: - if !finish { - endTime := time.Now() - duration := endTime.Sub(*startTime) - minutes := int(duration.Minutes()) - seconds := int(duration.Seconds()) % 60 - currentTime := time.Now().Format("Mon Jan 2 15:04:05 MST 2006") - outputMutex.Lock() - timeInfo := utils.PrintAndCapture(func() { - utils.PrintCenteredTitle("", width) - if language == "zh" { - fmt.Printf("花费 : %d 分 %d 秒\n", minutes, seconds) - fmt.Printf("时间 : %s\n", currentTime) - } else { - fmt.Printf("Cost Time : %d min %d sec\n", minutes, seconds) - fmt.Printf("Current Time : %s\n", currentTime) - } - utils.PrintCenteredTitle("", width) - }, "", "") - *output += timeInfo - finalOutput := *output - outputMutex.Unlock() - resultChan := make(chan struct { - httpURL string - httpsURL string - }, 1) - if enabelUpload { - go func() { - httpURL, httpsURL := utils.ProcessAndUpload(finalOutput, filePath, enabelUpload) - resultChan <- struct { - httpURL string - httpsURL string - }{httpURL, httpsURL} - uploadDone <- true - }() - select { - case result := <-resultChan: - if result.httpURL != "" || result.httpsURL != "" { - if language == "en" { - fmt.Printf("Upload successfully!\nHttp URL: %s\nHttps URL: %s\n", result.httpURL, result.httpsURL) - } else { - fmt.Printf("上传成功!\nHttp URL: %s\nHttps URL: %s\n", result.httpURL, result.httpsURL) - } - } - time.Sleep(100 * time.Millisecond) - if runtime.GOOS == "windows" || runtime.GOOS == "darwin" { - fmt.Println("Press Enter to exit...") - fmt.Scanln() - } - os.Exit(0) - case <-time.After(30 * time.Second): - if language == "en" { - fmt.Println("Upload timeout, program exit") - } else { - fmt.Println("上传超时,程序退出") - } - if runtime.GOOS == "windows" || runtime.GOOS == "darwin" { - fmt.Println("Press Enter to exit...") - fmt.Scanln() - } - os.Exit(1) - } - } else { - if runtime.GOOS == "windows" || runtime.GOOS == "darwin" { - fmt.Println("Press Enter to exit...") - fmt.Scanln() - } - os.Exit(0) - } - } - os.Exit(0) - } -} - -func runChineseTests(preCheck utils.NetCheckResult, wg1, wg2, wg3 *sync.WaitGroup, basicInfo, securityInfo, emailInfo, mediaInfo, ptInfo *string, output *string, tempOutput string, startTime time.Time, outputMutex *sync.Mutex) { - *output = runBasicTests(preCheck, basicInfo, securityInfo, *output, tempOutput, outputMutex) - *output = runCPUTest(*output, tempOutput, outputMutex) - *output = runMemoryTest(*output, tempOutput, outputMutex) - *output = runDiskTest(*output, tempOutput, outputMutex) - if onlyIpInfoCheckStatus && !basicStatus && preCheck.Connected && preCheck.StackType != "" && preCheck.StackType != "None" { - *output = runIpInfoCheck(*output, tempOutput, outputMutex) - } - if utTestStatus && preCheck.Connected && preCheck.StackType != "" && preCheck.StackType != "None" && !onlyChinaTest { - wg1.Add(1) - go func() { - defer wg1.Done() - *mediaInfo = unlocktest.MediaTest(language) - }() - } - if emailTestStatus && preCheck.Connected && preCheck.StackType != "" && preCheck.StackType != "None" { - wg2.Add(1) - go func() { - defer wg2.Done() - *emailInfo = email.EmailCheck() - }() - } - if (onlyChinaTest || pingTestStatus) && preCheck.Connected && preCheck.StackType != "" && preCheck.StackType != "None" { - wg3.Add(1) - go func() { - defer wg3.Done() - *ptInfo = pt.PingTest() - }() - } - if preCheck.Connected && preCheck.StackType != "" && preCheck.StackType != "None" { - *output = runStreamingTests(wg1, mediaInfo, *output, tempOutput, outputMutex) - *output = runSecurityTests(*securityInfo, *output, tempOutput, outputMutex) - *output = runEmailTests(wg2, emailInfo, *output, tempOutput, outputMutex) - } - if runtime.GOOS != "windows" && preCheck.Connected && preCheck.StackType != "" && preCheck.StackType != "None" { - *output = runNetworkTests(wg3, ptInfo, *output, tempOutput, outputMutex) - } - if preCheck.Connected && preCheck.StackType != "" && preCheck.StackType != "None" { - *output = runSpeedTests(*output, tempOutput, outputMutex) - } - *output = appendTimeInfo(*output, tempOutput, startTime, outputMutex) -} - -func runEnglishTests(preCheck utils.NetCheckResult, wg1, wg2, wg3 *sync.WaitGroup, basicInfo, securityInfo, emailInfo, mediaInfo, ptInfo *string, output *string, tempOutput string, startTime time.Time, outputMutex *sync.Mutex) { - *output = runBasicTests(preCheck, basicInfo, securityInfo, *output, tempOutput, outputMutex) - *output = runCPUTest(*output, tempOutput, outputMutex) - *output = runMemoryTest(*output, tempOutput, outputMutex) - *output = runDiskTest(*output, tempOutput, outputMutex) - if onlyIpInfoCheckStatus && !basicStatus && preCheck.Connected && preCheck.StackType != "" && preCheck.StackType != "None" { - *output = runIpInfoCheck(*output, tempOutput, outputMutex) - } - if preCheck.Connected && preCheck.StackType != "" && preCheck.StackType != "None" { - if utTestStatus { - wg1.Add(1) - go func() { - defer wg1.Done() - *mediaInfo = unlocktest.MediaTest(language) - }() - } - if emailTestStatus { - wg2.Add(1) - go func() { - defer wg2.Done() - *emailInfo = email.EmailCheck() - }() - } - // 英文模式不进行三网PING测试,所以不启动 pt.PingTest() - *output = runStreamingTests(wg1, mediaInfo, *output, tempOutput, outputMutex) - *output = runSecurityTests(*securityInfo, *output, tempOutput, outputMutex) - *output = runEmailTests(wg2, emailInfo, *output, tempOutput, outputMutex) - *output = runEnglishNetworkTests(wg3, ptInfo, *output, tempOutput, outputMutex) - *output = runEnglishSpeedTests(*output, tempOutput, outputMutex) - } - *output = appendTimeInfo(*output, tempOutput, startTime, outputMutex) -} - -// runIpInfoCheck 系统和网络基础信息检测不进行测试的时候,该函数检测取得本机IP信息并显示(单项测试中输出) -func runIpInfoCheck(output, tempOutput string, outputMutex *sync.Mutex) string { - outputMutex.Lock() - defer outputMutex.Unlock() - return utils.PrintAndCapture(func() { - var ipinfo string - upstreams.IPV4, upstreams.IPV6, ipinfo = utils.OnlyBasicsIpInfo(language) - if ipinfo != "" { - if language == "zh" { - utils.PrintCenteredTitle("IP信息", width) - } else { - utils.PrintCenteredTitle("IP-Information", width) - } - fmt.Printf("%s", ipinfo) - } - }, tempOutput, output) -} - -func runBasicTests(preCheck utils.NetCheckResult, basicInfo, securityInfo *string, output, tempOutput string, outputMutex *sync.Mutex) string { - outputMutex.Lock() - defer outputMutex.Unlock() - return utils.PrintAndCapture(func() { - utils.PrintHead(language, width, ecsVersion) - if basicStatus || securityTestStatus { - if basicStatus { - if language == "zh" { - utils.PrintCenteredTitle("系统基础信息", width) - } else { - utils.PrintCenteredTitle("System-Basic-Information", width) - } - } - if preCheck.Connected && preCheck.StackType == "DualStack" { - upstreams.IPV4, upstreams.IPV6, *basicInfo, *securityInfo, nt3CheckType = utils.BasicsAndSecurityCheck(language, nt3CheckType, securityTestStatus) - } else if preCheck.Connected && preCheck.StackType == "IPv4" { - upstreams.IPV4, upstreams.IPV6, *basicInfo, *securityInfo, nt3CheckType = utils.BasicsAndSecurityCheck(language, "ipv4", securityTestStatus) - } else if preCheck.Connected && preCheck.StackType == "IPv6" { - upstreams.IPV4, upstreams.IPV6, *basicInfo, *securityInfo, nt3CheckType = utils.BasicsAndSecurityCheck(language, "ipv6", securityTestStatus) - } else { - upstreams.IPV4, upstreams.IPV6, *basicInfo, *securityInfo, nt3CheckType = utils.BasicsAndSecurityCheck(language, "", false) - securityTestStatus = false - } - if basicStatus { - fmt.Printf("%s", *basicInfo) - } else if (input == "6" || input == "9") && securityTestStatus { - scanner := bufio.NewScanner(strings.NewReader(*basicInfo)) - for scanner.Scan() { - line := scanner.Text() - if strings.Contains(line, "IPV") { - fmt.Println(line) - } - } - } - } - }, tempOutput, output) -} - -func runCPUTest(output, tempOutput string, outputMutex *sync.Mutex) string { - outputMutex.Lock() - defer outputMutex.Unlock() - return utils.PrintAndCapture(func() { - if cpuTestStatus { - realTestMethod, res := cputest.CpuTest(language, cpuTestMethod, cpuTestThreadMode) - if language == "zh" { - utils.PrintCenteredTitle(fmt.Sprintf("CPU测试-通过%s测试", realTestMethod), width) - } else { - utils.PrintCenteredTitle(fmt.Sprintf("CPU-Test--%s-Method", realTestMethod), width) - } - fmt.Print(res) - } - }, tempOutput, output) -} - -func runMemoryTest(output, tempOutput string, outputMutex *sync.Mutex) string { - outputMutex.Lock() - defer outputMutex.Unlock() - return utils.PrintAndCapture(func() { - if memoryTestStatus { - realTestMethod, res := memorytest.MemoryTest(language, memoryTestMethod) - if language == "zh" { - utils.PrintCenteredTitle(fmt.Sprintf("内存测试-通过%s测试", realTestMethod), width) - } else { - utils.PrintCenteredTitle(fmt.Sprintf("Memory-Test--%s-Method", realTestMethod), width) - } - fmt.Print(res) - } - }, tempOutput, output) -} - -func runDiskTest(output, tempOutput string, outputMutex *sync.Mutex) string { - outputMutex.Lock() - defer outputMutex.Unlock() - return utils.PrintAndCapture(func() { - if diskTestStatus && autoChangeDiskTestMethod { - realTestMethod, res := disktest.DiskTest(language, diskTestMethod, diskTestPath, diskMultiCheck, autoChangeDiskTestMethod) - if language == "zh" { - utils.PrintCenteredTitle(fmt.Sprintf("硬盘测试-通过%s测试", realTestMethod), width) - } else { - utils.PrintCenteredTitle(fmt.Sprintf("Disk-Test--%s-Method", realTestMethod), width) - } - fmt.Print(res) - } else if diskTestStatus && !autoChangeDiskTestMethod { - if language == "zh" { - utils.PrintCenteredTitle(fmt.Sprintf("硬盘测试-通过%s测试", "dd"), width) - _, res := disktest.DiskTest(language, "dd", diskTestPath, diskMultiCheck, autoChangeDiskTestMethod) - fmt.Print(res) - utils.PrintCenteredTitle(fmt.Sprintf("硬盘测试-通过%s测试", "fio"), width) - _, res = disktest.DiskTest(language, "fio", diskTestPath, diskMultiCheck, autoChangeDiskTestMethod) - fmt.Print(res) - } else { - utils.PrintCenteredTitle(fmt.Sprintf("Disk-Test--%s-Method", "dd"), width) - _, res := disktest.DiskTest(language, "dd", diskTestPath, diskMultiCheck, autoChangeDiskTestMethod) - fmt.Print(res) - utils.PrintCenteredTitle(fmt.Sprintf("Disk-Test--%s-Method", "fio"), width) - _, res = disktest.DiskTest(language, "fio", diskTestPath, diskMultiCheck, autoChangeDiskTestMethod) - fmt.Print(res) - } - } - }, tempOutput, output) -} - -func runStreamingTests(wg1 *sync.WaitGroup, mediaInfo *string, output, tempOutput string, outputMutex *sync.Mutex) string { - outputMutex.Lock() - defer outputMutex.Unlock() - return utils.PrintAndCapture(func() { - if language == "zh" { - if commTestStatus && !onlyChinaTest { - utils.PrintCenteredTitle("御三家流媒体解锁", width) - fmt.Printf("%s", commediatests.MediaTests(language)) - } - } - if utTestStatus && (language == "zh" && !onlyChinaTest || language == "en") { - wg1.Wait() - if language == "zh" { - utils.PrintCenteredTitle("跨国流媒体解锁", width) - } else { - utils.PrintCenteredTitle("Cross-Border-Streaming-Media-Unlock", width) - } - fmt.Printf("%s", *mediaInfo) - } - }, tempOutput, output) -} - -func runSecurityTests(securityInfo, output, tempOutput string, outputMutex *sync.Mutex) string { - outputMutex.Lock() - defer outputMutex.Unlock() - return utils.PrintAndCapture(func() { - if securityTestStatus { - if language == "zh" { - utils.PrintCenteredTitle("IP质量检测", width) - } else { - utils.PrintCenteredTitle("IP-Quality-Check", width) - } - fmt.Printf("%s", securityInfo) - } - }, tempOutput, output) -} - -func runEmailTests(wg2 *sync.WaitGroup, emailInfo *string, output, tempOutput string, outputMutex *sync.Mutex) string { - outputMutex.Lock() - defer outputMutex.Unlock() - return utils.PrintAndCapture(func() { - if emailTestStatus { - wg2.Wait() - if language == "zh" { - utils.PrintCenteredTitle("邮件端口检测", width) - } else { - utils.PrintCenteredTitle("Email-Port-Check", width) - } - fmt.Println(*emailInfo) - } - }, tempOutput, output) -} - -func runNetworkTests(wg3 *sync.WaitGroup, ptInfo *string, output, tempOutput string, outputMutex *sync.Mutex) string { - outputMutex.Lock() - defer outputMutex.Unlock() - return utils.PrintAndCapture(func() { - if backtraceStatus && !onlyChinaTest { - utils.PrintCenteredTitle("上游及回程线路检测", width) - upstreams.UpstreamsCheck() // 不能在重定向的同时外部并发,此处仅可以顺序执行 - } - if nt3Status && !onlyChinaTest { - utils.PrintCenteredTitle("三网回程路由检测", width) - nexttrace.NextTrace3Check(language, nt3Location, nt3CheckType) // 不能在重定向的同时外部并发,此处仅可以顺序执行 - } - // 中国模式:显示三网 PING 测试 - if onlyChinaTest && *ptInfo != "" { - wg3.Wait() - utils.PrintCenteredTitle("PING值检测", width) - fmt.Println(*ptInfo) - } - // 选项 6/10:显示三网 PING + TGDC + 网站 - if pingTestStatus && *ptInfo != "" { - wg3.Wait() - utils.PrintCenteredTitle("PING值检测", width) - fmt.Println(*ptInfo) - if tgdcTestStatus { - fmt.Println(pt.TelegramDCTest()) - } - if webTestStatus { - fmt.Println(pt.WebsiteTest()) - } - } - // 非中国模式且非 pingTestStatus:只显示 TGDC + 网站(选项 1 的情况) - if !onlyChinaTest && !pingTestStatus && (tgdcTestStatus || webTestStatus) { - utils.PrintCenteredTitle("PING值检测", width) - if tgdcTestStatus { - fmt.Println(pt.TelegramDCTest()) - } - if webTestStatus { - fmt.Println(pt.WebsiteTest()) - } - } - }, tempOutput, output) -} - -func runSpeedTests(output, tempOutput string, outputMutex *sync.Mutex) string { - outputMutex.Lock() - defer outputMutex.Unlock() - return utils.PrintAndCapture(func() { - if speedTestStatus { - utils.PrintCenteredTitle("就近节点测速", width) - speedtest.ShowHead(language) - if choice == "1" || !menuMode { - speedtest.NearbySP() - speedtest.CustomSP("net", "global", 2, language) - speedtest.CustomSP("net", "cu", spNum, language) - speedtest.CustomSP("net", "ct", spNum, language) - speedtest.CustomSP("net", "cmcc", spNum, language) - } else if choice == "2" || choice == "3" || choice == "4" || choice == "5" { - speedtest.CustomSP("net", "global", 4, language) - } else if choice == "6" { - speedtest.CustomSP("net", "global", 11, language) - } - } - }, tempOutput, output) -} - -func runEnglishNetworkTests(wg3 *sync.WaitGroup, ptInfo *string, output, tempOutput string, outputMutex *sync.Mutex) string { - outputMutex.Lock() - defer outputMutex.Unlock() - return utils.PrintAndCapture(func() { - // 英文模式只测试 TGDC 和主流网站,不测试三网PING - if tgdcTestStatus || webTestStatus { - utils.PrintCenteredTitle("PING-Test", width) - if tgdcTestStatus { - fmt.Println(pt.TelegramDCTest()) - } - if webTestStatus { - fmt.Println(pt.WebsiteTest()) - } - } - }, tempOutput, output) -} - -func runEnglishSpeedTests(output, tempOutput string, outputMutex *sync.Mutex) string { - outputMutex.Lock() - defer outputMutex.Unlock() - return utils.PrintAndCapture(func() { - if speedTestStatus { - utils.PrintCenteredTitle("Speed-Test", width) - speedtest.ShowHead(language) - speedtest.NearbySP() - speedtest.CustomSP("net", "global", -1, language) - } - }, tempOutput, output) -} - -func appendTimeInfo(output, tempOutput string, startTime time.Time, outputMutex *sync.Mutex) string { - outputMutex.Lock() - defer outputMutex.Unlock() - endTime := time.Now() - duration := endTime.Sub(startTime) - minutes := int(duration.Minutes()) - seconds := int(duration.Seconds()) % 60 - currentTime := time.Now().Format("Mon Jan 2 15:04:05 MST 2006") - return utils.PrintAndCapture(func() { - utils.PrintCenteredTitle("", width) - if language == "zh" { - fmt.Printf("花费 : %d 分 %d 秒\n", minutes, seconds) - fmt.Printf("时间 : %s\n", currentTime) - } else { - fmt.Printf("Cost Time : %d min %d sec\n", minutes, seconds) - fmt.Printf("Current Time : %s\n", currentTime) - } - utils.PrintCenteredTitle("", width) - }, tempOutput, output) -} - -func handleUploadResults(output string) { - httpURL, httpsURL := utils.ProcessAndUpload(output, filePath, enabelUpload) - if httpURL != "" || httpsURL != "" { - if language == "en" { - fmt.Printf("Upload successfully!\nHttp URL: %s\nHttps URL: %s\n", httpURL, httpsURL) - fmt.Println("Each Test Benchmark: https://bash.spiritlhl.net/ecsguide") - } else { - fmt.Printf("上传成功!\nHttp URL: %s\nHttps URL: %s\n", httpURL, httpsURL) - fmt.Println("每项测试基准见: https://bash.spiritlhl.net/ecsguide") - } + if !configs.EnableUpload { + configs.SecurityTestStatus = false } } func main() { - parseFlags() - if handleHelpAndVersion() { + configs.ParseFlags(os.Args[1:]) + if configs.HandleHelpAndVersion("goecs") { return } initLogger() @@ -1186,14 +71,14 @@ func main() { http.Get("https://hits.spiritlhl.net/goecs.svg?action=hit&title=Hits&title_bg=%23555555&count_bg=%230eecf8&edge_flat=false") } }() - if menuMode { - handleMenuMode(preCheck) + if configs.MenuMode { + menu.HandleMenuMode(preCheck, configs) } else { - onlyIpInfoCheckStatus = true + configs.OnlyIpInfoCheck = true } handleLanguageSpecificSettings() if !preCheck.Connected { - enabelUpload = false + configs.EnableUpload = false } var ( wg1, wg2, wg3 sync.WaitGroup @@ -1205,19 +90,19 @@ func main() { uploadDone := make(chan bool, 1) sig := make(chan os.Signal, 1) signal.Notify(sig, os.Interrupt, syscall.SIGINT, syscall.SIGTERM) - go handleSignalInterrupt(sig, &startTime, &output, tempOutput, uploadDone, &outputMutex) - switch language { + go runner.HandleSignalInterrupt(sig, configs, &startTime, &output, tempOutput, uploadDone, &outputMutex) + switch configs.Language { case "zh": - runChineseTests(preCheck, &wg1, &wg2, &wg3, &basicInfo, &securityInfo, &emailInfo, &mediaInfo, &ptInfo, &output, tempOutput, startTime, &outputMutex) + runner.RunChineseTests(preCheck, configs, &wg1, &wg2, &wg3, &basicInfo, &securityInfo, &emailInfo, &mediaInfo, &ptInfo, &output, tempOutput, startTime, &outputMutex) case "en": - runEnglishTests(preCheck, &wg1, &wg2, &wg3, &basicInfo, &securityInfo, &emailInfo, &mediaInfo, &ptInfo, &output, tempOutput, startTime, &outputMutex) + runner.RunEnglishTests(preCheck, configs, &wg1, &wg2, &wg3, &basicInfo, &securityInfo, &emailInfo, &mediaInfo, &ptInfo, &output, tempOutput, startTime, &outputMutex) default: fmt.Println("Unsupported language") } if preCheck.Connected { - handleUploadResults(output) + runner.HandleUploadResults(configs, output) } - finish = true + configs.Finish = true if runtime.GOOS == "windows" || runtime.GOOS == "darwin" { fmt.Println("Press Enter to exit...") fmt.Scanln() diff --git a/internal/menu/menu.go b/internal/menu/menu.go new file mode 100644 index 0000000..72db38d --- /dev/null +++ b/internal/menu/menu.go @@ -0,0 +1,365 @@ +package menu + +import ( + "context" + "fmt" + "os" + "os/signal" + "regexp" + "strings" + "sync" + "syscall" + + "github.com/oneclickvirt/ecs/internal/params" + "github.com/oneclickvirt/ecs/utils" +) + +// GetMenuChoice prompts user for menu choice +func GetMenuChoice(language string) string { + ctx, cancel := context.WithCancel(context.Background()) + defer cancel() + sigChan := make(chan os.Signal, 1) + signal.Notify(sigChan, os.Interrupt, syscall.SIGINT, syscall.SIGTERM) + defer signal.Stop(sigChan) + inputChan := make(chan string, 1) + go func() { + select { + case <-sigChan: + fmt.Println("\n程序在选择过程中被用户中断") + os.Exit(0) + case <-ctx.Done(): + return + } + }() + for { + go func() { + var input string + fmt.Print("请输入选项 / Please enter your choice: ") + fmt.Scanln(&input) + input = strings.TrimSpace(input) + input = strings.TrimRight(input, "\n") + select { + case inputChan <- input: + case <-ctx.Done(): + return + } + }() + select { + case input := <-inputChan: + re := regexp.MustCompile(`^\d+$`) + if re.MatchString(input) { + inChoice := input + switch inChoice { + case "0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "10": + return inChoice + default: + if language == "zh" { + fmt.Println("无效的选项") + } else { + fmt.Println("Invalid choice") + } + } + } else { + if language == "zh" { + fmt.Println("输入错误,请输入一个纯数字") + } else { + fmt.Println("Invalid input, please enter a number") + } + } + case <-ctx.Done(): + return "" + } + } +} + +// PrintMenuOptions displays menu options +func PrintMenuOptions(preCheck utils.NetCheckResult, config *params.Config) { + var stats *utils.StatsResponse + var statsErr error + var githubInfo *utils.GitHubRelease + var githubErr error + if preCheck.Connected { + var pwg sync.WaitGroup + pwg.Add(2) + go func() { + defer pwg.Done() + stats, statsErr = utils.GetGoescStats() + }() + go func() { + defer pwg.Done() + githubInfo, githubErr = utils.GetLatestEcsRelease() + }() + pwg.Wait() + } else { + statsErr = fmt.Errorf("network not connected") + githubErr = fmt.Errorf("network not connected") + } + var statsInfo string + var cmp int + if preCheck.Connected { + if statsErr != nil { + statsInfo = "NULL" + } else { + switch config.Language { + case "zh": + statsInfo = fmt.Sprintf("总使用量: %s | 今日使用: %s", + utils.FormatGoecsNumber(stats.Total), + utils.FormatGoecsNumber(stats.Daily)) + case "en": + statsInfo = fmt.Sprintf("Total Usage: %s | Daily Usage: %s", + utils.FormatGoecsNumber(stats.Total), + utils.FormatGoecsNumber(stats.Daily)) + } + } + if githubErr == nil { + cmp = utils.CompareVersions(config.EcsVersion, githubInfo.TagName) + } else { + cmp = 0 + } + } + switch config.Language { + case "zh": + fmt.Printf("VPS融合怪版本: %s\n", config.EcsVersion) + if preCheck.Connected { + switch cmp { + case -1: + fmt.Printf("检测到新版本 %s 如有必要请更新!\n", githubInfo.TagName) + } + 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("8. 硬件单项(系统信息+CPU+dd磁盘测试+fio磁盘测试)") + fmt.Println("9. IP质量检测(15个数据库的IP质量检测+邮件端口检测)") + fmt.Println("10. 三网回程线路检测+三网回程详细路由(北京上海广州成都)+全国延迟+TGDC+网站延迟") + fmt.Println("0. 退出程序") + case "en": + fmt.Printf("VPS Fusion Monster Test Version: %s\n", config.EcsVersion) + if preCheck.Connected { + switch cmp { + case -1: + fmt.Printf("New version detected %s update if necessary!\n", githubInfo.TagName) + } + 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 + Basic Unlock Tests + 5 Speed Test Nodes)") + fmt.Println("4. Network-Focused Test Suite (System Info + CPU + Memory + Disk + 5 Speed Test Nodes)") + fmt.Println("5. Unlock-Focused Test Suite (System Info + CPU + Memory + Disk IO + Basic Unlock Tests + Common Streaming Services + 5 Speed Test Nodes)") + fmt.Println("6. Network-Only Test (IP Quality Test + TGDC + Websites + 11 Speed Test Nodes)") + fmt.Println("7. Unlock-Only Test (Basic Unlock Tests + Common Streaming Services 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 +func HandleMenuMode(preCheck utils.NetCheckResult, config *params.Config) { + savedParams := config.SaveUserSetParams() + config.BasicStatus = false + config.CpuTestStatus = false + config.MemoryTestStatus = false + config.DiskTestStatus = false + config.CommTestStatus = false + config.UtTestStatus = false + config.SecurityTestStatus = false + config.EmailTestStatus = false + config.BacktraceStatus = false + config.Nt3Status = false + config.SpeedTestStatus = false + config.TgdcTestStatus = false + config.WebTestStatus = false + config.AutoChangeDiskMethod = true + PrintMenuOptions(preCheck, config) +Loop: + for { + config.Choice = GetMenuChoice(config.Language) + switch config.Choice { + case "0": + os.Exit(0) + case "1": + SetFullTestStatus(preCheck, config) + config.OnlyChinaTest = utils.CheckChina(config.EnableLogger) + 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) + } + } + config.RestoreUserSetParams(savedParams) +} + +// SetFullTestStatus enables all tests +func SetFullTestStatus(preCheck utils.NetCheckResult, config *params.Config) { + config.BasicStatus = true + config.CpuTestStatus = true + config.MemoryTestStatus = true + config.DiskTestStatus = true + if preCheck.Connected { + config.CommTestStatus = true + config.UtTestStatus = true + config.SecurityTestStatus = true + config.EmailTestStatus = true + config.BacktraceStatus = true + config.Nt3Status = true + config.SpeedTestStatus = true + config.TgdcTestStatus = true + config.WebTestStatus = true + } +} + +// SetMinimalTestStatus sets minimal test configuration +func SetMinimalTestStatus(preCheck utils.NetCheckResult, config *params.Config) { + config.BasicStatus = true + config.CpuTestStatus = true + config.MemoryTestStatus = true + config.DiskTestStatus = true + if preCheck.Connected { + config.SpeedTestStatus = true + } +} + +// SetStandardTestStatus sets standard test configuration +func SetStandardTestStatus(preCheck utils.NetCheckResult, config *params.Config) { + config.BasicStatus = true + config.CpuTestStatus = true + config.MemoryTestStatus = true + config.DiskTestStatus = true + if preCheck.Connected { + config.UtTestStatus = true + config.Nt3Status = true + config.SpeedTestStatus = true + } +} + +// SetNetworkFocusedTestStatus sets network-focused test configuration +func SetNetworkFocusedTestStatus(preCheck utils.NetCheckResult, config *params.Config) { + config.BasicStatus = true + config.CpuTestStatus = true + config.MemoryTestStatus = true + config.DiskTestStatus = true + if preCheck.Connected { + config.BacktraceStatus = true + config.Nt3Status = true + config.SpeedTestStatus = true + } +} + +// SetUnlockFocusedTestStatus sets unlock-focused test configuration +func SetUnlockFocusedTestStatus(preCheck utils.NetCheckResult, config *params.Config) { + config.BasicStatus = true + config.CpuTestStatus = true + config.MemoryTestStatus = true + config.DiskTestStatus = true + if preCheck.Connected { + config.CommTestStatus = true + config.UtTestStatus = true + config.SpeedTestStatus = true + } +} + +// SetNetworkOnlyTestStatus sets network-only test configuration +func SetNetworkOnlyTestStatus(config *params.Config) { + config.OnlyIpInfoCheck = true + config.SecurityTestStatus = true + config.SpeedTestStatus = true + config.BacktraceStatus = true + config.Nt3Status = true + config.PingTestStatus = true + config.TgdcTestStatus = true + config.WebTestStatus = true +} + +// SetUnlockOnlyTestStatus sets unlock-only test configuration +func SetUnlockOnlyTestStatus(config *params.Config) { + config.OnlyIpInfoCheck = true + config.CommTestStatus = true + config.UtTestStatus = true +} + +// SetHardwareOnlyTestStatus sets hardware-only test configuration +func SetHardwareOnlyTestStatus(preCheck utils.NetCheckResult, config *params.Config) { + _ = preCheck + config.BasicStatus = true + config.CpuTestStatus = true + config.MemoryTestStatus = true + config.DiskTestStatus = true + config.SecurityTestStatus = false + config.AutoChangeDiskMethod = false +} + +// SetIPQualityTestStatus sets IP quality test configuration +func SetIPQualityTestStatus(config *params.Config) { + config.OnlyIpInfoCheck = true + config.SecurityTestStatus = true + config.EmailTestStatus = true +} + +// SetRouteTestStatus sets route test configuration +func SetRouteTestStatus(config *params.Config) { + config.OnlyIpInfoCheck = true + config.BacktraceStatus = true + config.Nt3Status = true + config.PingTestStatus = true + config.TgdcTestStatus = true + config.WebTestStatus = true +} + +// PrintInvalidChoice prints invalid choice message +func PrintInvalidChoice(language string) { + if language == "zh" { + fmt.Println("无效的选项") + } else { + fmt.Println("Invalid choice") + } +} diff --git a/internal/params/params.go b/internal/params/params.go new file mode 100644 index 0000000..363d34d --- /dev/null +++ b/internal/params/params.go @@ -0,0 +1,369 @@ +package params + +import ( + "flag" + "fmt" +) + +// Config holds all configuration parameters +type Config struct { + EcsVersion string + MenuMode bool + OnlyChinaTest bool + Input string + Choice string + ShowVersion bool + EnableLogger bool + Language string + CpuTestMethod string + CpuTestThreadMode string + MemoryTestMethod string + DiskTestMethod string + DiskTestPath string + DiskMultiCheck bool + Nt3CheckType string + Nt3Location string + SpNum int + Width int + BasicStatus bool + CpuTestStatus bool + MemoryTestStatus bool + DiskTestStatus bool + CommTestStatus bool + UtTestStatus bool + SecurityTestStatus bool + EmailTestStatus bool + BacktraceStatus bool + Nt3Status bool + SpeedTestStatus bool + PingTestStatus bool + TgdcTestStatus bool + WebTestStatus bool + AutoChangeDiskMethod bool + FilePath string + EnableUpload bool + OnlyIpInfoCheck bool + Help bool + Finish bool + UserSetFlags map[string]bool + GoecsFlag *flag.FlagSet +} + +// NewConfig creates a new Config with default values +func NewConfig(version string) *Config { + return &Config{ + EcsVersion: version, + MenuMode: true, + Language: "zh", + CpuTestMethod: "sysbench", + CpuTestThreadMode: "multi", + MemoryTestMethod: "stream", + DiskTestMethod: "fio", + SpNum: 2, + Width: 82, + BasicStatus: true, + CpuTestStatus: true, + MemoryTestStatus: true, + DiskTestStatus: true, + CommTestStatus: true, + UtTestStatus: true, + SecurityTestStatus: true, + EmailTestStatus: true, + BacktraceStatus: true, + Nt3Status: true, + SpeedTestStatus: true, + Nt3Location: "GZ", + Nt3CheckType: "ipv4", + AutoChangeDiskMethod: true, + FilePath: "goecs.txt", + EnableUpload: true, + UserSetFlags: make(map[string]bool), + GoecsFlag: flag.NewFlagSet("goecs", flag.ContinueOnError), + } +} + +// ParseFlags parses command line flags +func (c *Config) ParseFlags(args []string) { + 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") + c.GoecsFlag.BoolVar(&c.ShowVersion, "version", false, "Display version information") + c.GoecsFlag.BoolVar(&c.MenuMode, "menu", true, "Enable/Disable menu mode, disable example: -menu=false") + c.GoecsFlag.StringVar(&c.Language, "l", "zh", "Set language (supported: en, zh)") + c.GoecsFlag.BoolVar(&c.BasicStatus, "basic", true, "Enable/Disable basic test") + c.GoecsFlag.BoolVar(&c.CpuTestStatus, "cpu", true, "Enable/Disable CPU test") + c.GoecsFlag.BoolVar(&c.MemoryTestStatus, "memory", true, "Enable/Disable memory test") + c.GoecsFlag.BoolVar(&c.DiskTestStatus, "disk", true, "Enable/Disable disk test") + c.GoecsFlag.BoolVar(&c.CommTestStatus, "comm", true, "Enable/Disable common media test") + c.GoecsFlag.BoolVar(&c.UtTestStatus, "ut", true, "Enable/Disable unlock media test") + c.GoecsFlag.BoolVar(&c.SecurityTestStatus, "security", true, "Enable/Disable security test") + c.GoecsFlag.BoolVar(&c.EmailTestStatus, "email", true, "Enable/Disable email port test") + c.GoecsFlag.BoolVar(&c.BacktraceStatus, "backtrace", true, "Enable/Disable backtrace test (in 'en' language or on windows it always false)") + c.GoecsFlag.BoolVar(&c.Nt3Status, "nt3", true, "Enable/Disable NT3 test (in 'en' language or on windows it always false)") + c.GoecsFlag.BoolVar(&c.SpeedTestStatus, "speed", true, "Enable/Disable speed test") + c.GoecsFlag.BoolVar(&c.PingTestStatus, "ping", false, "Enable/Disable ping test") + c.GoecsFlag.BoolVar(&c.TgdcTestStatus, "tgdc", false, "Enable/Disable Telegram DC test") + c.GoecsFlag.BoolVar(&c.WebTestStatus, "web", false, "Enable/Disable popular websites test") + c.GoecsFlag.StringVar(&c.CpuTestMethod, "cpum", "sysbench", "Set CPU test method (supported: sysbench, geekbench, winsat)") + c.GoecsFlag.StringVar(&c.CpuTestThreadMode, "cput", "multi", "Set CPU test thread mode (supported: single, multi)") + c.GoecsFlag.StringVar(&c.MemoryTestMethod, "memorym", "stream", "Set memory test method (supported: stream, sysbench, dd, winsat, auto)") + c.GoecsFlag.StringVar(&c.DiskTestMethod, "diskm", "fio", "Set disk test method (supported: fio, dd, winsat)") + c.GoecsFlag.StringVar(&c.DiskTestPath, "diskp", "", "Set disk test path, e.g., -diskp /root") + c.GoecsFlag.BoolVar(&c.DiskMultiCheck, "diskmc", false, "Enable/Disable multiple disk checks, e.g., -diskmc=false") + c.GoecsFlag.StringVar(&c.Nt3Location, "nt3loc", "GZ", "Specify NT3 test location (supported: GZ, SH, BJ, CD, ALL for Guangzhou, Shanghai, Beijing, Chengdu and all)") + c.GoecsFlag.StringVar(&c.Nt3CheckType, "nt3t", "ipv4", "Set NT3 test type (supported: both, ipv4, ipv6)") + 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.Parse(args) + + c.GoecsFlag.Visit(func(f *flag.Flag) { + c.UserSetFlags[f.Name] = true + }) +} + +// HandleHelpAndVersion handles help and version flags +func (c *Config) HandleHelpAndVersion(programName string) bool { + if c.Help { + fmt.Printf("Usage: %s [options]\n", programName) + c.GoecsFlag.PrintDefaults() + return true + } + if c.ShowVersion { + fmt.Println(c.EcsVersion) + return true + } + return false +} + +// SaveUserSetParams saves user-set parameters +func (c *Config) SaveUserSetParams() map[string]interface{} { + saved := make(map[string]interface{}) + + if c.UserSetFlags["basic"] { + saved["basic"] = c.BasicStatus + } + if c.UserSetFlags["cpu"] { + saved["cpu"] = c.CpuTestStatus + } + if c.UserSetFlags["memory"] { + saved["memory"] = c.MemoryTestStatus + } + if c.UserSetFlags["disk"] { + saved["disk"] = c.DiskTestStatus + } + if c.UserSetFlags["comm"] { + saved["comm"] = c.CommTestStatus + } + if c.UserSetFlags["ut"] { + saved["ut"] = c.UtTestStatus + } + if c.UserSetFlags["security"] { + saved["security"] = c.SecurityTestStatus + } + if c.UserSetFlags["email"] { + saved["email"] = c.EmailTestStatus + } + if c.UserSetFlags["backtrace"] { + saved["backtrace"] = c.BacktraceStatus + } + if c.UserSetFlags["nt3"] { + saved["nt3"] = c.Nt3Status + } + if c.UserSetFlags["speed"] { + saved["speed"] = c.SpeedTestStatus + } + if c.UserSetFlags["ping"] { + saved["ping"] = c.PingTestStatus + } + if c.UserSetFlags["tgdc"] { + saved["tgdc"] = c.TgdcTestStatus + } + if c.UserSetFlags["web"] { + saved["web"] = c.WebTestStatus + } + if c.UserSetFlags["cpum"] { + saved["cpum"] = c.CpuTestMethod + } + if c.UserSetFlags["cput"] { + saved["cput"] = c.CpuTestThreadMode + } + if c.UserSetFlags["memorym"] { + saved["memorym"] = c.MemoryTestMethod + } + if c.UserSetFlags["diskm"] { + saved["diskm"] = c.DiskTestMethod + } + if c.UserSetFlags["diskp"] { + saved["diskp"] = c.DiskTestPath + } + if c.UserSetFlags["diskmc"] { + saved["diskmc"] = c.DiskMultiCheck + } + if c.UserSetFlags["nt3loc"] { + saved["nt3loc"] = c.Nt3Location + } + if c.UserSetFlags["nt3t"] { + saved["nt3t"] = c.Nt3CheckType + } + if c.UserSetFlags["spnum"] { + saved["spnum"] = c.SpNum + } + + return saved +} + +// RestoreUserSetParams restores user-set parameters +func (c *Config) RestoreUserSetParams(saved map[string]interface{}) { + if val, ok := saved["basic"]; ok { + c.BasicStatus = val.(bool) + } + if val, ok := saved["cpu"]; ok { + c.CpuTestStatus = val.(bool) + } + if val, ok := saved["memory"]; ok { + c.MemoryTestStatus = val.(bool) + } + if val, ok := saved["disk"]; ok { + c.DiskTestStatus = val.(bool) + } + if val, ok := saved["comm"]; ok { + c.CommTestStatus = val.(bool) + } + if val, ok := saved["ut"]; ok { + c.UtTestStatus = val.(bool) + } + if val, ok := saved["security"]; ok { + c.SecurityTestStatus = val.(bool) + } + if val, ok := saved["email"]; ok { + c.EmailTestStatus = val.(bool) + } + if val, ok := saved["backtrace"]; ok { + c.BacktraceStatus = val.(bool) + } + if val, ok := saved["nt3"]; ok { + c.Nt3Status = val.(bool) + } + if val, ok := saved["speed"]; ok { + c.SpeedTestStatus = val.(bool) + } + if val, ok := saved["ping"]; ok { + c.PingTestStatus = val.(bool) + } + if val, ok := saved["tgdc"]; ok { + c.TgdcTestStatus = val.(bool) + } + if val, ok := saved["web"]; ok { + c.WebTestStatus = val.(bool) + } + if val, ok := saved["cpum"]; ok { + c.CpuTestMethod = val.(string) + } + if val, ok := saved["cput"]; ok { + c.CpuTestThreadMode = val.(string) + } + if val, ok := saved["memorym"]; ok { + c.MemoryTestMethod = val.(string) + } + if val, ok := saved["diskm"]; ok { + c.DiskTestMethod = val.(string) + } + if val, ok := saved["diskp"]; ok { + c.DiskTestPath = val.(string) + } + if val, ok := saved["diskmc"]; ok { + c.DiskMultiCheck = val.(bool) + } + if val, ok := saved["nt3loc"]; ok { + if c.Choice != "10" { + c.Nt3Location = val.(string) + } + } + if val, ok := saved["nt3t"]; ok { + c.Nt3CheckType = val.(string) + } + if val, ok := saved["spnum"]; ok { + c.SpNum = val.(int) + } + + c.ValidateParams() +} + +// ValidateParams validates parameter values +func (c *Config) ValidateParams() { + validCpuMethods := map[string]bool{"sysbench": true, "geekbench": true, "winsat": true} + if !validCpuMethods[c.CpuTestMethod] { + if c.Language == "zh" { + fmt.Printf("警告: CPU测试方法 '%s' 无效,使用默认值 'sysbench'\n", c.CpuTestMethod) + } else { + fmt.Printf("Warning: Invalid CPU test method '%s', using default 'sysbench'\n", c.CpuTestMethod) + } + c.CpuTestMethod = "sysbench" + } + + validThreadModes := map[string]bool{"single": true, "multi": true} + if !validThreadModes[c.CpuTestThreadMode] { + if c.Language == "zh" { + fmt.Printf("警告: CPU线程模式 '%s' 无效,使用默认值 'multi'\n", c.CpuTestThreadMode) + } else { + fmt.Printf("Warning: Invalid CPU thread mode '%s', using default 'multi'\n", c.CpuTestThreadMode) + } + c.CpuTestThreadMode = "multi" + } + + validMemoryMethods := map[string]bool{"stream": true, "sysbench": true, "dd": true, "winsat": true, "auto": true} + if !validMemoryMethods[c.MemoryTestMethod] { + if c.Language == "zh" { + fmt.Printf("警告: 内存测试方法 '%s' 无效,使用默认值 'stream'\n", c.MemoryTestMethod) + } else { + fmt.Printf("Warning: Invalid memory test method '%s', using default 'stream'\n", c.MemoryTestMethod) + } + c.MemoryTestMethod = "stream" + } + + validDiskMethods := map[string]bool{"fio": true, "dd": true, "winsat": true} + if !validDiskMethods[c.DiskTestMethod] { + if c.Language == "zh" { + fmt.Printf("警告: 磁盘测试方法 '%s' 无效,使用默认值 'fio'\n", c.DiskTestMethod) + } else { + fmt.Printf("Warning: Invalid disk test method '%s', using default 'fio'\n", c.DiskTestMethod) + } + c.DiskTestMethod = "fio" + } + + validNt3Locations := map[string]bool{"GZ": true, "SH": true, "BJ": true, "CD": true, "ALL": true} + if !validNt3Locations[c.Nt3Location] { + if c.Language == "zh" { + fmt.Printf("警告: NT3测试位置 '%s' 无效,使用默认值 'GZ'\n", c.Nt3Location) + } else { + fmt.Printf("Warning: Invalid NT3 location '%s', using default 'GZ'\n", c.Nt3Location) + } + c.Nt3Location = "GZ" + } + + validNt3Types := map[string]bool{"both": true, "ipv4": true, "ipv6": true} + if !validNt3Types[c.Nt3CheckType] { + if c.Language == "zh" { + fmt.Printf("警告: NT3测试类型 '%s' 无效,使用默认值 'ipv4'\n", c.Nt3CheckType) + } else { + fmt.Printf("Warning: Invalid NT3 check type '%s', using default 'ipv4'\n", c.Nt3CheckType) + } + c.Nt3CheckType = "ipv4" + } + + if c.SpNum < 0 { + if c.Language == "zh" { + fmt.Printf("警告: 测速节点数量 '%d' 无效,使用默认值 2\n", c.SpNum) + } else { + fmt.Printf("Warning: Invalid speed test node count '%d', using default 2\n", c.SpNum) + } + c.SpNum = 2 + } + + validLanguages := map[string]bool{"zh": true, "en": true} + if !validLanguages[c.Language] { + fmt.Printf("Warning: Invalid language '%s', using default 'zh'\n", c.Language) + c.Language = "zh" + } +} diff --git a/internal/runner/runner.go b/internal/runner/runner.go new file mode 100644 index 0000000..027403e --- /dev/null +++ b/internal/runner/runner.go @@ -0,0 +1,489 @@ +package runner + +import ( + "bufio" + "fmt" + "os" + "runtime" + "strings" + "sync" + "time" + + "github.com/oneclickvirt/CommonMediaTests/commediatests" + "github.com/oneclickvirt/ecs/cputest" + "github.com/oneclickvirt/ecs/disktest" + "github.com/oneclickvirt/ecs/internal/params" + "github.com/oneclickvirt/ecs/memorytest" + "github.com/oneclickvirt/ecs/nexttrace" + "github.com/oneclickvirt/ecs/speedtest" + "github.com/oneclickvirt/ecs/unlocktest" + "github.com/oneclickvirt/ecs/upstreams" + "github.com/oneclickvirt/ecs/utils" + "github.com/oneclickvirt/pingtest/pt" + "github.com/oneclickvirt/portchecker/email" +) + +// RunChineseTests runs all tests in Chinese mode +func RunChineseTests(preCheck utils.NetCheckResult, config *params.Config, wg1, wg2, wg3 *sync.WaitGroup, basicInfo, securityInfo, emailInfo, mediaInfo, ptInfo *string, output *string, tempOutput string, startTime time.Time, outputMutex *sync.Mutex) { + *output = RunBasicTests(preCheck, config, basicInfo, securityInfo, *output, tempOutput, outputMutex) + *output = RunCPUTest(config, *output, tempOutput, outputMutex) + *output = RunMemoryTest(config, *output, tempOutput, outputMutex) + *output = RunDiskTest(config, *output, tempOutput, outputMutex) + if config.OnlyIpInfoCheck && !config.BasicStatus && preCheck.Connected && preCheck.StackType != "" && preCheck.StackType != "None" { + *output = RunIpInfoCheck(config, *output, tempOutput, outputMutex) + } + if config.UtTestStatus && preCheck.Connected && preCheck.StackType != "" && preCheck.StackType != "None" && !config.OnlyChinaTest { + wg1.Add(1) + go func() { + defer wg1.Done() + *mediaInfo = unlocktest.MediaTest(config.Language) + }() + } + if config.EmailTestStatus && preCheck.Connected && preCheck.StackType != "" && preCheck.StackType != "None" { + wg2.Add(1) + go func() { + defer wg2.Done() + *emailInfo = email.EmailCheck() + }() + } + if (config.OnlyChinaTest || config.PingTestStatus) && preCheck.Connected && preCheck.StackType != "" && preCheck.StackType != "None" { + wg3.Add(1) + go func() { + defer wg3.Done() + *ptInfo = pt.PingTest() + }() + } + if preCheck.Connected && preCheck.StackType != "" && preCheck.StackType != "None" { + *output = RunStreamingTests(config, wg1, mediaInfo, *output, tempOutput, outputMutex) + *output = RunSecurityTests(config, *securityInfo, *output, tempOutput, outputMutex) + *output = RunEmailTests(config, wg2, emailInfo, *output, tempOutput, outputMutex) + } + if runtime.GOOS != "windows" && preCheck.Connected && preCheck.StackType != "" && preCheck.StackType != "None" { + *output = RunNetworkTests(config, wg3, ptInfo, *output, tempOutput, outputMutex) + } + if preCheck.Connected && preCheck.StackType != "" && preCheck.StackType != "None" { + *output = RunSpeedTests(config, *output, tempOutput, outputMutex) + } + *output = AppendTimeInfo(config, *output, tempOutput, startTime, outputMutex) +} + +// RunEnglishTests runs all tests in English mode +func RunEnglishTests(preCheck utils.NetCheckResult, config *params.Config, wg1, wg2, wg3 *sync.WaitGroup, basicInfo, securityInfo, emailInfo, mediaInfo, ptInfo *string, output *string, tempOutput string, startTime time.Time, outputMutex *sync.Mutex) { + *output = RunBasicTests(preCheck, config, basicInfo, securityInfo, *output, tempOutput, outputMutex) + *output = RunCPUTest(config, *output, tempOutput, outputMutex) + *output = RunMemoryTest(config, *output, tempOutput, outputMutex) + *output = RunDiskTest(config, *output, tempOutput, outputMutex) + if config.OnlyIpInfoCheck && !config.BasicStatus && preCheck.Connected && preCheck.StackType != "" && preCheck.StackType != "None" { + *output = RunIpInfoCheck(config, *output, tempOutput, outputMutex) + } + if preCheck.Connected && preCheck.StackType != "" && preCheck.StackType != "None" { + if config.UtTestStatus { + wg1.Add(1) + go func() { + defer wg1.Done() + *mediaInfo = unlocktest.MediaTest(config.Language) + }() + } + if config.EmailTestStatus { + wg2.Add(1) + go func() { + defer wg2.Done() + *emailInfo = email.EmailCheck() + }() + } + *output = RunStreamingTests(config, wg1, mediaInfo, *output, tempOutput, outputMutex) + *output = RunSecurityTests(config, *securityInfo, *output, tempOutput, outputMutex) + *output = RunEmailTests(config, wg2, emailInfo, *output, tempOutput, outputMutex) + *output = RunEnglishNetworkTests(config, wg3, ptInfo, *output, tempOutput, outputMutex) + *output = RunEnglishSpeedTests(config, *output, tempOutput, outputMutex) + } + *output = AppendTimeInfo(config, *output, tempOutput, startTime, outputMutex) +} + +// RunIpInfoCheck performs IP info check +func RunIpInfoCheck(config *params.Config, output, tempOutput string, outputMutex *sync.Mutex) string { + outputMutex.Lock() + defer outputMutex.Unlock() + return utils.PrintAndCapture(func() { + var ipinfo string + upstreams.IPV4, upstreams.IPV6, ipinfo = utils.OnlyBasicsIpInfo(config.Language) + if ipinfo != "" { + if config.Language == "zh" { + utils.PrintCenteredTitle("IP信息", config.Width) + } else { + utils.PrintCenteredTitle("IP-Information", config.Width) + } + fmt.Printf("%s", ipinfo) + } + }, tempOutput, output) +} + +// RunBasicTests runs basic system tests +func RunBasicTests(preCheck utils.NetCheckResult, config *params.Config, basicInfo, securityInfo *string, output, tempOutput string, outputMutex *sync.Mutex) string { + outputMutex.Lock() + defer outputMutex.Unlock() + return utils.PrintAndCapture(func() { + utils.PrintHead(config.Language, config.Width, config.EcsVersion) + if config.BasicStatus || config.SecurityTestStatus { + if config.BasicStatus { + if config.Language == "zh" { + utils.PrintCenteredTitle("系统基础信息", config.Width) + } else { + utils.PrintCenteredTitle("System-Basic-Information", config.Width) + } + } + if preCheck.Connected && preCheck.StackType == "DualStack" { + upstreams.IPV4, upstreams.IPV6, *basicInfo, *securityInfo, config.Nt3CheckType = utils.BasicsAndSecurityCheck(config.Language, config.Nt3CheckType, config.SecurityTestStatus) + } else if preCheck.Connected && preCheck.StackType == "IPv4" { + upstreams.IPV4, upstreams.IPV6, *basicInfo, *securityInfo, config.Nt3CheckType = utils.BasicsAndSecurityCheck(config.Language, "ipv4", config.SecurityTestStatus) + } else if preCheck.Connected && preCheck.StackType == "IPv6" { + upstreams.IPV4, upstreams.IPV6, *basicInfo, *securityInfo, config.Nt3CheckType = utils.BasicsAndSecurityCheck(config.Language, "ipv6", config.SecurityTestStatus) + } else { + upstreams.IPV4, upstreams.IPV6, *basicInfo, *securityInfo, config.Nt3CheckType = utils.BasicsAndSecurityCheck(config.Language, "", false) + config.SecurityTestStatus = false + } + if config.BasicStatus { + fmt.Printf("%s", *basicInfo) + } else if (config.Input == "6" || config.Input == "9") && config.SecurityTestStatus { + scanner := bufio.NewScanner(strings.NewReader(*basicInfo)) + for scanner.Scan() { + line := scanner.Text() + if strings.Contains(line, "IPV") { + fmt.Println(line) + } + } + } + } + }, tempOutput, output) +} + +// RunCPUTest runs CPU test +func RunCPUTest(config *params.Config, output, tempOutput string, outputMutex *sync.Mutex) string { + outputMutex.Lock() + defer outputMutex.Unlock() + return utils.PrintAndCapture(func() { + if config.CpuTestStatus { + realTestMethod, res := cputest.CpuTest(config.Language, config.CpuTestMethod, config.CpuTestThreadMode) + if config.Language == "zh" { + utils.PrintCenteredTitle(fmt.Sprintf("CPU测试-通过%s测试", realTestMethod), config.Width) + } else { + utils.PrintCenteredTitle(fmt.Sprintf("CPU-Test--%s-Method", realTestMethod), config.Width) + } + fmt.Print(res) + } + }, tempOutput, output) +} + +// RunMemoryTest runs memory test +func RunMemoryTest(config *params.Config, output, tempOutput string, outputMutex *sync.Mutex) string { + outputMutex.Lock() + defer outputMutex.Unlock() + return utils.PrintAndCapture(func() { + if config.MemoryTestStatus { + realTestMethod, res := memorytest.MemoryTest(config.Language, config.MemoryTestMethod) + if config.Language == "zh" { + utils.PrintCenteredTitle(fmt.Sprintf("内存测试-通过%s测试", realTestMethod), config.Width) + } else { + utils.PrintCenteredTitle(fmt.Sprintf("Memory-Test--%s-Method", realTestMethod), config.Width) + } + fmt.Print(res) + } + }, tempOutput, output) +} + +// RunDiskTest runs disk test +func RunDiskTest(config *params.Config, output, tempOutput string, outputMutex *sync.Mutex) string { + outputMutex.Lock() + defer outputMutex.Unlock() + return utils.PrintAndCapture(func() { + if config.DiskTestStatus && config.AutoChangeDiskMethod { + realTestMethod, res := disktest.DiskTest(config.Language, config.DiskTestMethod, config.DiskTestPath, config.DiskMultiCheck, config.AutoChangeDiskMethod) + if config.Language == "zh" { + utils.PrintCenteredTitle(fmt.Sprintf("硬盘测试-通过%s测试", realTestMethod), config.Width) + } else { + utils.PrintCenteredTitle(fmt.Sprintf("Disk-Test--%s-Method", realTestMethod), config.Width) + } + fmt.Print(res) + } else if config.DiskTestStatus && !config.AutoChangeDiskMethod { + if config.Language == "zh" { + utils.PrintCenteredTitle(fmt.Sprintf("硬盘测试-通过%s测试", "dd"), config.Width) + _, res := disktest.DiskTest(config.Language, "dd", config.DiskTestPath, config.DiskMultiCheck, config.AutoChangeDiskMethod) + fmt.Print(res) + utils.PrintCenteredTitle(fmt.Sprintf("硬盘测试-通过%s测试", "fio"), config.Width) + _, res = disktest.DiskTest(config.Language, "fio", config.DiskTestPath, config.DiskMultiCheck, config.AutoChangeDiskMethod) + fmt.Print(res) + } else { + utils.PrintCenteredTitle(fmt.Sprintf("Disk-Test--%s-Method", "dd"), config.Width) + _, res := disktest.DiskTest(config.Language, "dd", config.DiskTestPath, config.DiskMultiCheck, config.AutoChangeDiskMethod) + fmt.Print(res) + utils.PrintCenteredTitle(fmt.Sprintf("Disk-Test--%s-Method", "fio"), config.Width) + _, res = disktest.DiskTest(config.Language, "fio", config.DiskTestPath, config.DiskMultiCheck, config.AutoChangeDiskMethod) + fmt.Print(res) + } + } + }, tempOutput, output) +} + +// RunStreamingTests runs streaming media tests +func RunStreamingTests(config *params.Config, wg1 *sync.WaitGroup, mediaInfo *string, output, tempOutput string, outputMutex *sync.Mutex) string { + outputMutex.Lock() + defer outputMutex.Unlock() + return utils.PrintAndCapture(func() { + if config.Language == "zh" { + if config.CommTestStatus && !config.OnlyChinaTest { + utils.PrintCenteredTitle("御三家流媒体解锁", config.Width) + fmt.Printf("%s", commediatests.MediaTests(config.Language)) + } + } + if config.UtTestStatus && (config.Language == "zh" && !config.OnlyChinaTest || config.Language == "en") { + wg1.Wait() + if config.Language == "zh" { + utils.PrintCenteredTitle("跨国流媒体解锁", config.Width) + } else { + utils.PrintCenteredTitle("Cross-Border-Streaming-Media-Unlock", config.Width) + } + fmt.Printf("%s", *mediaInfo) + } + }, tempOutput, output) +} + +// RunSecurityTests runs security tests +func RunSecurityTests(config *params.Config, securityInfo, output, tempOutput string, outputMutex *sync.Mutex) string { + outputMutex.Lock() + defer outputMutex.Unlock() + return utils.PrintAndCapture(func() { + if config.SecurityTestStatus { + if config.Language == "zh" { + utils.PrintCenteredTitle("IP质量检测", config.Width) + } else { + utils.PrintCenteredTitle("IP-Quality-Check", config.Width) + } + fmt.Printf("%s", securityInfo) + } + }, tempOutput, output) +} + +// RunEmailTests runs email port tests +func RunEmailTests(config *params.Config, wg2 *sync.WaitGroup, emailInfo *string, output, tempOutput string, outputMutex *sync.Mutex) string { + outputMutex.Lock() + defer outputMutex.Unlock() + return utils.PrintAndCapture(func() { + if config.EmailTestStatus { + wg2.Wait() + if config.Language == "zh" { + utils.PrintCenteredTitle("邮件端口检测", config.Width) + } else { + utils.PrintCenteredTitle("Email-Port-Check", config.Width) + } + fmt.Println(*emailInfo) + } + }, tempOutput, output) +} + +// RunNetworkTests runs network tests (Chinese mode) +func RunNetworkTests(config *params.Config, wg3 *sync.WaitGroup, ptInfo *string, output, tempOutput string, outputMutex *sync.Mutex) string { + outputMutex.Lock() + defer outputMutex.Unlock() + return utils.PrintAndCapture(func() { + if config.BacktraceStatus && !config.OnlyChinaTest { + utils.PrintCenteredTitle("上游及回程线路检测", config.Width) + upstreams.UpstreamsCheck() + } + if config.Nt3Status && !config.OnlyChinaTest { + utils.PrintCenteredTitle("三网回程路由检测", config.Width) + nexttrace.NextTrace3Check(config.Language, config.Nt3Location, config.Nt3CheckType) + } + if config.OnlyChinaTest && *ptInfo != "" { + wg3.Wait() + utils.PrintCenteredTitle("PING值检测", config.Width) + fmt.Println(*ptInfo) + } + if config.PingTestStatus && *ptInfo != "" { + wg3.Wait() + utils.PrintCenteredTitle("PING值检测", config.Width) + fmt.Println(*ptInfo) + if config.TgdcTestStatus { + fmt.Println(pt.TelegramDCTest()) + } + if config.WebTestStatus { + fmt.Println(pt.WebsiteTest()) + } + } + if !config.OnlyChinaTest && !config.PingTestStatus && (config.TgdcTestStatus || config.WebTestStatus) { + utils.PrintCenteredTitle("PING值检测", config.Width) + if config.TgdcTestStatus { + fmt.Println(pt.TelegramDCTest()) + } + if config.WebTestStatus { + fmt.Println(pt.WebsiteTest()) + } + } + }, tempOutput, output) +} + +// RunSpeedTests runs speed tests (Chinese mode) +func RunSpeedTests(config *params.Config, output, tempOutput string, outputMutex *sync.Mutex) string { + outputMutex.Lock() + defer outputMutex.Unlock() + return utils.PrintAndCapture(func() { + if config.SpeedTestStatus { + utils.PrintCenteredTitle("就近节点测速", config.Width) + speedtest.ShowHead(config.Language) + if config.Choice == "1" || !config.MenuMode { + speedtest.NearbySP() + speedtest.CustomSP("net", "global", 2, config.Language) + speedtest.CustomSP("net", "cu", config.SpNum, config.Language) + speedtest.CustomSP("net", "ct", config.SpNum, config.Language) + speedtest.CustomSP("net", "cmcc", config.SpNum, config.Language) + } else if config.Choice == "2" || config.Choice == "3" || config.Choice == "4" || config.Choice == "5" { + speedtest.CustomSP("net", "global", 4, config.Language) + } else if config.Choice == "6" { + speedtest.CustomSP("net", "global", 11, config.Language) + } + } + }, tempOutput, output) +} + +// RunEnglishNetworkTests runs network tests (English mode) +func RunEnglishNetworkTests(config *params.Config, wg3 *sync.WaitGroup, ptInfo *string, output, tempOutput string, outputMutex *sync.Mutex) string { + outputMutex.Lock() + defer outputMutex.Unlock() + return utils.PrintAndCapture(func() { + if config.TgdcTestStatus || config.WebTestStatus { + utils.PrintCenteredTitle("PING-Test", config.Width) + if config.TgdcTestStatus { + fmt.Println(pt.TelegramDCTest()) + } + if config.WebTestStatus { + fmt.Println(pt.WebsiteTest()) + } + } + }, tempOutput, output) +} + +// RunEnglishSpeedTests runs speed tests (English mode) +func RunEnglishSpeedTests(config *params.Config, output, tempOutput string, outputMutex *sync.Mutex) string { + outputMutex.Lock() + defer outputMutex.Unlock() + return utils.PrintAndCapture(func() { + if config.SpeedTestStatus { + utils.PrintCenteredTitle("Speed-Test", config.Width) + speedtest.ShowHead(config.Language) + speedtest.NearbySP() + speedtest.CustomSP("net", "global", -1, config.Language) + } + }, tempOutput, output) +} + +// AppendTimeInfo appends timing information +func AppendTimeInfo(config *params.Config, output, tempOutput string, startTime time.Time, outputMutex *sync.Mutex) string { + outputMutex.Lock() + defer outputMutex.Unlock() + endTime := time.Now() + duration := endTime.Sub(startTime) + minutes := int(duration.Minutes()) + seconds := int(duration.Seconds()) % 60 + currentTime := time.Now().Format("Mon Jan 2 15:04:05 MST 2006") + return utils.PrintAndCapture(func() { + utils.PrintCenteredTitle("", config.Width) + if config.Language == "zh" { + fmt.Printf("花费 : %d 分 %d 秒\n", minutes, seconds) + fmt.Printf("时间 : %s\n", currentTime) + } else { + fmt.Printf("Cost Time : %d min %d sec\n", minutes, seconds) + fmt.Printf("Current Time : %s\n", currentTime) + } + utils.PrintCenteredTitle("", config.Width) + }, 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 { + case <-sig: + if !config.Finish { + endTime := time.Now() + duration := endTime.Sub(*startTime) + minutes := int(duration.Minutes()) + seconds := int(duration.Seconds()) % 60 + currentTime := time.Now().Format("Mon Jan 2 15:04:05 MST 2006") + outputMutex.Lock() + timeInfo := utils.PrintAndCapture(func() { + utils.PrintCenteredTitle("", config.Width) + if config.Language == "zh" { + fmt.Printf("花费 : %d 分 %d 秒\n", minutes, seconds) + fmt.Printf("时间 : %s\n", currentTime) + } else { + fmt.Printf("Cost Time : %d min %d sec\n", minutes, seconds) + fmt.Printf("Current Time : %s\n", currentTime) + } + utils.PrintCenteredTitle("", config.Width) + }, "", "") + *output += timeInfo + finalOutput := *output + outputMutex.Unlock() + resultChan := make(chan struct { + httpURL string + httpsURL string + }, 1) + if config.EnableUpload { + go func() { + httpURL, httpsURL := utils.ProcessAndUpload(finalOutput, config.FilePath, config.EnableUpload) + resultChan <- struct { + httpURL string + httpsURL string + }{httpURL, httpsURL} + uploadDone <- true + }() + select { + case result := <-resultChan: + if result.httpURL != "" || result.httpsURL != "" { + if config.Language == "en" { + fmt.Printf("Upload successfully!\nHttp URL: %s\nHttps URL: %s\n", result.httpURL, result.httpsURL) + } else { + fmt.Printf("上传成功!\nHttp URL: %s\nHttps URL: %s\n", result.httpURL, result.httpsURL) + } + } + time.Sleep(100 * time.Millisecond) + if runtime.GOOS == "windows" || runtime.GOOS == "darwin" { + fmt.Println("Press Enter to exit...") + fmt.Scanln() + } + os.Exit(0) + case <-time.After(30 * time.Second): + if config.Language == "en" { + fmt.Println("Upload timeout, program exit") + } else { + fmt.Println("上传超时,程序退出") + } + if runtime.GOOS == "windows" || runtime.GOOS == "darwin" { + fmt.Println("Press Enter to exit...") + fmt.Scanln() + } + os.Exit(1) + } + } else { + if runtime.GOOS == "windows" || runtime.GOOS == "darwin" { + fmt.Println("Press Enter to exit...") + fmt.Scanln() + } + os.Exit(0) + } + } + os.Exit(0) + } +} + +// HandleUploadResults handles uploading results +func HandleUploadResults(config *params.Config, output string) { + httpURL, httpsURL := utils.ProcessAndUpload(output, config.FilePath, config.EnableUpload) + if httpURL != "" || httpsURL != "" { + if config.Language == "en" { + fmt.Printf("Upload successfully!\nHttp URL: %s\nHttps URL: %s\n", httpURL, httpsURL) + fmt.Println("Each Test Benchmark: https://bash.spiritlhl.net/ecsguide") + } else { + fmt.Printf("上传成功!\nHttp URL: %s\nHttps URL: %s\n", httpURL, httpsURL) + fmt.Println("每项测试基准见: https://bash.spiritlhl.net/ecsguide") + } + } +}