Files
ecs/ui/executor.go
T
spiritlhl 791ec8df5e
Build All UI APP / Prepare Version (push) Has been cancelled
Build All UI APP / Build Android APK (push) Has been cancelled
Build All UI APP / Build Desktop Apps (amd64, macos-amd64, macos-13, darwin) (push) Has been cancelled
Build All UI APP / Build Desktop Apps (amd64, windows-amd64, windows-latest, windows) (push) Has been cancelled
Build All UI APP / Build Desktop Apps (arm64, macos-arm64, macos-latest, darwin) (push) Has been cancelled
fix:添加UI配置参数对接
2025-11-02 18:59:03 +08:00

330 lines
8.8 KiB
Go

package ui
import (
"fmt"
"io"
"os"
"os/signal"
"strings"
"sync"
"syscall"
"time"
"github.com/oneclickvirt/CommonMediaTests/commediatests"
"github.com/oneclickvirt/basics/utils"
"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"
ecsutils "github.com/oneclickvirt/ecs/utils"
"github.com/oneclickvirt/pingtest/pt"
"github.com/oneclickvirt/portchecker/email"
)
const ecsVersion = "v0.1.93"
type CommandExecutor struct {
outputCallback func(string)
}
func NewCommandExecutor(outputCallback func(string)) *CommandExecutor {
return &CommandExecutor{
outputCallback: outputCallback,
}
}
func (e *CommandExecutor) Execute(selectedOptions map[string]bool, language string, testUpload bool, testDownload bool, chinaModeEnabled bool,
cpuMethod, threadMode, memoryMethod, diskMethod, diskPath string, diskMulti bool,
nt3Location, nt3Type string, spNum int) error {
// 设置测试选项
basicStatus := selectedOptions["basic"]
cpuTestStatus := selectedOptions["cpu"]
memoryTestStatus := selectedOptions["memory"]
diskTestStatus := selectedOptions["disk"]
commTestStatus := selectedOptions["comm"]
utTestStatus := selectedOptions["unlock"]
securityTestStatus := selectedOptions["security"]
emailTestStatus := selectedOptions["email"]
backtraceStatus := selectedOptions["backtrace"]
nt3Status := selectedOptions["nt3"]
speedTestStatus := selectedOptions["speed"]
pingTestStatus := selectedOptions["ping"]
// 中国模式逻辑:禁用流媒体测试,启用PING测试
if chinaModeEnabled {
commTestStatus = false
utTestStatus = false
pingTestStatus = true
}
// 检查网络连接
preCheck := utils.CheckPublicAccess(3 * time.Second)
// 初始化变量
var (
wg1, wg2 sync.WaitGroup
basicInfo, securityInfo, emailInfo, mediaInfo string
output, tempOutput string
outputMutex sync.Mutex
)
startTime := time.Now()
uploadDone := make(chan bool, 1)
sig := make(chan os.Signal, 1)
signal.Notify(sig, os.Interrupt, syscall.SIGINT, syscall.SIGTERM)
// 重定向输出到回调
oldStdout := os.Stdout
r, w, _ := os.Pipe()
os.Stdout = w
done := make(chan bool)
go func() {
buf := make([]byte, 8192) // 增加缓冲区大小
var partial string // 用于保存不完整的行
for {
n, err := r.Read(buf)
if n > 0 && e.outputCallback != nil {
text := partial + string(buf[:n])
// 找到最后一个换行符
lastNewline := strings.LastIndex(text, "\n")
if lastNewline >= 0 {
// 输出完整的行
e.outputCallback(text[:lastNewline+1])
// 保存不完整的部分
partial = text[lastNewline+1:]
} else {
// 没有换行符,全部保存为不完整部分
partial = text
}
}
if err != nil {
if err == io.EOF {
// 输出剩余的不完整部分
if partial != "" && e.outputCallback != nil {
e.outputCallback(partial)
}
break
}
}
}
done <- true
}()
// 执行测试(参考原goecs.go的runChineseTests和runEnglishTests顺序)
// 1. 基础信息测试
if basicStatus || securityTestStatus {
outputMutex.Lock()
ecsutils.PrintHead(language, 82, ecsVersion)
if basicStatus {
if language == "zh" {
ecsutils.PrintCenteredTitle("系统基础信息", 82)
} else {
ecsutils.PrintCenteredTitle("System-Basic-Information", 82)
}
}
if preCheck.Connected {
_, _, basicInfo, securityInfo, _ = ecsutils.BasicsAndSecurityCheck(language, "ipv4", securityTestStatus)
}
if basicStatus {
fmt.Printf("%s", basicInfo)
}
outputMutex.Unlock()
}
// 2. CPU测试
if cpuTestStatus {
outputMutex.Lock()
realTestMethod, res := cputest.CpuTest(language, cpuMethod, threadMode)
if language == "zh" {
ecsutils.PrintCenteredTitle(fmt.Sprintf("CPU测试-通过%s测试", realTestMethod), 82)
} else {
ecsutils.PrintCenteredTitle(fmt.Sprintf("CPU-Test--%s-Method", realTestMethod), 82)
}
fmt.Print(res)
outputMutex.Unlock()
}
// 3. 内存测试
if memoryTestStatus {
outputMutex.Lock()
realTestMethod, res := memorytest.MemoryTest(language, memoryMethod)
if language == "zh" {
ecsutils.PrintCenteredTitle(fmt.Sprintf("内存测试-通过%s测试", realTestMethod), 82)
} else {
ecsutils.PrintCenteredTitle(fmt.Sprintf("Memory-Test--%s-Method", realTestMethod), 82)
}
fmt.Print(res)
outputMutex.Unlock()
}
// 4. 磁盘测试
if diskTestStatus {
outputMutex.Lock()
realTestMethod, res := disktest.DiskTest(language, diskMethod, diskPath, diskMulti, true)
if language == "zh" {
ecsutils.PrintCenteredTitle(fmt.Sprintf("硬盘测试-通过%s测试", realTestMethod), 82)
} else {
ecsutils.PrintCenteredTitle(fmt.Sprintf("Disk-Test--%s-Method", realTestMethod), 82)
}
fmt.Print(res)
outputMutex.Unlock()
}
// 5. 启动异步测试(流媒体解锁和邮件端口)
if utTestStatus && preCheck.Connected {
wg1.Add(1)
go func() {
defer wg1.Done()
mediaInfo = unlocktest.MediaTest(language)
}()
}
if emailTestStatus && preCheck.Connected {
wg2.Add(1)
go func() {
defer wg2.Done()
emailInfo = email.EmailCheck()
}()
}
// 6. 御三家流媒体测试(仅中文)
if commTestStatus && preCheck.Connected && language == "zh" {
outputMutex.Lock()
ecsutils.PrintCenteredTitle("御三家流媒体测试", 82)
commInfo := commediatests.MediaTests(language)
fmt.Print(commInfo)
outputMutex.Unlock()
}
// 7. 显示跨国流媒体解锁结果
if utTestStatus && preCheck.Connected {
wg1.Wait()
outputMutex.Lock()
if language == "zh" {
ecsutils.PrintCenteredTitle("跨国流媒体解锁", 82)
} else {
ecsutils.PrintCenteredTitle("Cross-Border-Streaming-Media-Unlock", 82)
}
fmt.Printf("%s", mediaInfo)
outputMutex.Unlock()
}
// 8. 显示IP质量检测结果
if securityTestStatus && preCheck.Connected {
outputMutex.Lock()
if language == "zh" {
ecsutils.PrintCenteredTitle("IP质量检测", 82)
} else {
ecsutils.PrintCenteredTitle("IP-Quality-Check", 82)
}
fmt.Printf("%s", securityInfo)
outputMutex.Unlock()
}
// 9. 显示邮件端口测试结果
if emailTestStatus && preCheck.Connected {
wg2.Wait()
outputMutex.Lock()
if language == "zh" {
ecsutils.PrintCenteredTitle("邮件端口检测", 82)
} else {
ecsutils.PrintCenteredTitle("Email-Port-Check", 82)
}
fmt.Println(emailInfo)
outputMutex.Unlock()
}
// 10. 上游及回程线路检测
if backtraceStatus && preCheck.Connected {
outputMutex.Lock()
if language == "zh" {
ecsutils.PrintCenteredTitle("上游及回程线路检测", 82)
} else {
ecsutils.PrintCenteredTitle("Upstreams-Backtrace-Check", 82)
}
upstreams.UpstreamsCheck()
outputMutex.Unlock()
}
// 11. 三网回程路由检测
if nt3Status && preCheck.Connected {
outputMutex.Lock()
if language == "zh" {
ecsutils.PrintCenteredTitle("三网回程路由检测", 82)
} else {
ecsutils.PrintCenteredTitle("NextTrace-3Networks-Check", 82)
}
nexttrace.NextTrace3Check(language, nt3Location, nt3Type)
outputMutex.Unlock()
}
// 12. PING值测试
if pingTestStatus && preCheck.Connected {
outputMutex.Lock()
if language == "zh" {
ecsutils.PrintCenteredTitle("三网PING值检测", 82)
} else {
ecsutils.PrintCenteredTitle("Three-Network-PING-Test", 82)
}
pingResult := pt.PingTest()
fmt.Print(pingResult)
outputMutex.Unlock()
}
// 13. 速度测试
if speedTestStatus && preCheck.Connected {
outputMutex.Lock()
if language == "zh" {
ecsutils.PrintCenteredTitle("就近节点测速", 82)
} else {
ecsutils.PrintCenteredTitle("Speed-Test", 82)
}
speedtest.ShowHead(language)
// 根据上传/下载配置进行测试
if testUpload || testDownload {
speedtest.NearbySP()
if language == "zh" {
speedtest.CustomSP("net", "global", spNum, language)
} else {
speedtest.CustomSP("net", "global", -1, language)
}
}
outputMutex.Unlock()
}
// 打印时间信息
outputMutex.Lock()
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")
ecsutils.PrintCenteredTitle("", 82)
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)
}
ecsutils.PrintCenteredTitle("", 82)
outputMutex.Unlock()
// 清理
_ = uploadDone
_ = sig
_ = output
_ = tempOutput
// 恢复输出
w.Close()
<-done
os.Stdout = oldStdout
return nil
}