Files
AutoDoneTeam/modules/register.py
2026-01-09 15:46:40 +08:00

243 lines
8.3 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# modules/registrar.py (更新版)
"""OpenAI 注册流程控制器"""
import json
from typing import Dict, Optional
import secrets
from .fingerprint import BrowserFingerprint
from .sentinel_solver import SentinelSolver
from .http_client import HTTPClient
from config import AUTH_BASE_URL, DEBUG
class OpenAIRegistrar:
"""完整的 OpenAI 注册流程"""
def __init__(self, session_id: Optional[str] = None):
self.fingerprint = BrowserFingerprint(session_id)
self.solver = SentinelSolver(self.fingerprint)
self.http_client = HTTPClient(self.fingerprint)
def _step1_get_cookies_and_csrf(self):
"""访问注册页,获取必需的 session cookies"""
if DEBUG:
print("\n=== STEP 1: Getting session cookies ===")
# 访问注册页(会设置 login_session 等 cookies
url = f"{AUTH_BASE_URL}/create-account/password"
headers = self.http_client.fingerprint.get_headers()
headers['Accept'] = 'text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8'
resp = self.http_client.get(url, headers=headers)
if DEBUG:
print(f"Cookies received: {list(self.http_client.cookies.keys())}")
# 检查关键 cookies
required_cookies = ['oai-did', 'login_session', 'oai-client-auth-session']
missing = [c for c in required_cookies if c not in self.http_client.cookies]
if missing:
print(f"⚠ Warning: Missing cookies: {missing}")
else:
print(f"✓ All required cookies present")
def _step2_init_sentinel(self):
"""初始化 Sentinel生成 token"""
if DEBUG:
print("\n=== STEP 2: Initializing Sentinel ===")
try:
token_data = self.solver.generate_requirements_token()
self.sentinel_token = json.dumps(token_data)
if DEBUG:
token_str = str(self.sentinel_token)
print(f"✓ Sentinel token: {token_str[:80]}...")
except Exception as e:
if DEBUG:
print(f"✗ Sentinel initialization failed: {e}")
raise
def _step3_attempt_register(self, email: str, password: str) -> Dict:
"""尝试注册(会触发 enforcement"""
if DEBUG:
print("\n=== STEP 3: Attempting registration ===")
url = f"{AUTH_BASE_URL}/api/accounts/user/register"
# 正确的 payload 格式(根据真实抓包)
payload = {
'username': email,
'password': password
}
# 添加额外的 headers
headers = self.http_client.fingerprint.get_headers(with_sentinel=self.sentinel_token)
headers['Accept'] = 'application/json'
headers['Referer'] = f'{AUTH_BASE_URL}/create-account/password'
headers['Origin'] = AUTH_BASE_URL
# 添加 Datadog tracing headers模拟真实浏览器
headers.update({
'traceparent': f'00-0000000000000000{secrets.token_hex(8)}-{secrets.token_hex(8)}-01',
'tracestate': 'dd=s:1;o:rum',
'x-datadog-origin': 'rum',
'x-datadog-parent-id': str(secrets.randbits(63)),
'x-datadog-sampling-priority': '1',
'x-datadog-trace-id': str(secrets.randbits(63))
})
resp = self.http_client.session.post(
url,
json=payload,
headers=headers,
cookies=self.http_client.cookies,
)
if DEBUG:
print(f"Response status: {resp.status_code}")
# 更新 cookies
self.http_client.cookies.update(resp.cookies.get_dict())
# 403: Enforcement 挑战(预期)
if resp.status_code == 403:
try:
challenge = resp.json()
if DEBUG:
print(f"✓ Got enforcement challenge!")
print(f" Type: {challenge.get('type', 'unknown')}")
if 'proofofwork' in challenge:
pow_data = challenge['proofofwork']
print(f" PoW seed: {pow_data.get('seed', 'N/A')}")
print(f" Difficulty: {pow_data.get('difficulty', 'N/A')}")
return challenge
except Exception as e:
if DEBUG:
print(f"✗ Failed to parse challenge: {e}")
print(resp.text[:500])
raise
# 200: 成功
elif resp.status_code == 200:
if DEBUG:
print("✓ Registration succeeded!")
return {'success': True, 'data': resp.json()}
# 409: Invalid session
elif resp.status_code == 409:
error = resp.json()
if DEBUG:
print(f"✗ 409: {error}")
raise Exception(f"Invalid session: {error}")
# 400: 参数错误
elif resp.status_code == 400:
error = resp.json()
if DEBUG:
print(f"✗ 400: {error}")
raise Exception(f"Bad request: {error}")
# 其他错误
else:
if DEBUG:
print(f"✗ Unexpected status: {resp.status_code}")
print(resp.text[:500])
raise Exception(f"Unexpected status: {resp.status_code}\n{resp.text}")
def _step4_solve_challenge(self, challenge: Dict) -> str:
"""解决 enforcement 挑战"""
if DEBUG:
print("\n=== STEP 4: Solving enforcement challenge ===")
sentinel_token = self.solver.solve_enforcement(challenge)
return sentinel_token
def _step5_register_with_token(self, email: str, password: str,
sentinel_token: str) -> Dict:
"""带 Sentinel token 重新注册"""
if DEBUG:
print("\n=== STEP 5: Registering with Sentinel token ===")
url = f"{AUTH_BASE_URL}/api/accounts/user/register"
payload = {
'username': email,
'password': password,
'client_id': 'sentinel'
}
resp = self.http_client.post(
url,
json_data=payload,
sentinel_token=sentinel_token
)
if resp.status_code == 200:
if DEBUG:
print("✓ Registration successful!")
return {'success': True, 'data': resp.json()}
else:
if DEBUG:
print(f"✗ Registration failed: {resp.status_code}")
print(resp.text)
return {
'success': False,
'status_code': resp.status_code,
'error': resp.text
}
def register(self, email: str, password: str) -> Dict:
"""完整注册流程"""
if DEBUG:
print(f"\n{'='*60}")
print(f"Registering: {email}")
print(f"Session ID: {self.fingerprint.session_id}")
print(f"{'='*60}")
try:
# Step 1: 获取 cookies 和 CSRF token
self._step1_get_cookies_and_csrf()
# Step 2: 初始化 Sentinel跳过
self._step2_init_sentinel()
# Step 3: 尝试注册(获取挑战)
challenge = self._step3_attempt_register(email, password)
# 如果直接成功了
if challenge.get('success'):
return challenge
# Step 4: 解决挑战
sentinel_token = self._step4_solve_challenge(challenge)
# Step 5: 带 token 重新注册
result = self._step5_register_with_token(email, password, sentinel_token)
return result
except Exception as e:
if DEBUG:
import traceback
print(f"\n✗ Registration failed with exception:")
traceback.print_exc()
return {
'success': False,
'error': str(e)
}