u
This commit is contained in:
138
auto_gpt_team.py
138
auto_gpt_team.py
@@ -606,6 +606,30 @@ def get_verification_content(target_email, max_retries=90):
|
||||
return None
|
||||
|
||||
|
||||
def _is_shutdown_requested():
|
||||
"""检查是否收到停止请求"""
|
||||
try:
|
||||
import run
|
||||
return run._shutdown_requested
|
||||
except Exception:
|
||||
return False
|
||||
|
||||
|
||||
def _is_connection_lost(error_msg):
|
||||
"""检查是否是连接断开错误(通常由 /stop 命令导致)"""
|
||||
disconnect_keywords = [
|
||||
"connection to the page has been disconnected",
|
||||
"page has been closed",
|
||||
"target closed",
|
||||
"session closed",
|
||||
"browser has disconnected",
|
||||
"no such window",
|
||||
"invalid session id"
|
||||
]
|
||||
error_lower = str(error_msg).lower()
|
||||
return any(kw in error_lower for kw in disconnect_keywords)
|
||||
|
||||
|
||||
def run_payment_flow(page, email, step_callback=None):
|
||||
"""执行 SEPA 支付流程 - 严格按顺序执行,任一步骤失败则终止
|
||||
|
||||
@@ -613,11 +637,21 @@ def run_payment_flow(page, email, step_callback=None):
|
||||
page: 浏览器页面对象
|
||||
email: 邮箱地址
|
||||
step_callback: 步骤回调函数 (step: str)
|
||||
|
||||
Returns:
|
||||
dict: 成功时返回 {"token": ..., "account_id": ...}
|
||||
被停止时返回 {"stopped": True}
|
||||
失败时返回 None
|
||||
"""
|
||||
def step_cb(step):
|
||||
if step_callback:
|
||||
step_callback(step)
|
||||
|
||||
# 检查停止请求
|
||||
if _is_shutdown_requested():
|
||||
log_progress("⚠ 检测到停止请求,中断支付流程")
|
||||
return {"stopped": True}
|
||||
|
||||
log_status("支付流程", "开始处理 Stripe 支付页...")
|
||||
|
||||
try:
|
||||
@@ -672,6 +706,11 @@ def run_payment_flow(page, email, step_callback=None):
|
||||
step_cb("填写支付邮箱...")
|
||||
log_progress("[步骤1] 填写邮箱...")
|
||||
try:
|
||||
# 检查停止请求
|
||||
if _is_shutdown_requested():
|
||||
log_progress("⚠ 检测到停止请求")
|
||||
return {"stopped": True}
|
||||
|
||||
# 如果之前已经找到了,直接使用;否则重新查找
|
||||
if not email_input:
|
||||
email_input = page.ele('#email', timeout=10)
|
||||
@@ -688,6 +727,10 @@ def run_payment_flow(page, email, step_callback=None):
|
||||
log_progress(f"✓ 已填写邮箱: {email}")
|
||||
time.sleep(1)
|
||||
except Exception as e:
|
||||
error_msg = str(e)
|
||||
if _is_connection_lost(error_msg) or _is_shutdown_requested():
|
||||
log_progress("⚠ 检测到停止请求,中断支付流程")
|
||||
return {"stopped": True}
|
||||
log_progress(f"❌ 邮箱填写失败: {e}")
|
||||
log_progress(f"当前URL: {page.url}")
|
||||
return None
|
||||
@@ -944,6 +987,11 @@ def run_payment_flow(page, email, step_callback=None):
|
||||
return None
|
||||
|
||||
except Exception as e:
|
||||
error_msg = str(e)
|
||||
# 检查是否是连接断开(由 /stop 命令导致)
|
||||
if _is_connection_lost(error_msg) or _is_shutdown_requested():
|
||||
log_status("停止", "⚠ 检测到停止请求,支付流程已中断")
|
||||
return {"stopped": True}
|
||||
log_status("错误", f"[X] 支付流程异常: {e}")
|
||||
return None
|
||||
|
||||
@@ -1138,22 +1186,29 @@ def run_main_process():
|
||||
# === 注册流程 ===
|
||||
log_status("步骤 1/5", "打开 ChatGPT 注册页...")
|
||||
page.get(TARGET_URL)
|
||||
log_progress(f"当前URL: {page.url}")
|
||||
|
||||
# 使用 data-testid 定位登录按钮
|
||||
login_btn = page.ele('@data-testid=login-button', timeout=30)
|
||||
if not login_btn:
|
||||
login_btn = page.ele('css:button[data-testid*="login"], a[href*="auth"]', timeout=10)
|
||||
login_btn.click()
|
||||
time.sleep(2)
|
||||
log_progress(f"当前URL: {page.url}")
|
||||
|
||||
log_progress("填入邮箱...")
|
||||
email_input = page.ele('@name=email', timeout=30)
|
||||
email_input.input(email)
|
||||
page.ele('xpath://button[@type="submit"]').click()
|
||||
time.sleep(2)
|
||||
log_progress(f"当前URL: {page.url}")
|
||||
|
||||
log_progress("填入密码...")
|
||||
password_input = page.ele('xpath://input[@type="password"]', timeout=30)
|
||||
password_input.input(password)
|
||||
page.ele('xpath://button[@type="submit"]').click()
|
||||
time.sleep(2)
|
||||
log_progress(f"当前URL: {page.url}")
|
||||
|
||||
log_status("步骤 2/5", "等待邮件 (All Mail)...")
|
||||
|
||||
@@ -1165,6 +1220,7 @@ def run_main_process():
|
||||
if verify_data['type'] == 'link':
|
||||
page.new_tab(verify_data['val'])
|
||||
time.sleep(5)
|
||||
log_progress(f"当前URL: {page.url}")
|
||||
elif verify_data['type'] == 'code':
|
||||
code = verify_data['val']
|
||||
log_progress(f"填入验证码: {code}")
|
||||
@@ -1181,11 +1237,14 @@ def run_main_process():
|
||||
continue_btn.click()
|
||||
except:
|
||||
log_progress("未找到按钮或已自动跳转...")
|
||||
time.sleep(2)
|
||||
log_progress(f"当前URL: {page.url}")
|
||||
except Exception as e:
|
||||
log_progress(f"验证码填入异常: {e}")
|
||||
|
||||
# === 资料填写 (姓名+生日) ===
|
||||
log_status("步骤 4/5", "进入信息填写页...")
|
||||
log_progress(f"当前URL: {page.url}")
|
||||
try:
|
||||
name_input = page.ele('@name=name', timeout=20)
|
||||
name_input.input(real_name)
|
||||
@@ -1206,6 +1265,8 @@ def run_main_process():
|
||||
# 点击继续/完成注册(使用 type=submit)
|
||||
final_reg_btn = page.ele('css:button[type="submit"]', timeout=20)
|
||||
final_reg_btn.click()
|
||||
time.sleep(2)
|
||||
log_progress(f"当前URL: {page.url}")
|
||||
|
||||
# =======================================================
|
||||
# 【关键节点】等待进入主页后再执行 JS 跳转到支付页
|
||||
@@ -1230,9 +1291,11 @@ def run_main_process():
|
||||
|
||||
if not entered_main:
|
||||
log_progress("⚠ 等待主页超时,尝试继续...")
|
||||
log_progress(f"当前URL: {page.url}")
|
||||
# 尝试直接访问主页
|
||||
page.get("https://chatgpt.com/")
|
||||
time.sleep(3)
|
||||
log_progress(f"跳转后URL: {page.url}")
|
||||
|
||||
# 额外等待页面稳定
|
||||
time.sleep(3)
|
||||
@@ -1296,13 +1359,16 @@ def run_main_process():
|
||||
|
||||
# 等待 JS 执行完成
|
||||
time.sleep(2)
|
||||
log_progress(f"当前URL: {page.url}")
|
||||
|
||||
# 等待跳转到支付页(使用 URL 检测代替固定等待)
|
||||
try:
|
||||
page.wait.url_change('pay.openai.com', timeout=15)
|
||||
log_progress("✓ 已跳转到支付页")
|
||||
log_progress(f"支付页URL: {page.url}")
|
||||
except:
|
||||
time.sleep(2) # 兜底等待
|
||||
time.sleep(2)
|
||||
log_progress(f"当前URL: {page.url}")
|
||||
|
||||
# 执行支付流程
|
||||
result = run_payment_flow(page, email)
|
||||
@@ -1439,29 +1505,75 @@ def run_single_registration(progress_callback=None, step_callback=None) -> dict:
|
||||
page = ChromiumPage(co)
|
||||
if RANDOM_FINGERPRINT:
|
||||
inject_fingerprint(page, fingerprint)
|
||||
except Exception as e:
|
||||
log_status("浏览器", f"启动失败: {e},尝试清理后重试...")
|
||||
cleanup_chrome_processes()
|
||||
time.sleep(2)
|
||||
|
||||
# 注册流程
|
||||
# 重新配置
|
||||
co2 = ChromiumOptions()
|
||||
co2.set_argument('--no-first-run')
|
||||
co2.set_argument('--disable-infobars')
|
||||
co2.set_argument('--incognito')
|
||||
co2.set_argument('--disable-gpu')
|
||||
co2.set_argument('--disable-dev-shm-usage')
|
||||
co2.set_argument('--no-sandbox')
|
||||
co2.set_argument('--disable-blink-features=AutomationControlled')
|
||||
co2.set_argument('--lang=zh-CN')
|
||||
co2.set_argument(f'--user-agent={fingerprint["user_agent"]}')
|
||||
co2.set_argument('--headless=new')
|
||||
co2.set_argument(f'--window-size={screen["width"]},{screen["height"]}')
|
||||
|
||||
if is_linux:
|
||||
co2.set_argument('--disable-software-rasterizer')
|
||||
co2.set_argument('--disable-extensions')
|
||||
co2.set_argument('--disable-setuid-sandbox')
|
||||
co2.set_argument('--single-process')
|
||||
co2.set_argument('--remote-debugging-port=0')
|
||||
for chrome_path in chrome_paths:
|
||||
if os.path.exists(chrome_path):
|
||||
co2.set_browser_path(chrome_path)
|
||||
break
|
||||
else:
|
||||
co2.auto_port(True)
|
||||
co2.set_local_port(random.randint(30000, 39999))
|
||||
|
||||
try:
|
||||
page = ChromiumPage(co2)
|
||||
if RANDOM_FINGERPRINT:
|
||||
inject_fingerprint(page, fingerprint)
|
||||
except Exception as e2:
|
||||
return {"success": False, "error": f"浏览器启动失败: {e2}", "account": email, "password": password}
|
||||
|
||||
try:
|
||||
step_cb("打开注册页面...")
|
||||
log_status("步骤 1/5", "打开 ChatGPT 注册页...")
|
||||
page.get(TARGET_URL)
|
||||
log_progress(f"当前URL: {page.url}")
|
||||
|
||||
step_cb("点击登录按钮...")
|
||||
login_btn = page.ele('@data-testid=login-button', timeout=30)
|
||||
if not login_btn:
|
||||
login_btn = page.ele('css:button[data-testid*="login"], a[href*="auth"]', timeout=10)
|
||||
login_btn.click()
|
||||
time.sleep(2)
|
||||
log_progress(f"当前URL: {page.url}")
|
||||
|
||||
step_cb("填写邮箱...")
|
||||
log_progress("填入邮箱...")
|
||||
email_input = page.ele('@name=email', timeout=30)
|
||||
email_input.input(email)
|
||||
page.ele('xpath://button[@type="submit"]').click()
|
||||
time.sleep(2)
|
||||
log_progress(f"当前URL: {page.url}")
|
||||
|
||||
step_cb("填写密码...")
|
||||
log_progress("填入密码...")
|
||||
password_input = page.ele('xpath://input[@type="password"]', timeout=30)
|
||||
password_input.input(password)
|
||||
page.ele('xpath://button[@type="submit"]').click()
|
||||
time.sleep(2)
|
||||
log_progress(f"当前URL: {page.url}")
|
||||
|
||||
step_cb("等待验证邮件...")
|
||||
log_status("步骤 2/5", "等待邮件 (All Mail)...")
|
||||
@@ -1475,6 +1587,7 @@ def run_single_registration(progress_callback=None, step_callback=None) -> dict:
|
||||
if verify_data['type'] == 'link':
|
||||
page.new_tab(verify_data['val'])
|
||||
time.sleep(5)
|
||||
log_progress(f"当前URL: {page.url}")
|
||||
elif verify_data['type'] == 'code':
|
||||
code = verify_data['val']
|
||||
log_progress(f"填入验证码: {code}")
|
||||
@@ -1488,10 +1601,13 @@ def run_single_registration(progress_callback=None, step_callback=None) -> dict:
|
||||
continue_btn.click()
|
||||
except:
|
||||
log_progress("未找到按钮或已自动跳转...")
|
||||
time.sleep(2)
|
||||
log_progress(f"当前URL: {page.url}")
|
||||
|
||||
# 资料填写
|
||||
step_cb("填写个人信息...")
|
||||
log_status("步骤 4/5", "进入信息填写页...")
|
||||
log_progress(f"当前URL: {page.url}")
|
||||
name_input = page.ele('@name=name', timeout=20)
|
||||
name_input.input(real_name)
|
||||
log_progress(f"姓名: {real_name}")
|
||||
@@ -1507,6 +1623,8 @@ def run_single_registration(progress_callback=None, step_callback=None) -> dict:
|
||||
time.sleep(1.5)
|
||||
final_reg_btn = page.ele('css:button[type="submit"]', timeout=20)
|
||||
final_reg_btn.click()
|
||||
time.sleep(2)
|
||||
log_progress(f"当前URL: {page.url}")
|
||||
|
||||
# 等待进入主页 - 改进检测逻辑
|
||||
step_cb("等待进入主页...")
|
||||
@@ -1530,9 +1648,11 @@ def run_single_registration(progress_callback=None, step_callback=None) -> dict:
|
||||
|
||||
if not entered_main:
|
||||
log_progress("⚠ 等待主页超时,尝试继续...")
|
||||
log_progress(f"当前URL: {page.url}")
|
||||
# 尝试直接访问主页
|
||||
page.get("https://chatgpt.com/")
|
||||
time.sleep(3)
|
||||
log_progress(f"跳转后URL: {page.url}")
|
||||
|
||||
# 额外等待页面稳定
|
||||
time.sleep(3)
|
||||
@@ -1576,18 +1696,25 @@ def run_single_registration(progress_callback=None, step_callback=None) -> dict:
|
||||
|
||||
# 等待 JS 执行完成
|
||||
time.sleep(2)
|
||||
log_progress(f"当前URL: {page.url}")
|
||||
|
||||
try:
|
||||
page.wait.url_change('pay.openai.com', timeout=15)
|
||||
log_progress("✓ 已跳转到支付页")
|
||||
log_progress(f"支付页URL: {page.url}")
|
||||
except:
|
||||
time.sleep(2)
|
||||
log_progress(f"当前URL: {page.url}")
|
||||
|
||||
# 执行支付流程
|
||||
step_cb("执行 SEPA 支付...")
|
||||
result = run_payment_flow(page, email, step_cb)
|
||||
|
||||
if result and result.get("token"):
|
||||
if result and result.get("stopped"):
|
||||
# 被 /stop 命令中断
|
||||
log_status("停止", "⚠ 注册被用户停止")
|
||||
return {"success": False, "error": "用户停止", "stopped": True, "account": email, "password": password}
|
||||
elif result and result.get("token"):
|
||||
step_cb("注册成功!")
|
||||
log_status("完成", "✓ 注册成功!")
|
||||
return {
|
||||
@@ -1602,6 +1729,11 @@ def run_single_registration(progress_callback=None, step_callback=None) -> dict:
|
||||
return {"success": False, "error": "支付流程失败", "account": email, "password": password}
|
||||
|
||||
except Exception as e:
|
||||
error_msg = str(e)
|
||||
# 检查是否是连接断开(由 /stop 命令导致)
|
||||
if _is_connection_lost(error_msg) or _is_shutdown_requested():
|
||||
log_status("停止", "⚠ 注册被用户停止")
|
||||
return {"success": False, "error": "用户停止", "stopped": True, "account": email, "password": password}
|
||||
log_status("错误", f"注册异常: {e}")
|
||||
return {"success": False, "error": str(e), "account": email, "password": password}
|
||||
finally:
|
||||
|
||||
@@ -2802,6 +2802,14 @@ class ProvisionerBot:
|
||||
|
||||
# 开始注册任务
|
||||
self.current_team = f"GPT Team 注册 ({count}个)"
|
||||
|
||||
# 重置停止标志,确保新任务可以正常运行
|
||||
try:
|
||||
import run
|
||||
run._shutdown_requested = False
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
self.current_task = asyncio.create_task(
|
||||
self._run_team_registration(query.message.chat_id, count, output_type)
|
||||
)
|
||||
@@ -2908,7 +2916,11 @@ class ProvisionerBot:
|
||||
run_with_callback
|
||||
)
|
||||
|
||||
if result.get("success"):
|
||||
if result.get("stopped"):
|
||||
# 被 /stop 命令中断,不计入失败
|
||||
log.info("注册被用户停止")
|
||||
break
|
||||
elif result.get("success"):
|
||||
success_count += 1
|
||||
results.append({
|
||||
"account": result["account"],
|
||||
|
||||
Reference in New Issue
Block a user