diff --git a/api_register.py b/api_register.py index 541b5c8..caff264 100644 --- a/api_register.py +++ b/api_register.py @@ -28,7 +28,7 @@ def log_status(step, message): def log_progress(message): """进度输出""" - print(f" -> {message}") + print(f" {message}") def request_with_retry(func, *args, max_retries=3, **kwargs): @@ -393,7 +393,8 @@ def api_register_flow( def log_cb(msg): if progress_callback: progress_callback(msg) - log_progress(msg) + else: + log_progress(msg) reg = ChatGPTAPIRegister(proxy=proxy) @@ -480,7 +481,8 @@ def api_login_flow( def log_cb(msg): if progress_callback: progress_callback(msg) - log_progress(msg) + else: + log_progress(msg) reg = ChatGPTAPIRegister(proxy=proxy) @@ -552,7 +554,8 @@ def api_register_account_only( def log_cb(msg): if progress_callback: progress_callback(msg) - log_progress(msg) + else: + log_progress(msg) if not CURL_CFFI_AVAILABLE: log_status("错误", "协议模式不可用,请安装 curl_cffi") diff --git a/auto_gpt_team.py b/auto_gpt_team.py index 9aeee9f..c6eb919 100644 --- a/auto_gpt_team.py +++ b/auto_gpt_team.py @@ -536,7 +536,7 @@ def _input_birthday_precise(page, birth_year: str, birth_month: str, birth_day: day_input = page.ele('css:[data-type="day"]', timeout=3) if not all([year_input, month_input, day_input]): - log_progress("⚠ 未找到完整的生日输入框 (data-type),尝试备用方案...") + log_progress("[!] 未找到完整的生日输入框 (data-type),尝试备用方案...") return False # 检测页面语言 @@ -563,14 +563,14 @@ def _input_birthday_precise(page, birth_year: str, birth_month: str, birth_day: input_elem.input(value, clear=True) time.sleep(0.2) except Exception as e: - log_progress(f"⚠ 生日字段输入异常: {e}") + log_progress(f"[!] 生日字段输入异常: {e}") return False - log_progress("✓ 生日已输入 (精确模式)") + log_progress("[OK] 生日已输入 (精确模式)") return True except Exception as e: - log_progress(f"⚠ 精确生日输入失败: {e}") + log_progress(f"[!] 精确生日输入失败: {e}") return False @@ -595,7 +595,7 @@ def _input_birthday_fallback(page, birth_year: str, birth_month: str, birth_day: page.actions.type(digit) time.sleep(0.1) - log_progress("✓ 生日已输入 (备用模式)") + log_progress("[OK] 生日已输入 (备用模式)") # 地址格式: (街道, 邮编, 城市) SEPA_ADDRESSES = [ @@ -742,7 +742,7 @@ def log_status(step, message): sys.stdout.flush() def log_progress(message): - print(f" -> {message}") + print(f" {message}") sys.stdout.flush() def save_account(email, password, token, account_id=""): @@ -829,7 +829,7 @@ def get_verification_content(target_email, max_retries=90): sys.stdout.flush() time.sleep(2) - log_status("超时", "❌ 未能获取验证码。") + log_status("超时", "[X] 未能获取验证码。") return None @@ -876,9 +876,9 @@ def run_payment_flow(page, email, step_callback=None): # 检查停止请求 if _is_shutdown_requested(): - log_progress("⚠ 检测到停止请求,中断支付流程") + log_progress("[!] 检测到停止请求,中断支付流程") return {"stopped": True} - + log_status("支付流程", "开始处理 Stripe 支付页...") try: @@ -911,15 +911,15 @@ def run_payment_flow(page, email, step_callback=None): time.sleep(2) if email_input: - log_progress("✓ 支付页已加载") + log_progress("[OK] 支付页已加载") else: - log_progress("⚠ 邮箱输入框未立即出现,继续尝试...") + log_progress("[!] 邮箱输入框未立即出现,继续尝试...") time.sleep(3) # 随机选择 IBAN 和地址 ibans = get_sepa_ibans() if not ibans: - log_progress("❌ 没有可用的 IBAN,请先通过 Bot 导入") + log_progress("[X] 没有可用的 IBAN,请先通过 Bot 导入") return None sepa_iban = random.choice(ibans) street, postal_code, city = random.choice(SEPA_ADDRESSES) @@ -931,13 +931,13 @@ def run_payment_flow(page, email, step_callback=None): # ========== 步骤 1: 填写邮箱 ========== step_cb("填写支付邮箱...") - log_progress("[步骤1] 填写邮箱...") + log_progress("[1] 填写邮箱...") try: # 检查停止请求 if _is_shutdown_requested(): - log_progress("⚠ 检测到停止请求") + log_progress("[!] 检测到停止请求") return {"stopped": True} - + # 如果之前已经找到了,直接使用;否则重新查找 if not email_input: email_input = page.ele('#email', timeout=10) @@ -946,33 +946,32 @@ def run_payment_flow(page, email, step_callback=None): if not email_input: email_input = page.ele('css:input[type="email"]', timeout=5) if not email_input: - log_progress("❌ 邮箱输入框未找到") + log_progress("[X] 邮箱输入框未找到") log_progress(f"当前URL: {page.url}") return None email_input.clear() email_input.input(email) - log_progress(f"✓ 已填写邮箱: {email}") + log_progress(f"[OK] 已填写邮箱: {email}") time.sleep(1) except Exception as e: error_msg = str(e) if _is_connection_lost(error_msg) or _is_shutdown_requested(): - log_progress("⚠ 检测到停止请求,中断支付流程") + log_progress("[!] 检测到停止请求,中断支付流程") return {"stopped": True} - log_progress(f"❌ 邮箱填写失败: {e}") + log_progress(f"[X] 邮箱填写失败: {e}") log_progress(f"当前URL: {page.url}") return None # ========== 步骤 2: 选择 SEPA ========== step_cb("选择 SEPA 支付方式...") - log_progress("[步骤2] 选择 SEPA 直接借记...") - time.sleep(2) + log_progress("[2] 选择 SEPA...") + time.sleep(1) sepa_clicked = False - + # 定位方式(按速度排序:属性选择器 > CSS > xpath) sepa_selectors = [ '@data-testid=sepa_debit-accordion-item-button', # 最快:属性选择器 'css:button[data-testid*="sepa"]', # 快:CSS 模糊匹配 - 'xpath://button[contains(., "SEPA")]', # 备用:xpath 文本匹配 ] for selector in sepa_selectors: try: @@ -980,12 +979,11 @@ def run_payment_flow(page, email, step_callback=None): if sepa_btn: page.run_js('arguments[0].click()', sepa_btn) sepa_clicked = True - log_progress("✓ 已点击 SEPA 按钮") - time.sleep(2) + time.sleep(1) break except: continue - + if not sepa_clicked: # 最后尝试 JS try: @@ -1001,184 +999,105 @@ def run_payment_flow(page, email, step_callback=None): ''') if result: sepa_clicked = True - log_progress("✓ 已点击 SEPA (JS)") - time.sleep(2) + time.sleep(1) except: pass - + if not sepa_clicked: - log_progress("❌ SEPA 选择失败") + log_progress("[X] SEPA 选择失败") return None - + # 验证 SEPA 是否真正展开(检查 IBAN 输入框是否出现) - log_progress("验证 SEPA 是否展开...") - time.sleep(2) try: iban_check = page.ele('#iban', timeout=5) if not iban_check: - log_progress("❌ SEPA 未展开,IBAN 输入框未出现") + log_progress("[X] SEPA 未展开") return None - log_progress("✓ SEPA 已展开,IBAN 输入框已出现") except: - log_progress("❌ SEPA 未展开,IBAN 输入框未出现") + log_progress("[X] SEPA 未展开") return None # ========== 步骤 3: 填写 IBAN ========== step_cb("填写 IBAN...") - log_progress("[步骤3] 填写 IBAN...") + log_progress("[3] 填写 IBAN...") try: - # 优先使用 #iban (Stripe 标准 id),更快 iban_input = page.ele('#iban', timeout=5) if not iban_input: - iban_input = page.ele('@name=iban', timeout=3) - if not iban_input: - log_progress("❌ IBAN 输入框未找到") + log_progress("[X] IBAN 输入框未找到") return None iban_input.input(sepa_iban) - log_progress(f"✓ 已填写 IBAN: {sepa_iban}") - time.sleep(1) except Exception as e: - log_progress(f"❌ IBAN 填写失败: {e}") + log_progress(f"[X] IBAN 填写失败: {e}") return None # ========== 步骤 4: 填写账户姓名 ========== step_cb("填写账户姓名...") - log_progress("[步骤4] 填写账户姓名...") + log_progress("[4] 填写姓名...") try: - # 优先使用 billingName (Stripe 支付页面标准 id) - name_input = page.ele('#billingName', timeout=5) + name_input = page.ele('#billingName', timeout=3) if not name_input: - name_input = page.ele('@name=billingName', timeout=3) - if not name_input: - name_input = page.ele('xpath://input[@name="name" or contains(@id, "name") or contains(@placeholder, "姓名")]', timeout=3) - if not name_input: - log_progress("❌ 姓名输入框未找到") - return None - name_input.input(account_name) - log_progress(f"✓ 已填写账户姓名: {account_name}") - time.sleep(1) - except Exception as e: - log_progress(f"❌ 账户姓名填写失败: {e}") - return None + name_input = page.ele('@name=billingName', timeout=2) + if name_input: + name_input.input(account_name) + except: + pass # ========== 步骤 5: 填写地址 ========== step_cb("填写账单地址...") - log_progress("[步骤5] 填写地址...") + log_progress("[5] 填写地址...") try: - # 检查是否需要点击"手动输入地址"(仅当地址输入框不存在时) addr_input = page.ele('#billingAddressLine1', timeout=1) if not addr_input: - # 尝试点击手动输入地址按钮 try: manual_btn = page.ele('@data-testid=manual-address-entry', timeout=1) if manual_btn: manual_btn.click() - time.sleep(0.5) + time.sleep(0.3) except: pass - addr_input = page.ele('#billingAddressLine1', timeout=3) + addr_input = page.ele('#billingAddressLine1', timeout=2) - if not addr_input: - log_progress("❌ 地址输入框未找到") - return None - - # 一次性填写所有地址字段 - addr_input.input(street) - log_progress(f"✓ 已填写地址: {street}") - - postal_input = page.ele('#billingPostalCode', timeout=1) - if postal_input: - postal_input.input(postal_code) - log_progress(f"✓ 已填写邮编: {postal_code}") - - city_input = page.ele('#billingLocality', timeout=1) - if city_input: - city_input.input(city) - log_progress(f"✓ 已填写城市: {city}") - - # 关闭 Google 地址建议弹窗 - page.actions.key_down('Escape').key_up('Escape') - time.sleep(0.3) - page.run_js('document.body.click()') - - except Exception as e: - log_progress(f"❌ 地址填写失败: {e}") - return None + if addr_input: + addr_input.input(street) + postal_input = page.ele('#billingPostalCode', timeout=1) + if postal_input: + postal_input.input(postal_code) + city_input = page.ele('#billingLocality', timeout=1) + if city_input: + city_input.input(city) + page.actions.key_down('Escape').key_up('Escape') + except: + pass # ========== 步骤 6: 勾选条款 ========== step_cb("勾选服务条款...") - log_progress("[步骤6] 勾选条款...") + log_progress("[6] 勾选条款...") try: - terms_checkbox = page.ele('#termsOfServiceConsentCheckbox', timeout=5) + terms_checkbox = page.ele('#termsOfServiceConsentCheckbox', timeout=3) if terms_checkbox: terms_checkbox.click() - log_progress("✓ 已勾选条款") - time.sleep(1) - except Exception as e: - log_progress(f"⚠ 条款勾选失败(可能已勾选): {e}") - + except: + pass + # ========== 步骤 7: 点击订阅 ========== step_cb("提交订阅...") - log_progress("[步骤7] 点击订阅按钮...") - time.sleep(2) - subscribe_processing = False - - # 尝试点击订阅按钮并验证是否进入处理状态 - for attempt in range(3): - try: - subscribe_btn = page.ele('css:button[type="submit"]', timeout=5) - if subscribe_btn: - subscribe_btn.click() - log_progress(f"[尝试{attempt+1}] 已点击订阅按钮,等待处理状态...") - - # 等待按钮变成"正在处理"状态(检测 disabled 属性或 spinner) - for _ in range(10): - time.sleep(0.5) - try: - # 检查按钮是否被禁用(处理中) - btn_disabled = page.run_js(''' - const btn = document.querySelector('button[type="submit"]'); - if (!btn) return false; - return btn.disabled || btn.classList.contains('processing') || - btn.querySelector('.spinner, .loading, svg') !== null; - ''') - if btn_disabled: - subscribe_processing = True - log_progress("✓ 订阅按钮已进入处理状态") - break - - # 检查 URL 是否已经变化(支付成功) - if 'success' in page.url: - subscribe_processing = True - log_progress("✓ 已检测到支付成功") - break - except: - pass - - if subscribe_processing: - break - except: - pass - - if not subscribe_processing: - # JS 备用点击 - try: - page.run_js('document.querySelector("button[type=submit]").click()') - time.sleep(2) - except: - pass - - if not subscribe_processing: - log_progress("⚠ 未检测到处理状态,继续等待支付结果...") + log_progress("[7] 点击订阅...") + time.sleep(1) + try: + subscribe_btn = page.ele('css:button[type="submit"]', timeout=5) + if subscribe_btn: + subscribe_btn.click() + except: + page.run_js('document.querySelector("button[type=submit]").click()') # ========== 步骤 8: 等待支付成功 ========== step_cb("等待支付处理...") - log_status("等待", "等待支付处理(超时60秒)...") + log_status("等待", "等待支付处理(超时60秒)...") try: page.wait.url_change('payments/success-team', timeout=60) - log_status("成功", "✓ 支付成功!") + log_status("成功", "[OK] 支付成功!") except: - log_status("超时", "❌ 支付未在60秒内完成") + log_status("超时", "[X] 支付未完成") return None # ========== 步骤 9: 获取 token 和 account_id ========== @@ -1196,7 +1115,7 @@ def run_payment_flow(page, email, step_callback=None): access_token = session_data.get('accessToken', '') if access_token: - log_status("成功", f"获取到 token: {access_token[:50]}...") + log_status("成功", f"Token: {access_token[:50]}...") # 优先从 session 数据直接提取 account_id(最快) step_cb("获取 Account ID...") @@ -1206,22 +1125,25 @@ def run_payment_flow(page, email, step_callback=None): if not account_id: account_id = fetch_account_id(page, access_token) + if account_id: + log_progress(f"account_id: {account_id}") + return { "token": access_token, "account_id": account_id } else: - log_progress("未找到 accessToken") + log_progress("[X] 未找到 accessToken") return None except Exception as e: - log_progress(f"获取 token 失败: {e}") + log_progress(f"[X] 获取 token 失败: {e}") return None except Exception as e: error_msg = str(e) # 检查是否是连接断开(由 /stop 命令导致) if _is_connection_lost(error_msg) or _is_shutdown_requested(): - log_status("停止", "⚠ 检测到停止请求,支付流程已中断") + log_status("停止", "[!] 检测到停止请求,支付流程已中断") return {"stopped": True} log_status("错误", f"[X] 支付流程异常: {e}") return None @@ -1361,7 +1283,7 @@ def browser_pay_with_cookies(reg, email: str, proxy: str = None, headless: bool try: page.wait.url_change('pay.openai.com', timeout=15) - log_progress("✓ 已跳转到支付页") + log_progress("[OK] 已跳转到支付页") except: time.sleep(2) @@ -1446,7 +1368,7 @@ def run_main_process(): # 检查必要配置 if not MAIL_API_TOKEN or not MAIL_API_BASE or not EMAIL_DOMAINS: print("\n" + "="*60) - print("❌ 配置错误: 请在 config.toml 中配置 [autogptplus] 段") + print("[X] 配置错误: 请在 config.toml 中配置 [autogptplus] 段") print(" - mail_api_token: Cloud Mail API Token") print(" - mail_api_base: Cloud Mail API 地址") print(" - email_domains: 可用邮箱域名列表") @@ -1461,7 +1383,7 @@ def run_main_process(): domains = get_email_domains() if not domains: print("\n" + "="*60) - print("❌ 配置错误: 没有可用的邮箱域名") + print("[X] 配置错误: 没有可用的邮箱域名") print(" 请在 config.toml 中配置 email_domains 或通过 Bot 添加") print("="*60 + "\n") return @@ -1672,7 +1594,7 @@ def run_main_process(): # 检查是否已跳转出 about-you 页面 if 'about-you' not in current_url: - log_progress(f"✓ 页面已跳转: {current_url[:50]}...") + log_progress(f"[OK] 页面已跳转: {current_url[:50]}...") submit_success = True break @@ -1680,7 +1602,7 @@ def run_main_process(): try: error_elem = page.ele('css:[role="alert"], [class*="error"], [class*="Error"]', timeout=1) if error_elem and error_elem.text: - log_progress(f"⚠ 发现错误提示: {error_elem.text[:50]}") + log_progress(f"[!] 发现错误提示: {error_elem.text[:50]}") except: pass @@ -1703,14 +1625,14 @@ def run_main_process(): try: captcha = page.ele('css:iframe[src*="captcha"], iframe[src*="recaptcha"], [class*="captcha"]', timeout=1) if captcha: - log_progress("⚠ 检测到 CAPTCHA,需要人工处理或等待...") + log_progress("[!] 检测到 CAPTCHA,需要人工处理或等待...") except: pass time.sleep(1) if not submit_success: - log_progress(f"⚠ 提交后仍在 about-you 页面,当前URL: {page.url}") + log_progress(f"[!] 提交后仍在 about-you 页面,当前URL: {page.url}") # ======================================================= # 【关键节点】等待进入主页后再执行 JS 跳转到支付页 @@ -1724,13 +1646,13 @@ def run_main_process(): # 更宽松的判断:只要不在 auth/login 页面就认为进入了主页 if 'chatgpt.com' in current_url: if '/auth' not in current_url and '/login' not in current_url and 'auth0' not in current_url: - log_progress(f"✓ 已进入主页: {current_url}") + log_progress(f"[OK] 已进入主页: {current_url}") entered_main = True break time.sleep(0.5) # 减少等待间隔 if not entered_main: - log_progress("⚠ 等待主页超时,尝试继续...") + log_progress("[!] 等待主页超时,尝试继续...") log_progress(f"当前URL: {page.url}") # 尝试直接访问主页 page.get("https://chatgpt.com/") @@ -1790,7 +1712,7 @@ def run_main_process(): # 等待跳转到支付页(使用 URL 检测代替固定等待) try: page.wait.url_change('pay.openai.com', timeout=15) - log_progress("✓ 已跳转到支付页") + log_progress("[OK] 已跳转到支付页") log_progress(f"支付页URL: {page.url}") except: time.sleep(1) @@ -1835,7 +1757,8 @@ def run_single_registration(progress_callback=None, step_callback=None) -> dict: def log_cb(msg): if progress_callback: progress_callback(msg) - log_progress(msg) + else: + log_progress(msg) def step_cb(step): if step_callback: @@ -2058,7 +1981,7 @@ def run_single_registration(progress_callback=None, step_callback=None) -> dict: # 检查是否已跳转出 about-you 页面 if 'about-you' not in current_url: - log_progress(f"✓ 页面已跳转: {current_url[:50]}...") + log_progress(f"[OK] 页面已跳转: {current_url[:50]}...") submit_success = True break @@ -2066,7 +1989,7 @@ def run_single_registration(progress_callback=None, step_callback=None) -> dict: try: error_elem = page.ele('css:[role="alert"], [class*="error"], [class*="Error"]', timeout=1) if error_elem and error_elem.text: - log_progress(f"⚠ 发现错误提示: {error_elem.text[:50]}") + log_progress(f"[!] 发现错误提示: {error_elem.text[:50]}") except: pass @@ -2089,14 +2012,14 @@ def run_single_registration(progress_callback=None, step_callback=None) -> dict: try: captcha = page.ele('css:iframe[src*="captcha"], iframe[src*="recaptcha"], [class*="captcha"]', timeout=1) if captcha: - log_progress("⚠ 检测到 CAPTCHA,需要人工处理或等待...") + log_progress("[!] 检测到 CAPTCHA,需要人工处理或等待...") except: pass time.sleep(1) if not submit_success: - log_progress(f"⚠ 提交后仍在 about-you 页面,当前URL: {page.url}") + log_progress(f"[!] 提交后仍在 about-you 页面,当前URL: {page.url}") # 等待进入主页 - 快速检测 step_cb("等待进入主页...") @@ -2109,13 +2032,13 @@ def run_single_registration(progress_callback=None, step_callback=None) -> dict: # 更宽松的判断:只要不在 auth/login 页面就认为进入了主页 if 'chatgpt.com' in current_url: if '/auth' not in current_url and '/login' not in current_url and 'auth0' not in current_url: - log_progress(f"✓ 已进入主页: {current_url}") + log_progress(f"[OK] 已进入主页: {current_url}") entered_main = True break time.sleep(0.5) # 减少等待间隔 if not entered_main: - log_progress("⚠ 等待主页超时,尝试继续...") + log_progress("[!] 等待主页超时,尝试继续...") log_progress(f"当前URL: {page.url}") # 尝试直接访问主页 page.get("https://chatgpt.com/") @@ -2156,7 +2079,7 @@ def run_single_registration(progress_callback=None, step_callback=None) -> dict: # 等待跳转到支付页 try: page.wait.url_change('pay.openai.com', timeout=15) - log_progress("✓ 已跳转到支付页") + log_progress("[OK] 已跳转到支付页") log_progress(f"支付页URL: {page.url}") except: time.sleep(1) @@ -2168,11 +2091,11 @@ def run_single_registration(progress_callback=None, step_callback=None) -> dict: if result and result.get("stopped"): # 被 /stop 命令中断 - log_status("停止", "⚠ 注册被用户停止") + log_status("停止", "[!] 注册被用户停止") return {"success": False, "error": "用户停止", "stopped": True, "account": email, "password": password} elif result and result.get("token"): step_cb("注册成功!") - log_status("完成", "✓ 注册成功!") + log_status("完成", "[OK] 注册成功!") return { "success": True, "account": email, @@ -2188,7 +2111,7 @@ def run_single_registration(progress_callback=None, step_callback=None) -> dict: error_msg = str(e) # 检查是否是连接断开(由 /stop 命令导致) if _is_connection_lost(error_msg) or _is_shutdown_requested(): - log_status("停止", "⚠ 注册被用户停止") + 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} @@ -2215,7 +2138,8 @@ def run_single_registration_api(progress_callback=None, step_callback=None, prox def log_cb(msg): if progress_callback: progress_callback(msg) - log_progress(msg) + else: + log_progress(msg) def step_cb(step): if step_callback: @@ -2308,11 +2232,11 @@ def run_single_registration_api(progress_callback=None, step_callback=None, prox ) if result and result.get("stopped"): - log_status("停止", "⚠ 注册被用户停止") + log_status("停止", "[!] 注册被用户停止") return {"success": False, "error": "用户停止", "stopped": True, "account": email, "password": password} elif result and result.get("token"): step_cb("注册成功!") - log_status("完成", "✓ 全部流程完成!") + log_status("完成", "[OK] 全部流程完成!") return { "success": True, "account": email, @@ -2343,7 +2267,7 @@ def run_single_registration_api(progress_callback=None, step_callback=None, prox if result and result.get("token"): step_cb("注册成功!") - log_status("完成", "✓ 全部流程完成!") + log_status("完成", "[OK] 全部流程完成!") return { "success": True, "account": email, @@ -2358,7 +2282,7 @@ def run_single_registration_api(progress_callback=None, step_callback=None, prox except Exception as e: error_msg = str(e) if _is_connection_lost(error_msg) or _is_shutdown_requested(): - log_status("停止", "⚠ 注册被用户停止") + 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} diff --git a/run.py b/run.py index 00ed482..5b123b2 100644 --- a/run.py +++ b/run.py @@ -528,7 +528,7 @@ def process_accounts(accounts: list, team_name: str, team_index: int = 0, # 账号之间的间隔 if i < len(accounts) - 1 and not _shutdown_requested: - wait_time = random.randint(3, 6) + wait_time = 1 log.info(f"等待 {wait_time}s 后处理下一个账号...", icon="wait") time.sleep(wait_time)