feat: Add backend API for team registration execution.

This commit is contained in:
2026-02-01 07:13:34 +08:00
parent d4fb35b143
commit c8aa925205

View File

@@ -10,6 +10,7 @@ import (
"os"
"os/exec"
"path/filepath"
"regexp"
"runtime"
"sort"
"strings"
@@ -20,6 +21,9 @@ import (
"codex-pool/internal/logger"
)
// ansiRegex 匹配 ANSI 转义序列(颜色码等)
var ansiRegex = regexp.MustCompile(`\x1b\[[0-9;]*[a-zA-Z]`)
// TeamRegConfig 注册配置
type TeamRegConfig struct {
Count int `json:"count"` // 注册数量
@@ -40,8 +44,17 @@ type TeamRegState struct {
cmd *exec.Cmd
cancel context.CancelFunc
stdin io.WriteCloser
// 403 错误检测
error403Count int // 403 错误计数
error403Start time.Time // 计数开始时间
}
// 403 自动停止配置
const (
max403Errors = 10 // 最大 403 错误数
error403Window = 60 * time.Second // 时间窗口60秒内
)
var teamRegState = &TeamRegState{
Logs: make([]string, 0),
}
@@ -91,6 +104,8 @@ func HandleTeamRegStart(w http.ResponseWriter, r *http.Request) {
teamRegState.Logs = make([]string, 0)
teamRegState.OutputFile = ""
teamRegState.Imported = 0
teamRegState.error403Count = 0
teamRegState.error403Start = time.Now()
teamRegState.mu.Unlock()
// 启动进程
@@ -110,9 +125,9 @@ func HandleTeamRegStop(w http.ResponseWriter, r *http.Request) {
}
teamRegState.mu.Lock()
defer teamRegState.mu.Unlock()
if !teamRegState.Running {
teamRegState.mu.Unlock()
json.NewEncoder(w).Encode(map[string]interface{}{
"success": false,
"message": "没有正在运行的任务",
@@ -120,7 +135,7 @@ func HandleTeamRegStop(w http.ResponseWriter, r *http.Request) {
return
}
// 发送 Ctrl+C 信号
// 发送取消信号
if teamRegState.cancel != nil {
teamRegState.cancel()
}
@@ -131,6 +146,9 @@ func HandleTeamRegStop(w http.ResponseWriter, r *http.Request) {
}
teamRegState.Running = false
teamRegState.mu.Unlock()
// 在释放锁之后再添加日志
addTeamRegLog("[系统] 任务已被用户停止")
json.NewEncoder(w).Encode(map[string]interface{}{
@@ -396,8 +414,54 @@ func readOutput(reader io.Reader, workDir string, config TeamRegConfig) {
trimmed := strings.TrimSpace(line)
if trimmed != "" {
addTeamRegLog(trimmed)
// 检测 403 错误
if strings.Contains(trimmed, "403") {
if check403AndStop() {
return // 已触发自动停止
}
}
}
}
}
// check403AndStop 检查 403 错误并决定是否自动停止
// 返回 true 表示已触发停止
func check403AndStop() bool {
teamRegState.mu.Lock()
defer teamRegState.mu.Unlock()
now := time.Now()
// 如果超过时间窗口,重置计数
if now.Sub(teamRegState.error403Start) > error403Window {
teamRegState.error403Count = 0
teamRegState.error403Start = now
}
teamRegState.error403Count++
// 如果超过阈值,自动停止
if teamRegState.error403Count >= max403Errors {
// 触发停止
if teamRegState.cancel != nil {
teamRegState.cancel()
}
if teamRegState.cmd != nil && teamRegState.cmd.Process != nil {
teamRegState.cmd.Process.Kill()
}
teamRegState.Running = false
// 不在锁内调用 addTeamRegLog先解锁
go func() {
addTeamRegLog(fmt.Sprintf("[警告] 检测到 %d 次 403 错误,自动停止注册", max403Errors))
addTeamRegLog("[提示] 可能是代理 IP 被限制,请更换代理后重试")
}()
return true
}
return false
}
// addTeamRegLog 添加日志
@@ -405,8 +469,14 @@ func addTeamRegLog(log string) {
teamRegState.mu.Lock()
defer teamRegState.mu.Unlock()
// 过滤 ANSI 颜色码
cleanLog := ansiRegex.ReplaceAllString(log, "")
if cleanLog == "" {
return
}
timestamp := time.Now().Format("15:04:05")
fullLog := fmt.Sprintf("[%s] %s", timestamp, log)
fullLog := fmt.Sprintf("[%s] %s", timestamp, cleanLog)
teamRegState.Logs = append(teamRegState.Logs, fullLog)
// 限制日志数量
@@ -415,7 +485,7 @@ func addTeamRegLog(log string) {
}
// 同时输出到系统日志
logger.Info(fmt.Sprintf("[TeamReg] %s", log), "", "team-reg")
logger.Info(fmt.Sprintf("[TeamReg] %s", cleanLog), "", "team-reg")
}
// findTeamRegExecutable 查找 team-reg 可执行文件