mirror of
https://github.com/verssache/chatgpt-creator.git
synced 2026-05-16 21:59:33 +00:00
135 lines
3.7 KiB
Go
135 lines
3.7 KiB
Go
package register
|
|
|
|
import (
|
|
"fmt"
|
|
"os"
|
|
"sync"
|
|
"sync/atomic"
|
|
"time"
|
|
|
|
"github.com/verssache/chatgpt-creator/internal/email"
|
|
"github.com/verssache/chatgpt-creator/internal/util"
|
|
)
|
|
|
|
// registerOne handles a single account registration.
|
|
func registerOne(workerID int, tag string, proxy, outputFile, defaultPassword, defaultDomain string, printMu, fileMu *sync.Mutex) (bool, string, string) {
|
|
client, err := NewClient(proxy, tag, workerID, printMu, fileMu)
|
|
if err != nil {
|
|
return false, "", fmt.Sprintf("failed to create client: %v", err)
|
|
}
|
|
|
|
emailAddr, err := email.CreateTempEmail(defaultDomain)
|
|
if err != nil {
|
|
return false, "", fmt.Sprintf("failed to create temp email: %v", err)
|
|
}
|
|
|
|
password := defaultPassword
|
|
if password == "" {
|
|
password = util.GeneratePassword(14)
|
|
}
|
|
|
|
firstName, lastName := util.RandomName()
|
|
birthdate := util.RandomBirthdate()
|
|
|
|
client.print(fmt.Sprintf("Starting registration for %s", emailAddr))
|
|
|
|
err = client.RunRegister(emailAddr, password, firstName+" "+lastName, birthdate)
|
|
if err != nil {
|
|
return false, emailAddr, err.Error()
|
|
}
|
|
|
|
// Append to file
|
|
fileMu.Lock()
|
|
defer fileMu.Unlock()
|
|
|
|
f, err := os.OpenFile(outputFile, os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0644)
|
|
if err != nil {
|
|
return false, emailAddr, fmt.Sprintf("failed to open output file: %v", err)
|
|
}
|
|
defer f.Close()
|
|
|
|
line := fmt.Sprintf("%s|%s\n", emailAddr, password)
|
|
if _, err := f.WriteString(line); err != nil {
|
|
return false, emailAddr, fmt.Sprintf("failed to write to output file: %v", err)
|
|
}
|
|
|
|
return true, emailAddr, ""
|
|
}
|
|
|
|
// RunBatch runs concurrent registration tasks with retry until target success count is reached.
|
|
func RunBatch(totalAccounts int, outputFile string, maxWorkers int, proxy, defaultPassword, defaultDomain string) {
|
|
var printMu sync.Mutex
|
|
var fileMu sync.Mutex
|
|
|
|
var remaining int64 = int64(totalAccounts)
|
|
var successCount int64
|
|
var failureCount int64
|
|
var attemptNum int64
|
|
|
|
startTime := time.Now()
|
|
|
|
var wg sync.WaitGroup
|
|
|
|
for w := 1; w <= maxWorkers; w++ {
|
|
wg.Add(1)
|
|
go func(workerID int) {
|
|
defer wg.Done()
|
|
for {
|
|
// Claim a slot before starting work
|
|
if atomic.AddInt64(&remaining, -1) < 0 {
|
|
// No more slots needed, put it back and exit
|
|
atomic.AddInt64(&remaining, 1)
|
|
return
|
|
}
|
|
|
|
attempt := atomic.AddInt64(&attemptNum, 1)
|
|
tag := fmt.Sprintf("%d/%d", attempt, totalAccounts)
|
|
|
|
success, emailAddr, errStr := registerOne(workerID, tag, proxy, outputFile, defaultPassword, defaultDomain, &printMu, &fileMu)
|
|
if success {
|
|
atomic.AddInt64(&successCount, 1)
|
|
ts := time.Now().Format("15:04:05")
|
|
printMu.Lock()
|
|
fmt.Printf("[%s] [W%d] ✓ SUCCESS: %s\n", ts, workerID, emailAddr)
|
|
printMu.Unlock()
|
|
} else {
|
|
atomic.AddInt64(&failureCount, 1)
|
|
// Failed — return the slot so it gets retried
|
|
atomic.AddInt64(&remaining, 1)
|
|
ts := time.Now().Format("15:04:05")
|
|
printMu.Lock()
|
|
fmt.Printf("[%s] [W%d] ✗ FAILURE: %s | %s\n", ts, workerID, emailAddr, errStr)
|
|
printMu.Unlock()
|
|
}
|
|
}
|
|
}(w)
|
|
}
|
|
|
|
wg.Wait()
|
|
|
|
elapsed := time.Since(startTime)
|
|
elapsedStr := formatDuration(elapsed)
|
|
|
|
fmt.Printf("\n--- Batch Registration Summary ---\n")
|
|
fmt.Printf("Target: %d\n", totalAccounts)
|
|
fmt.Printf("Success: %d\n", successCount)
|
|
fmt.Printf("Attempts: %d\n", attemptNum)
|
|
fmt.Printf("Failures: %d\n", failureCount)
|
|
fmt.Printf("Elapsed: %s\n", elapsedStr)
|
|
fmt.Printf("----------------------------------\n")
|
|
}
|
|
|
|
func formatDuration(d time.Duration) string {
|
|
h := int(d.Hours())
|
|
m := int(d.Minutes()) % 60
|
|
s := int(d.Seconds()) % 60
|
|
|
|
if h > 0 {
|
|
return fmt.Sprintf("%dh %dm %ds", h, m, s)
|
|
}
|
|
if m > 0 {
|
|
return fmt.Sprintf("%dm %ds", m, s)
|
|
}
|
|
return fmt.Sprintf("%ds", s)
|
|
}
|