feat: Add backend API for team registration execution.
This commit is contained in:
@@ -10,6 +10,7 @@ import (
|
|||||||
"os"
|
"os"
|
||||||
"os/exec"
|
"os/exec"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
|
"regexp"
|
||||||
"runtime"
|
"runtime"
|
||||||
"sort"
|
"sort"
|
||||||
"strings"
|
"strings"
|
||||||
@@ -20,6 +21,9 @@ import (
|
|||||||
"codex-pool/internal/logger"
|
"codex-pool/internal/logger"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// ansiRegex 匹配 ANSI 转义序列(颜色码等)
|
||||||
|
var ansiRegex = regexp.MustCompile(`\x1b\[[0-9;]*[a-zA-Z]`)
|
||||||
|
|
||||||
// TeamRegConfig 注册配置
|
// TeamRegConfig 注册配置
|
||||||
type TeamRegConfig struct {
|
type TeamRegConfig struct {
|
||||||
Count int `json:"count"` // 注册数量
|
Count int `json:"count"` // 注册数量
|
||||||
@@ -40,8 +44,17 @@ type TeamRegState struct {
|
|||||||
cmd *exec.Cmd
|
cmd *exec.Cmd
|
||||||
cancel context.CancelFunc
|
cancel context.CancelFunc
|
||||||
stdin io.WriteCloser
|
stdin io.WriteCloser
|
||||||
|
// 403 错误检测
|
||||||
|
error403Count int // 403 错误计数
|
||||||
|
error403Start time.Time // 计数开始时间
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 403 自动停止配置
|
||||||
|
const (
|
||||||
|
max403Errors = 10 // 最大 403 错误数
|
||||||
|
error403Window = 60 * time.Second // 时间窗口(60秒内)
|
||||||
|
)
|
||||||
|
|
||||||
var teamRegState = &TeamRegState{
|
var teamRegState = &TeamRegState{
|
||||||
Logs: make([]string, 0),
|
Logs: make([]string, 0),
|
||||||
}
|
}
|
||||||
@@ -91,6 +104,8 @@ func HandleTeamRegStart(w http.ResponseWriter, r *http.Request) {
|
|||||||
teamRegState.Logs = make([]string, 0)
|
teamRegState.Logs = make([]string, 0)
|
||||||
teamRegState.OutputFile = ""
|
teamRegState.OutputFile = ""
|
||||||
teamRegState.Imported = 0
|
teamRegState.Imported = 0
|
||||||
|
teamRegState.error403Count = 0
|
||||||
|
teamRegState.error403Start = time.Now()
|
||||||
teamRegState.mu.Unlock()
|
teamRegState.mu.Unlock()
|
||||||
|
|
||||||
// 启动进程
|
// 启动进程
|
||||||
@@ -110,9 +125,9 @@ func HandleTeamRegStop(w http.ResponseWriter, r *http.Request) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
teamRegState.mu.Lock()
|
teamRegState.mu.Lock()
|
||||||
defer teamRegState.mu.Unlock()
|
|
||||||
|
|
||||||
if !teamRegState.Running {
|
if !teamRegState.Running {
|
||||||
|
teamRegState.mu.Unlock()
|
||||||
json.NewEncoder(w).Encode(map[string]interface{}{
|
json.NewEncoder(w).Encode(map[string]interface{}{
|
||||||
"success": false,
|
"success": false,
|
||||||
"message": "没有正在运行的任务",
|
"message": "没有正在运行的任务",
|
||||||
@@ -120,7 +135,7 @@ func HandleTeamRegStop(w http.ResponseWriter, r *http.Request) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// 发送 Ctrl+C 信号
|
// 发送取消信号
|
||||||
if teamRegState.cancel != nil {
|
if teamRegState.cancel != nil {
|
||||||
teamRegState.cancel()
|
teamRegState.cancel()
|
||||||
}
|
}
|
||||||
@@ -131,6 +146,9 @@ func HandleTeamRegStop(w http.ResponseWriter, r *http.Request) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
teamRegState.Running = false
|
teamRegState.Running = false
|
||||||
|
teamRegState.mu.Unlock()
|
||||||
|
|
||||||
|
// 在释放锁之后再添加日志
|
||||||
addTeamRegLog("[系统] 任务已被用户停止")
|
addTeamRegLog("[系统] 任务已被用户停止")
|
||||||
|
|
||||||
json.NewEncoder(w).Encode(map[string]interface{}{
|
json.NewEncoder(w).Encode(map[string]interface{}{
|
||||||
@@ -396,8 +414,54 @@ func readOutput(reader io.Reader, workDir string, config TeamRegConfig) {
|
|||||||
trimmed := strings.TrimSpace(line)
|
trimmed := strings.TrimSpace(line)
|
||||||
if trimmed != "" {
|
if trimmed != "" {
|
||||||
addTeamRegLog(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 添加日志
|
// addTeamRegLog 添加日志
|
||||||
@@ -405,8 +469,14 @@ func addTeamRegLog(log string) {
|
|||||||
teamRegState.mu.Lock()
|
teamRegState.mu.Lock()
|
||||||
defer teamRegState.mu.Unlock()
|
defer teamRegState.mu.Unlock()
|
||||||
|
|
||||||
|
// 过滤 ANSI 颜色码
|
||||||
|
cleanLog := ansiRegex.ReplaceAllString(log, "")
|
||||||
|
if cleanLog == "" {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
timestamp := time.Now().Format("15:04:05")
|
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)
|
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 可执行文件
|
// findTeamRegExecutable 查找 team-reg 可执行文件
|
||||||
|
|||||||
Reference in New Issue
Block a user