feat: Introduce advanced TLS client with browser fingerprinting and new backend modules for API processing, authentication, mail, and ChatGPT registration.

This commit is contained in:
2026-02-06 18:49:55 +08:00
parent 4ac7290e1f
commit 98ac10987c
5 changed files with 130 additions and 32 deletions

View File

@@ -67,6 +67,18 @@ type TeamProcessState struct {
var teamProcessState = &TeamProcessState{}
// waitGroupWithTimeout 带超时的 WaitGroup 等待,超时返回 false
func waitGroupWithTimeout(wg *sync.WaitGroup, timeout time.Duration) bool {
done := make(chan struct{})
go func() { wg.Wait(); close(done) }()
select {
case <-done:
return true
case <-time.After(timeout):
return false
}
}
// getProxyDisplay 获取代理显示名称(隐藏密码)
func getProxyDisplay(proxy string) string {
if proxy == "" {
@@ -648,8 +660,17 @@ func processSingleTeam(idx int, req TeamProcessRequest) (result TeamProcessResul
memberLogPrefix := fmt.Sprintf("%s [Member %d]", logPrefix, memberIdx+1)
memberStartTime := time.Now()
// 获取入库信号量
s2aSem <- struct{}{}
// 获取入库信号量3分钟超时
select {
case s2aSem <- struct{}{}:
case <-time.After(3 * time.Minute):
logger.Warning(fmt.Sprintf("%s 入库信号量等待超时 (3分钟)", memberLogPrefix), memberEmail, "team")
atomic.AddInt32(&s2aFailCount, 1)
memberMu.Lock()
result.Errors = append(result.Errors, fmt.Sprintf("成员 %d 入库信号量超时", memberIdx+1))
memberMu.Unlock()
return false
}
defer func() { <-s2aSem }()
// 从代理池获取随机代理(默认轮询使用代理池,无代理则直连)
@@ -764,23 +785,29 @@ func processSingleTeam(idx int, req TeamProcessRequest) (result TeamProcessResul
currentEmail := email
currentPassword := password
if attempt > 0 {
// 重试时使用新邮箱
currentEmail = mail.GenerateEmail()
currentPassword = register.GeneratePassword()
logger.Warning(fmt.Sprintf("%s 重试 (第%d次), 新邮箱: %s", memberLogPrefix, attempt+1, currentEmail), currentEmail, "team")
// 注册失败重试:保持原邮箱(邀请已发送),仅重新注册
logger.Warning(fmt.Sprintf("%s 注册重试 (第%d次), 保持邮箱: %s", memberLogPrefix, attempt+1, currentEmail), currentEmail, "team")
}
// 发送邀请
if err := inviter.SendInvites([]string{currentEmail}); err != nil {
errStr := err.Error()
logger.Error(fmt.Sprintf("%s 邀请失败: %v", memberLogPrefix, err), currentEmail, "team")
// 首次尝试时发送邀请,重试时跳过(邀请已发送到该邮箱)
if attempt == 0 {
if err := inviter.SendInvites([]string{currentEmail}); err != nil {
errStr := err.Error()
logger.Error(fmt.Sprintf("%s 邀请失败: %v", memberLogPrefix, err), currentEmail, "team")
// 检测 Team 已达邀请上限401 或 maximum number of seats
if strings.Contains(errStr, "401") || strings.Contains(errStr, "maximum number of seats") {
markTeamExhausted()
return false
// 检测 Team 已达邀请上限401 或 maximum number of seats
if strings.Contains(errStr, "401") || strings.Contains(errStr, "maximum number of seats") {
markTeamExhausted()
return false
}
// 邀请失败时换新邮箱重试
email = mail.GenerateEmail()
password = register.GeneratePassword()
currentEmail = email
currentPassword = password
logger.Warning(fmt.Sprintf("%s 邀请失败,换新邮箱: %s", memberLogPrefix, currentEmail), currentEmail, "team")
continue
}
continue
}
// 再次检查是否应该停止(邀请期间其他 goroutine 可能已标记)
@@ -841,11 +868,15 @@ func processSingleTeam(idx int, req TeamProcessRequest) (result TeamProcessResul
registerAndS2AMember(idx, email, password)
}(i)
}
regWg.Wait()
if !waitGroupWithTimeout(&regWg, 8*time.Minute) {
logger.Warning(fmt.Sprintf("%s 注册阶段超时 (8分钟),继续处理已完成的成员", logPrefix), owner.Email, "team")
}
// 如果 Team 已满,等待已启动的入库完成
if isTeamExhausted() {
s2aWg.Wait()
if !waitGroupWithTimeout(&s2aWg, 5*time.Minute) {
logger.Warning(fmt.Sprintf("%s 入库等待超时 (5分钟)", logPrefix), owner.Email, "team")
}
result.AddedToS2A = int(atomic.LoadInt32(&s2aSuccessCount))
result.Errors = append(result.Errors, "Team 邀请已满")
result.DurationMs = time.Since(startTime).Milliseconds()
@@ -874,7 +905,9 @@ func processSingleTeam(idx int, req TeamProcessRequest) (result TeamProcessResul
}
// 等待所有入库完成
s2aWg.Wait()
if !waitGroupWithTimeout(&s2aWg, 10*time.Minute) {
logger.Warning(fmt.Sprintf("%s 入库阶段超时 (10分钟),继续统计结果", logPrefix), owner.Email, "team")
}
// 补救后再次检查 Team 是否已满
if isTeamExhausted() {