Files
grok-keygen/openai_register.py
T
chaos 2302e74209 feat: xAI Grok auto-registration tool
- DrissionPage + Chrome browser automation
- Temporary email via mail.tm API
- Verification code auto-extraction
- Turnstile CAPTCHA bypass via extension
- SSO cookie extraction and persistence
2026-06-16 07:12:51 +08:00

161 lines
5.9 KiB
Python

import requests
import re
import time
import secrets
import string
BASE_URL = "https://api.mail.tm"
def _random_string(length=12):
return "".join(secrets.choice(string.ascii_lowercase + string.digits) for _ in range(length))
def get_email_and_token():
try:
# 1. 获取可用域名
r = requests.get(f"{BASE_URL}/domains", timeout=30)
r.raise_for_status()
domains = r.json().get("hydra:member", [])
if not domains:
print("[Error] Mail.tm 没有可用域名")
return None, None
domain = domains[0]["domain"]
# 2. 生成随机邮箱和密码
local_part = _random_string(10)
email = f"{local_part}@{domain}"
password = _random_string(16)
# 3. 创建账户
r = requests.post(
f"{BASE_URL}/accounts",
json={"address": email, "password": password},
timeout=30,
)
r.raise_for_status()
# 4. 获取 token
r = requests.post(
f"{BASE_URL}/token",
json={"address": email, "password": password},
timeout=30,
)
r.raise_for_status()
token = r.json().get("token")
if not token:
print("[Error] 无法获取 Mail.tm token")
return None, None
print(f"[*] 已获取临时邮箱: {email}")
return email, token
except Exception as e:
print(f"[Error] 获取邮箱失败: {e}")
return None, None
def _extract_code(subject, text, html_text=""):
"""从邮件文本中提取验证码。优先匹配 xAI/常见服务的验证码格式。"""
text = text or ""
html_text = html_text or ""
subject = subject or ""
full_text = f"{subject}\n{text}\n{html_text}"
# 1. xAI 主题自带验证码格式: EB5-XJA xAI confirmation code
m = re.search(r"\b([A-Z0-9]{3}-[A-Z0-9]{3})\b.*confirmation\s*code", subject, re.IGNORECASE)
if m:
return m.group(1).upper()
# 2. 通用 xAI/OpenAI 验证码格式(字母数字混合)
patterns = [
# xAI 正文: code below to validate ... EB5-XJA
r"code\s+below\s+to\s+validate.*?\n\s*([A-Z0-9]{3}-[A-Z0-9]{3})\s*\n",
# 通用字母数字验证码: ABC-123, 123-ABC, A1B-2C3
r"\b([A-Z0-9]{3}-[A-Z0-9]{3})\b",
# verification code is 123456
r"(?:verification\s*code|code\s*is)[:\s]+(\d{6})",
# 中文验证码
r"(?:验证码|代码|确认码)[:\s为]+(\d{6})",
# code: 123456
r"(?:code|验证码)[:\s]+(\d{6})",
# 6位数字带上下文
r"\b(\d{6})\b(?:\s*(?:is your|作为您的)\s*(?:verification\s*code|code|验证码))?",
]
for pat in patterns:
m = re.search(pat, full_text, re.IGNORECASE | re.DOTALL)
if m:
code = m.group(1)
if code:
return code.upper() if "-" in code else code
# 3. 兜底:仅在纯文本中匹配 6 位数字,避开 HTML 颜色代码
if text:
for m in re.finditer(r"(?<!#)\b(\d{6})\b", text):
code = m.group(1)
if not code.startswith("20"):
return code
return None
def _is_verification_email(subject, sender):
"""判断是否为验证码邮件。"""
keywords = ["verification", "code", "验证码", "确认码", "xai", "x.ai", "openai", "grok"]
text = f"{subject} {sender}".lower()
return any(k in text for k in keywords)
def get_oai_code(token, email):
try:
headers = {"Authorization": f"Bearer {token}"}
deadline = time.time() + 180 # 最多轮询 180 秒
while time.time() < deadline:
r = requests.get(f"{BASE_URL}/messages", headers=headers, timeout=30)
r.raise_for_status()
messages = r.json().get("hydra:member", [])
# 按创建时间倒序,优先处理最新邮件
messages.sort(key=lambda m: m.get("createdAt", ""), reverse=True)
# 优先检查看起来像验证码的邮件
verification_msgs = [m for m in messages if _is_verification_email(m.get("subject", ""), "")]
other_msgs = [m for m in messages if m not in verification_msgs]
ordered_msgs = verification_msgs + other_msgs
for msg in ordered_msgs:
msg_id = msg.get("id")
if not msg_id:
continue
# 获取邮件详情
r = requests.get(f"{BASE_URL}/messages/{msg_id}", headers=headers, timeout=30)
r.raise_for_status()
detail = r.json()
subject = detail.get("subject", "")
text = detail.get("text", "")
html = detail.get("html", [])
html_content = " ".join(html) if isinstance(html, list) else str(html)
sender = detail.get("from", {}).get("address", "")
code = _extract_code(subject, text, html_content)
if code:
# xAI 验证码为 WVB-8OE 格式,OTP 输入框通常只需 6 位字母数字,去掉连字符
if "-" in code:
code = code.replace("-", "")
print(f"[*] 获取到验证码: {code}")
# 标记为已读,避免重复提取
try:
requests.patch(f"{BASE_URL}/messages/{msg_id}", headers={**headers, "Content-Type": "application/merge-patch+json"}, json={"seen": True}, timeout=10)
except Exception:
pass
return code
time.sleep(3)
print("[Error] 轮询超时,未获取到验证码")
return None
except Exception as e:
print(f"[Error] 获取验证码失败: {e}")
return None