feat: add human-like pacing to signup and checkout requests
This commit is contained in:
@@ -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}")
|
||||||
|
|||||||
@@ -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)
|
||||||
|
|||||||
@@ -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()
|
||||||
|
|||||||
@@ -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 ===")
|
||||||
|
|||||||
Reference in New Issue
Block a user