package register import ( "bytes" "encoding/json" "fmt" "math/rand" "net/http" "net/url" "strings" "time" "codex-pool/internal/client" "codex-pool/internal/mail" ) // ChatGPTReg ChatGPT 注册器 type ChatGPTReg struct { Proxy string Client *client.TLSClient AuthSessionLoggingID string OAIDid string CSRFToken string AuthorizeURL string AccessToken string } // Result 注册结果 type Result struct { Email string `json:"email"` Password string `json:"password"` Name string `json:"name"` AccessToken string `json:"access_token"` } // New 创建注册器 func New(proxy string) (*ChatGPTReg, error) { c, err := client.New(proxy) if err != nil { return nil, err } return &ChatGPTReg{ Proxy: proxy, Client: c, AuthSessionLoggingID: GenerateUUID(), }, nil } // InitSession 初始化会话 func (r *ChatGPTReg) InitSession() error { resp, err := r.Client.Get("https://chatgpt.com") if err != nil { return err } defer resp.Body.Close() if resp.StatusCode != 200 { return fmt.Errorf("初始化失败,状态码: %d", resp.StatusCode) } r.OAIDid = r.Client.GetCookie("https://chatgpt.com", "oai-did") csrfCookie := r.Client.GetCookie("https://chatgpt.com", "__Host-next-auth.csrf-token") if csrfCookie != "" { decoded, err := url.QueryUnescape(csrfCookie) if err == nil { parts := strings.Split(decoded, "|") if len(parts) > 0 { r.CSRFToken = parts[0] } } } if r.CSRFToken == "" { return fmt.Errorf("无法获取 CSRF token") } loginURL := fmt.Sprintf("https://chatgpt.com/auth/login?openaicom-did=%s", r.OAIDid) loginResp, err := r.Client.Get(loginURL) if err != nil { return err } defer loginResp.Body.Close() return nil } // GetAuthorizeURL 获取授权 URL func (r *ChatGPTReg) GetAuthorizeURL(email string) error { loginURL := fmt.Sprintf( "https://chatgpt.com/api/auth/signin/openai?prompt=login&ext-oai-did=%s&auth_session_logging_id=%s&screen_hint=login_or_signup&login_hint=%s", r.OAIDid, r.AuthSessionLoggingID, url.QueryEscape(email), ) data := url.Values{} data.Set("callbackUrl", "https://chatgpt.com/") data.Set("csrfToken", r.CSRFToken) data.Set("json", "true") req, err := http.NewRequest("POST", loginURL, strings.NewReader(data.Encode())) if err != nil { return err } req.Header.Set("Origin", "https://chatgpt.com") req.Header.Set("Content-Type", "application/x-www-form-urlencoded") resp, err := r.Client.Do(req) if err != nil { return err } defer resp.Body.Close() var result map[string]interface{} if err := json.NewDecoder(resp.Body).Decode(&result); err != nil { return err } if authURL, ok := result["url"].(string); ok && strings.Contains(authURL, "auth.openai.com") { r.AuthorizeURL = authURL return nil } return fmt.Errorf("无法获取授权 URL") } // StartAuthorize 开始授权流程 func (r *ChatGPTReg) StartAuthorize() error { resp, err := r.Client.Get(r.AuthorizeURL) if err != nil { return err } defer resp.Body.Close() finalURL := resp.Request.URL.String() if strings.Contains(finalURL, "create-account") || strings.Contains(finalURL, "log-in") { return nil } return fmt.Errorf("授权流程启动失败") } // Register 注册账户 func (r *ChatGPTReg) Register(email, password string) error { payload := map[string]string{ "password": password, "username": email, } jsonData, _ := json.Marshal(payload) req, err := http.NewRequest("POST", "https://auth.openai.com/api/accounts/user/register", bytes.NewReader(jsonData)) if err != nil { return err } req.Header.Set("Content-Type", "application/json") req.Header.Set("Origin", "https://auth.openai.com") resp, err := r.Client.Do(req) if err != nil { return err } defer resp.Body.Close() if resp.StatusCode != 200 { body, _ := client.ReadBodyString(resp) return fmt.Errorf("注册失败,状态码: %d, 响应: %s", resp.StatusCode, truncateStr(body, 200)) } return nil } // SendVerificationEmail 发送验证邮件 func (r *ChatGPTReg) SendVerificationEmail() error { resp, err := r.Client.Get("https://auth.openai.com/api/accounts/email-otp/send") if err != nil { return err } defer resp.Body.Close() if resp.StatusCode != 200 { return fmt.Errorf("发送验证邮件失败,状态码: %d", resp.StatusCode) } return nil } // ValidateOTP 验证 OTP func (r *ChatGPTReg) ValidateOTP(code string) error { payload := map[string]string{"code": code} jsonData, _ := json.Marshal(payload) req, err := http.NewRequest("POST", "https://auth.openai.com/api/accounts/email-otp/validate", bytes.NewReader(jsonData)) if err != nil { return err } req.Header.Set("Content-Type", "application/json") req.Header.Set("Origin", "https://auth.openai.com") resp, err := r.Client.Do(req) if err != nil { return err } defer resp.Body.Close() if resp.StatusCode != 200 { return fmt.Errorf("OTP 验证失败,状态码: %d", resp.StatusCode) } return nil } // CreateAccount 创建账户 func (r *ChatGPTReg) CreateAccount(name, birthdate string) error { payload := map[string]string{ "name": name, "birthdate": birthdate, } jsonData, _ := json.Marshal(payload) req, err := http.NewRequest("POST", "https://auth.openai.com/api/accounts/create_account", bytes.NewReader(jsonData)) if err != nil { return err } req.Header.Set("Content-Type", "application/json") req.Header.Set("Origin", "https://auth.openai.com") resp, err := r.Client.Do(req) if err != nil { return err } defer resp.Body.Close() if resp.StatusCode != 200 { return fmt.Errorf("创建账户失败,状态码: %d", resp.StatusCode) } var result map[string]interface{} if err := json.NewDecoder(resp.Body).Decode(&result); err == nil { if continueURL, ok := result["continue_url"].(string); ok && continueURL != "" { contResp, err := r.Client.Get(continueURL) if err == nil { contResp.Body.Close() } } } return nil } // GetSessionToken 获取 access token func (r *ChatGPTReg) GetSessionToken() error { resp, err := r.Client.Get("https://chatgpt.com/api/auth/session") if err != nil { return err } defer resp.Body.Close() if resp.StatusCode != 200 { return fmt.Errorf("获取 session 失败,状态码: %d", resp.StatusCode) } var result map[string]interface{} if err := json.NewDecoder(resp.Body).Decode(&result); err != nil { return err } if token, ok := result["accessToken"].(string); ok { r.AccessToken = token return nil } return fmt.Errorf("响应中没有 accessToken") } // Run 完整的注册流程 func Run(email, password, name, birthdate, proxy string) (*ChatGPTReg, error) { return RunWithRetry(email, password, name, birthdate, proxy, 3) } // RunWithRetry 带重试的注册流程 // 当验证码获取超过5秒,就换新邮箱重新注册 func RunWithRetry(email, password, name, birthdate, proxy string, maxRetries int) (*ChatGPTReg, error) { for attempt := 0; attempt < maxRetries; attempt++ { if attempt > 0 { // 重试时生成新邮箱 email = mail.GenerateEmail() password = GeneratePassword() fmt.Printf(" [Retry %d] New email: %s\n", attempt, email) } reg, err := runOnce(email, password, name, birthdate, proxy) if err == nil { return reg, nil } // 如果不是验证码超时错误,直接返回 if !strings.Contains(err.Error(), "验证码获取超时") { return nil, err } fmt.Printf(" [!] OTP timeout, retrying with new email...\n") } return nil, fmt.Errorf("注册失败: 已重试 %d 次", maxRetries) } // runOnce 执行一次注册流程(使用短超时获取验证码) func runOnce(email, password, name, birthdate, proxy string) (*ChatGPTReg, error) { reg, err := New(proxy) if err != nil { return nil, err } // 初始化 if err := reg.InitSession(); err != nil { return nil, fmt.Errorf("初始化失败: %v", err) } if err := reg.GetAuthorizeURL(email); err != nil { return nil, fmt.Errorf("获取授权URL失败: %v", err) } if err := reg.StartAuthorize(); err != nil { return nil, fmt.Errorf("启动授权失败: %v", err) } // 注册 if err := reg.Register(email, password); err != nil { return nil, fmt.Errorf("注册失败: %v", err) } if err := reg.SendVerificationEmail(); err != nil { return nil, fmt.Errorf("发送邮件失败: %v", err) } // 先用5秒超时尝试获取验证码 otpCode, err := mail.GetVerificationCode(email, 5*time.Second) if err != nil { // 5秒内没获取到,再等120秒(总共等待更多时间) otpCode, err = mail.GetVerificationCode(email, 120*time.Second) if err != nil { return nil, fmt.Errorf("验证码获取超时") } } if err := reg.ValidateOTP(otpCode); err != nil { return nil, fmt.Errorf("OTP验证失败: %v", err) } // 创建账户 if err := reg.CreateAccount(name, birthdate); err != nil { return nil, fmt.Errorf("创建账户失败: %v", err) } // 获取 Token _ = reg.GetSessionToken() return reg, nil } // ==================== 工具函数 ==================== // GenerateName 生成随机姓名 func GenerateName() string { firstNames := []string{"James", "John", "Robert", "Michael", "David", "William", "Richard", "Joseph", "Thomas", "Charles"} lastNames := []string{"Smith", "Johnson", "Williams", "Brown", "Jones", "Garcia", "Miller", "Davis", "Rodriguez", "Martinez"} return firstNames[rand.Intn(len(firstNames))] + " " + lastNames[rand.Intn(len(lastNames))] } // GenerateUUID 生成 UUID func GenerateUUID() string { b := make([]byte, 16) rand.Read(b) b[6] = (b[6] & 0x0f) | 0x40 b[8] = (b[8] & 0x3f) | 0x80 return fmt.Sprintf("%x-%x-%x-%x-%x", b[0:4], b[4:6], b[6:8], b[8:10], b[10:16]) } // GenerateBirthdate 生成随机生日 func GenerateBirthdate() string { year := 2000 + rand.Intn(5) month := 1 + rand.Intn(12) day := 1 + rand.Intn(28) return fmt.Sprintf("%d-%02d-%02d", year, month, day) } // GeneratePassword 生成随机密码 func GeneratePassword() string { const ( upper = "ABCDEFGHIJKLMNOPQRSTUVWXYZ" lower = "abcdefghijklmnopqrstuvwxyz" digits = "0123456789" special = "!@#$%" ) b := make([]byte, 13) for i := 0; i < 2; i++ { b[i] = upper[rand.Intn(len(upper))] } for i := 2; i < 10; i++ { b[i] = lower[rand.Intn(len(lower))] } for i := 10; i < 12; i++ { b[i] = digits[rand.Intn(len(digits))] } b[12] = special[rand.Intn(len(special))] return string(b) } func truncateStr(s string, maxLen int) string { if len(s) <= maxLen { return s } return s[:maxLen] + "..." }