feat: add human-like pacing to signup and checkout requests

This commit is contained in:
gameloader
2026-03-18 22:46:40 +08:00
parent e3a28050df
commit 8ba8b1404b
4 changed files with 35 additions and 10 deletions

View File

@@ -104,6 +104,7 @@ class ChatGPTPayment:
else: else:
captcha_token = "" captcha_token = ""
print(" No captcha required") print(" No captcha required")
skip_captcha_followup_delay = bool(captcha_token)
# 4. Create Stripe payment method # 4. Create Stripe payment method
print("[4/6] Creating payment method...") print("[4/6] Creating payment method...")
@@ -162,6 +163,7 @@ class ChatGPTPayment:
"Origin": "https://js.stripe.com", "Origin": "https://js.stripe.com",
"Referer": "https://js.stripe.com/", "Referer": "https://js.stripe.com/",
}, },
skip_pacing=skip_captcha_followup_delay,
) )
if r.status_code != 200: if r.status_code != 200:
raise RuntimeError(f"Create payment method failed: {r.text}") raise RuntimeError(f"Create payment method failed: {r.text}")
@@ -212,6 +214,7 @@ class ChatGPTPayment:
"Origin": "https://js.stripe.com", "Origin": "https://js.stripe.com",
"Referer": "https://js.stripe.com/", "Referer": "https://js.stripe.com/",
}, },
skip_pacing=skip_captcha_followup_delay,
) )
if r.status_code != 200: if r.status_code != 200:
raise RuntimeError(f"Stripe confirm failed: {r.text}") raise RuntimeError(f"Stripe confirm failed: {r.text}")

View File

@@ -1,8 +1,6 @@
"""Pure HTTP registration experiment with detailed auth-state diagnostics.""" """Pure HTTP registration experiment with detailed auth-state diagnostics."""
import os import os
import random
import re import re
import time
import uuid import uuid
from typing import Optional from typing import Optional
from urllib.parse import unquote, urlencode, urljoin, urlparse from urllib.parse import unquote, urlencode, urljoin, urlparse
@@ -19,9 +17,6 @@ class ChatGPTRegisterHTTPReverse:
self.auth_base = "https://auth.openai.com" self.auth_base = "https://auth.openai.com"
self.root_dir = os.path.dirname(os.path.dirname(__file__)) self.root_dir = os.path.dirname(os.path.dirname(__file__))
def _delay(self, lo=0.5, hi=1.5):
time.sleep(random.uniform(lo, hi))
def _cookie_rows(self) -> list[tuple[str, str, str]]: def _cookie_rows(self) -> list[tuple[str, str, str]]:
rows = [] rows = []
for cookie in self.http.session.cookies.jar: for cookie in self.http.session.cookies.jar:
@@ -345,16 +340,12 @@ class ChatGPTRegisterHTTPReverse:
mailbox = self.mail.create_mailbox() mailbox = self.mail.create_mailbox()
email = mailbox["address"] email = mailbox["address"]
print(f" Email: {email}") print(f" Email: {email}")
self._delay()
csrf_token = self._bootstrap_chatgpt() csrf_token = self._bootstrap_chatgpt()
self._delay()
auth_url = self._signin_auth0(email, csrf_token) auth_url = self._signin_auth0(email, csrf_token)
self._delay()
auth_page_url = self._follow_auth_redirects(auth_url) auth_page_url = self._follow_auth_redirects(auth_url)
self._delay()
accounts_api_base = self._accounts_api_base(auth_url) accounts_api_base = self._accounts_api_base(auth_url)
register_url = self._register_endpoint(auth_url) register_url = self._register_endpoint(auth_url)

View File

@@ -1,3 +1,5 @@
import random
import time
import uuid import uuid
from curl_cffi import requests as curl_requests from curl_cffi import requests as curl_requests
@@ -16,6 +18,10 @@ class HTTPClient:
"sec-ch-ua-platform": '"macOS"', "sec-ch-ua-platform": '"macOS"',
}) })
self.device_id = str(uuid.uuid4()) self.device_id = str(uuid.uuid4())
self._pacing_enabled = False
self._pacing_min_delay = 0.5
self._pacing_max_delay = 2.0
self._has_completed_request = False
@staticmethod @staticmethod
def _proxy_candidates(proxy: str) -> list[str]: def _proxy_candidates(proxy: str) -> list[str]:
@@ -42,12 +48,16 @@ class HTTPClient:
return ordered return ordered
def request(self, method: str, url: str, **kwargs): def request(self, method: str, url: str, **kwargs):
skip_pacing = kwargs.pop("skip_pacing", False)
kwargs.setdefault("timeout", 30) kwargs.setdefault("timeout", 30)
kwargs.setdefault("allow_redirects", False) kwargs.setdefault("allow_redirects", False)
# This environment/proxy setup does not expose a usable CA bundle to curl_cffi. # This environment/proxy setup does not expose a usable CA bundle to curl_cffi.
kwargs.setdefault("verify", False) kwargs.setdefault("verify", False)
self._maybe_delay_before_request(skip_pacing=skip_pacing)
if not self.proxy_candidates: if not self.proxy_candidates:
return self.session.request(method, url, **kwargs) response = self.session.request(method, url, **kwargs)
self._has_completed_request = True
return response
last_exc = None last_exc = None
for index, proxy in enumerate(self.proxy_candidates): for index, proxy in enumerate(self.proxy_candidates):
@@ -58,6 +68,7 @@ class HTTPClient:
print(f" Retrying HTTP request with proxy scheme fallback: {proxy.split('://', 1)[0]}") print(f" Retrying HTTP request with proxy scheme fallback: {proxy.split('://', 1)[0]}")
response = self.session.request(method, url, **request_kwargs) response = self.session.request(method, url, **request_kwargs)
self.proxy = proxy self.proxy = proxy
self._has_completed_request = True
return response return response
except Exception as exc: except Exception as exc:
last_exc = exc last_exc = exc
@@ -65,5 +76,24 @@ class HTTPClient:
raise raise
raise last_exc raise last_exc
def enable_pacing(self, min_delay: float = 0.5, max_delay: float = 2.0):
if min_delay < 0 or max_delay < min_delay:
raise ValueError("Invalid pacing delay range")
self._pacing_enabled = True
self._pacing_min_delay = min_delay
self._pacing_max_delay = max_delay
self._has_completed_request = False
def disable_pacing(self):
self._pacing_enabled = False
self._has_completed_request = False
def _maybe_delay_before_request(self, skip_pacing: bool = False):
if skip_pacing or not self._pacing_enabled or not self._has_completed_request:
return
delay = random.uniform(self._pacing_min_delay, self._pacing_max_delay)
print(f" Human pacing delay: sleeping {delay:.2f}s before next request...")
time.sleep(delay)
def close(self): def close(self):
self.session.close() self.session.close()

View File

@@ -40,6 +40,7 @@ def cmd_register(args):
mail = MailClient() mail = MailClient()
http = HTTPClient(proxy=settings.socks5_proxy) http = HTTPClient(proxy=settings.socks5_proxy)
http.enable_pacing(min_delay=0.5, max_delay=2.0)
try: try:
print("\n=== ChatGPT Registration ===") print("\n=== ChatGPT Registration ===")