mirror of
https://github.com/verssache/chatgpt-creator.git
synced 2026-05-17 06:09:42 +00:00
Initial commit: ChatGPT Account Registration Bot
This commit is contained in:
134
internal/register/batch.go
Normal file
134
internal/register/batch.go
Normal file
@@ -0,0 +1,134 @@
|
||||
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)
|
||||
}
|
||||
Reference in New Issue
Block a user