From 6559e4b84ab2e5032f2d30f8e1bffbc0d654ddfa Mon Sep 17 00:00:00 2001 From: kyx236 Date: Tue, 20 Jan 2026 21:09:54 +0800 Subject: [PATCH] update --- bot_notifier.py | 53 +++++++++++++++++++++++++++---------------- browser_automation.py | 17 ++++++++++++++ run.py | 14 ++++++------ telegram_bot.py | 14 ++++++------ 4 files changed, 64 insertions(+), 34 deletions(-) diff --git a/bot_notifier.py b/bot_notifier.py index 7b3284d..3ccb6c1 100644 --- a/bot_notifier.py +++ b/bot_notifier.py @@ -14,7 +14,7 @@ from config import ( ) -def make_progress_bar(current: int, total: int, width: int = 10) -> str: +def make_progress_bar(current: int, total: int, width: int = 20) -> str: """生成文本进度条 Args: @@ -23,19 +23,16 @@ def make_progress_bar(current: int, total: int, width: int = 10) -> str: width: 进度条宽度 (字符数) Returns: - 进度条字符串,如 "████████░░ 80%" + 进度条字符串,如 "▓▓▓▓░░░░░░" """ if total <= 0: - return "░" * width + " 0%" + return "░" * width percent = min(current / total, 1.0) filled = int(width * percent) empty = width - filled - bar = "█" * filled + "░" * empty - percent_text = f"{int(percent * 100)}%" - - return f"{bar} {percent_text}" + return "▓" * filled + "░" * empty class ProgressTracker: @@ -54,6 +51,7 @@ class ProgressTracker: self.success = 0 self.failed = 0 self.current_account = "" + self.current_phase = "" # 当前阶段 (注册/授权/验证) self.current_step = "" self.current_role = "" # 当前账号角色 (member/owner) self.messages: Dict[int, Message] = {} # chat_id -> Message @@ -63,29 +61,34 @@ class ProgressTracker: def _get_progress_text(self) -> str: """生成进度消息文本""" - bar = make_progress_bar(self.current, self.total, 12) + bar = make_progress_bar(self.current, self.total, 20) # 标题行:显示 Team 序号 if self.teams_total > 0: - title = f"📦 Team [{self.team_index}/{self.teams_total}]: {self.team_name}" + title = f"◈ Team [{self.team_index}/{self.teams_total}]: {self.team_name}" else: - title = f"📦 正在处理: {self.team_name}" + title = f"◈ 正在处理: {self.team_name}" + owner_tag = " (含 Owner)" if self.include_owner else "" lines = [ title, "", - f"进度: {bar}", - f"账号: {self.current}/{self.total}" + (f" (含 Owner)" if self.include_owner else ""), - f"成功: {self.success} | 失败: {self.failed}", + f"🔄 注册进度 {self.current}/{self.total}{owner_tag}", + bar, + "", + f"✅ 成功: {self.success}", + f"❌ 失败: {self.failed}", ] if self.current_account: lines.append("") role_tag = " 👑" if self.current_role == "owner" else "" - lines.append(f"当前: {self.current_account}{role_tag}") + lines.append(f"⏳ 正在处理: {self.current_account}{role_tag}") - if self.current_step: - lines.append(f"步骤: {self.current_step}") + if self.current_phase and self.current_step: + lines.append(f" ▸ [{self.current_phase}] {self.current_step}") + elif self.current_step: + lines.append(f" ▸ {self.current_step}") return "\n".join(lines) @@ -137,12 +140,14 @@ class ProgressTracker: self._loop = loop asyncio.run_coroutine_threadsafe(self._send_initial_message(), loop) - def update(self, current: int = None, account: str = None, step: str = None, role: str = None): + def update(self, current: int = None, account: str = None, phase: str = None, step: str = None, role: str = None): """更新进度 (供同步代码调用)""" if current is not None: self.current = current if account is not None: self.current_account = account + if phase is not None: + self.current_phase = phase if step is not None: self.current_step = step if role is not None: @@ -158,6 +163,7 @@ class ProgressTracker: else: self.failed += 1 self.current_account = "" + self.current_phase = "" self.current_step = "" self.current_role = "" # 最后一个账号完成时强制更新,确保显示 100% @@ -440,10 +446,17 @@ def progress_start(team_name: str, total: int, team_index: int = 0, return None -def progress_update(account: str = None, step: str = None, role: str = None): - """更新当前进度""" +def progress_update(account: str = None, phase: str = None, step: str = None, role: str = None): + """更新当前进度 + + Args: + account: 当前处理的账号 + phase: 当前阶段 (注册/授权/验证) + step: 当前步骤 + role: 账号角色 + """ if _notifier and _notifier.get_progress(): - _notifier.get_progress().update(account=account, step=step, role=role) + _notifier.get_progress().update(account=account, phase=phase, step=step, role=role) def progress_account_done(email: str, success: bool): diff --git a/browser_automation.py b/browser_automation.py index af338d6..eef05b7 100644 --- a/browser_automation.py +++ b/browser_automation.py @@ -34,6 +34,12 @@ from s2a_service import ( ) from logger import log +# 进度更新 (Telegram Bot 使用) +try: + from bot_notifier import progress_update +except ImportError: + def progress_update(account=None, phase=None, step=None, role=None): pass + # ==================== 停止检查 ==================== class ShutdownRequested(Exception): @@ -1106,6 +1112,7 @@ def register_openai_account(page, email: str, password: str) -> bool: # 步骤1: 输入邮箱 (在 log-in-or-create-account 页面) if "auth.openai.com/log-in-or-create-account" in current_url: + progress_update(phase="注册", step="输入邮箱...") log.step("等待邮箱输入框...") email_input = wait_for_element(page, 'css:input[type="email"]', timeout=15) if not email_input: @@ -1129,6 +1136,7 @@ def register_openai_account(page, email: str, password: str) -> bool: # 步骤2: 输入密码 (在密码页面: log-in/password 或 create-account/password) if "auth.openai.com/log-in/password" in current_url or "auth.openai.com/create-account/password" in current_url: + progress_update(phase="注册", step="输入密码...") # 先检查是否有密码错误提示,如果有则使用一次性验证码登录 try: error_text = page.ele('text:Incorrect email address or password', timeout=1) @@ -1229,6 +1237,7 @@ def register_openai_account(page, email: str, password: str) -> bool: # 检测到姓名/年龄输入页面 (账号已存在,只需补充信息) if "auth.openai.com/about-you" in current_url: + progress_update(phase="注册", step="补充个人信息...") log_current_url(page, "个人信息页面") log.info("检测到姓名输入页面,账号已存在,补充信息...") @@ -1282,6 +1291,7 @@ def register_openai_account(page, email: str, password: str) -> bool: return False # 获取验证码 + progress_update(phase="注册", step="等待验证码...") log.step("等待验证码邮件...") verification_code, error, email_time = unified_get_verification_code(email) @@ -1296,6 +1306,7 @@ def register_openai_account(page, email: str, password: str) -> bool: max_code_retries = 3 for code_attempt in range(max_code_retries): # 输入验证码 + progress_update(phase="注册", step="输入验证码...") log.step(f"输入验证码: {verification_code}") while check_and_handle_error(page): time.sleep(1) @@ -2473,6 +2484,7 @@ def perform_s2a_authorization(page, email: str, password: str) -> bool: bool: 授权是否成功 """ log.info(f"开始 S2A 授权: {email}", icon="code") + progress_update(phase="授权", step="开始 S2A 授权...") # 生成授权 URL auth_url, session_id = s2a_generate_auth_url() @@ -2481,6 +2493,7 @@ def perform_s2a_authorization(page, email: str, password: str) -> bool: return False # 打开授权页面 + progress_update(phase="授权", step="打开授权页面...") log.step("打开 S2A 授权页面...") log.info(f"[URL] S2A授权URL: {auth_url}", icon="browser") page.get(auth_url) @@ -2492,6 +2505,7 @@ def perform_s2a_authorization(page, email: str, password: str) -> bool: try: # 输入邮箱 + progress_update(phase="授权", step="输入邮箱...") log.step("输入邮箱...") email_input = wait_for_element(page, 'css:input[type="email"]', timeout=10) if not email_input: @@ -2516,6 +2530,7 @@ def perform_s2a_authorization(page, email: str, password: str) -> bool: current_url = page.url if "/password" in current_url: try: + progress_update(phase="授权", step="输入密码...") log.step("输入密码...") password_input = wait_for_element(page, 'css:input[type="password"]', timeout=10) @@ -2540,6 +2555,7 @@ def perform_s2a_authorization(page, email: str, password: str) -> bool: callback_url = None progress_shown = False last_url_in_loop = None + progress_update(phase="授权", step="等待回调...") log.step(f"等待 S2A 授权回调 (最多 {max_wait}s)...") while time.time() - start_time < max_wait: @@ -2604,6 +2620,7 @@ def perform_s2a_authorization(page, email: str, password: str) -> bool: return False # S2A 特有流程: 用授权码创建账号 (传入完整邮箱用于验证) + progress_update(phase="授权", step="提交授权码...") log.step("正在提交 S2A 授权码...") result = s2a_create_account_from_oauth(code, session_id, name=email) if result: diff --git a/run.py b/run.py index 4bc5fa4..00ed482 100644 --- a/run.py +++ b/run.py @@ -48,7 +48,7 @@ try: except ImportError: # 如果没有 bot_notifier,使用空函数 def progress_start(team_name, total): pass - def progress_update(account=None, step=None): pass + def progress_update(account=None, phase=None, step=None, role=None): pass def progress_account_done(email, success): pass def progress_finish(): pass def notify_team_completed_sync(team_name, results): pass @@ -319,7 +319,7 @@ def process_accounts(accounts: list, team_name: str, team_index: int = 0, log.separator("#", 50) # 更新进度: 当前账号 - progress_update(account=email, step="Starting...", role=role) + progress_update(account=email, phase="准备", step="开始处理...", role=role) result = { "team": team_name, @@ -370,13 +370,13 @@ def process_accounts(accounts: list, team_name: str, team_index: int = 0, if is_team_owner_otp: # 旧格式 Team Owner: 使用 OTP 登录授权 log.info("Team Owner 账号 (旧格式),使用一次性验证码登录...", icon="auth") - progress_update(step="OTP Login...") + progress_update(phase="授权", step="OTP 登录...") auth_success, codex_data = login_and_authorize_with_otp(email) register_success = auth_success elif need_crs_only: # 已授权但未入库: 跳过授权,直接尝试入库 log.info(f"已授权账号 (状态: {account_status}),跳过授权,直接入库...", icon="auth") - progress_update(step="Adding to CRS...") + progress_update(phase="入库", step="添加到 CRS...") register_success = True codex_data = None # CPA/S2A 模式不需要 codex_data # CRS 模式下,由于没有 codex_data,无法入库,需要重新授权 @@ -387,12 +387,12 @@ def process_accounts(accounts: list, team_name: str, team_index: int = 0, elif need_auth_only: # 已注册账号 (包括新格式 Owner): 使用密码登录授权 log.info(f"已注册账号 (状态: {account_status}, 角色: {account_role}),使用密码登录授权...", icon="auth") - progress_update(step="Authorizing...") + progress_update(phase="授权", step="密码登录授权...") auth_success, codex_data = authorize_only(email, password) register_success = True else: # 新账号: 注册 + Codex 授权 - progress_update(step="Registering...") + progress_update(phase="注册", step="注册 OpenAI...") register_success, codex_data = register_and_authorize(email, password) # 检查是否是域名黑名单错误 @@ -436,7 +436,7 @@ def process_accounts(accounts: list, team_name: str, team_index: int = 0, # 验证账号是否成功入库 log.step("正在验证 S2A 账号入库状态...") - progress_update(step="验证入库...") + progress_update(phase="验证", step="检查入库状态...") verified, account_data = s2a_verify_account_in_pool(email) if verified: diff --git a/telegram_bot.py b/telegram_bot.py index a581d46..c1592e4 100644 --- a/telegram_bot.py +++ b/telegram_bot.py @@ -1207,19 +1207,19 @@ class ProvisionerBot: # 创建时间选择按钮 keyboard = [ [ - InlineKeyboardButton("📅 今天", callback_data="keys_usage:today"), - InlineKeyboardButton("📅 昨天", callback_data="keys_usage:yesterday"), + InlineKeyboardButton("📍 今天", callback_data="keys_usage:today"), + InlineKeyboardButton("◀ 昨天", callback_data="keys_usage:yesterday"), ], [ - InlineKeyboardButton("📆 近 7 天", callback_data="keys_usage:7d"), - InlineKeyboardButton("📆 近 14 天", callback_data="keys_usage:14d"), + InlineKeyboardButton("◀ 近 7 天", callback_data="keys_usage:7d"), + InlineKeyboardButton("◀ 近 14 天", callback_data="keys_usage:14d"), ], [ - InlineKeyboardButton("📆 近 30 天", callback_data="keys_usage:30d"), - InlineKeyboardButton("📆 本月", callback_data="keys_usage:this_month"), + InlineKeyboardButton("◀ 近 30 天", callback_data="keys_usage:30d"), + InlineKeyboardButton("📅 本月", callback_data="keys_usage:this_month"), ], [ - InlineKeyboardButton("📆 上月", callback_data="keys_usage:last_month"), + InlineKeyboardButton("📅 上月", callback_data="keys_usage:last_month"), ], ] reply_markup = InlineKeyboardMarkup(keyboard)