diff --git a/telegram_bot.py b/telegram_bot.py
index 7ddade4..9eda085 100644
--- a/telegram_bot.py
+++ b/telegram_bot.py
@@ -137,6 +137,7 @@ class ProvisionerBot:
("dashboard", self.cmd_dashboard),
("import", self.cmd_import),
("verify", self.cmd_verify),
+ ("verify_all", self.cmd_verify_all),
("stock", self.cmd_stock),
("gptmail_keys", self.cmd_gptmail_keys),
("gptmail_add", self.cmd_gptmail_add),
@@ -270,7 +271,8 @@ class ProvisionerBot:
BotCommand("stock", "查看账号库存"),
BotCommand("s2a_config", "配置 S2A 参数"),
BotCommand("import", "导入账号到 team.json"),
- BotCommand("verify", "验证账号并移除无效账号"),
+ BotCommand("verify", "验证未验证的账号"),
+ BotCommand("verify_all", "强制重新验证所有账号"),
# GPTMail
BotCommand("gptmail_keys", "查看 GPTMail API Keys"),
BotCommand("gptmail_add", "添加 GPTMail API Key"),
@@ -338,7 +340,8 @@ class ProvisionerBot:
📤 导入账号:
/import - 导入账号到 team.json
-/verify - 验证账号并移除无效账号
+/verify - 验证未验证的账号
+/verify_all - 强制重新验证所有账号
或直接发送 JSON 文件
📧 GPTMail 管理:
@@ -2041,20 +2044,23 @@ class ProvisionerBot:
if added_count > 0:
await self._validate_and_cleanup_accounts(chat_id)
- async def _validate_and_cleanup_accounts(self, chat_id: int):
+ async def _validate_and_cleanup_accounts(self, chat_id: int, force_all: bool = False):
"""验证新导入账号的 account_id,移除无效账号
Args:
chat_id: Telegram 聊天 ID,用于发送进度消息
+ force_all: 是否强制重新验证所有有 token 的账号
"""
import json
from pathlib import Path
from concurrent.futures import ThreadPoolExecutor, as_completed
+ mode_text = "重新验证" if force_all else "验证"
+
# 发送开始验证的消息
progress_msg = await self.app.bot.send_message(
chat_id=chat_id,
- text="🔍 正在验证账号...\n\n⏳ 获取 account_id 中...",
+ text=f"🔍 正在{mode_text}账号...\n\n⏳ 获取 account_id 中...",
parse_mode="HTML"
)
@@ -2075,13 +2081,19 @@ class ProvisionerBot:
if not isinstance(accounts, list):
accounts = [accounts]
- # 筛选需要验证的账号 (有 token 但没有 account_id)
+ # 筛选需要验证的账号
accounts_to_verify = []
for i, acc in enumerate(accounts):
token = acc.get("token", "")
account_id = acc.get("account_id", "")
- if token and not account_id:
- accounts_to_verify.append((i, acc))
+ if force_all:
+ # 强制模式:验证所有有 token 的账号
+ if token:
+ accounts_to_verify.append((i, acc))
+ else:
+ # 普通模式:只验证有 token 但没有 account_id 的账号
+ if token and not account_id:
+ accounts_to_verify.append((i, acc))
if not accounts_to_verify:
await self.app.bot.edit_message_text(
@@ -2093,10 +2105,23 @@ class ProvisionerBot:
return
total = len(accounts_to_verify)
+
+ # 生成进度条的辅助函数
+ def make_progress_bar(current: int, total: int, width: int = 16) -> str:
+ """生成进度条字符串"""
+ if total == 0:
+ return "[" + "░" * width + "]"
+ filled = int(width * current / total)
+ empty = width - filled
+ percent = int(100 * current / total)
+ return f"[{'█' * filled}{'░' * empty}] {current}/{total} ({percent}%)"
+
await self.app.bot.edit_message_text(
chat_id=chat_id,
message_id=progress_msg.message_id,
- text=f"🔍 正在验证账号...\n\n⏳ 验证 {total} 个账号的 account_id (20 并发)...",
+ text=f"🔍 正在{mode_text}账号...\n\n"
+ f"{make_progress_bar(0, total)}\n\n"
+ f"⏳ 验证 {total} 个账号的 account_id (20 并发)...",
parse_mode="HTML"
)
@@ -2148,11 +2173,12 @@ class ProvisionerBot:
if completed_count % 10 == 0 or completed_count == total or current_time - last_update_time > 1:
last_update_time = current_time
try:
+ progress_bar = make_progress_bar(completed_count, total)
await self.app.bot.edit_message_text(
chat_id=chat_id,
message_id=progress_msg.message_id,
- text=f"🔍 正在验证账号...\n\n"
- f"进度: {completed_count}/{total}\n"
+ text=f"🔍 正在{mode_text}账号...\n\n"
+ f"{progress_bar}\n\n"
f"✅ 成功: {len(valid_indices)}\n"
f"❌ 失败: {len(failed_accounts)}",
parse_mode="HTML"
@@ -2176,6 +2202,8 @@ class ProvisionerBot:
lines = [
"✅ 账号验证完成",
"",
+ f"{make_progress_bar(total, total)}",
+ "",
f"📊 验证结果:",
f" • 验证总数: {total}",
f" • 成功: {len(valid_indices)}",
@@ -2217,7 +2245,83 @@ class ProvisionerBot:
@admin_only
async def cmd_verify(self, update: Update, context: ContextTypes.DEFAULT_TYPE):
- """手动验证 team.json 中的账号,获取 account_id 并移除无效账号"""
+ """手动验证 team.json 中的账号,获取 account_id 并移除无效账号
+
+ 用法:
+ /verify - 验证未验证的账号
+ /verify_all - 强制重新验证所有账号
+ """
+ chat_id = update.effective_chat.id
+
+ # 检查是否有任务正在运行
+ if self.current_task and not self.current_task.done():
+ await update.message.reply_text(
+ f"⚠️ 有任务正在运行: {self.current_team}\n"
+ "请等待任务完成或使用 /stop 停止后再验证"
+ )
+ return
+
+ # 解析参数
+ force_all = context.args and context.args[0].lower() == "all"
+
+ # 检查 team.json 是否存在
+ from pathlib import Path
+ team_json_path = Path(TEAM_JSON_FILE)
+ if not team_json_path.exists():
+ await update.message.reply_text("❌ team.json 不存在,请先导入账号")
+ return
+
+ # 统计需要验证的账号
+ import json
+ try:
+ with open(team_json_path, "r", encoding="utf-8") as f:
+ accounts = json.load(f)
+ if not isinstance(accounts, list):
+ accounts = [accounts]
+ except Exception as e:
+ await update.message.reply_text(f"❌ 读取 team.json 失败: {e}")
+ return
+
+ total_accounts = len(accounts)
+ has_token = sum(1 for acc in accounts if acc.get("token"))
+ already_verified = sum(1 for acc in accounts if acc.get("account_id"))
+
+ if force_all:
+ # 强制重新验证所有有 token 的账号
+ need_verify = has_token
+ else:
+ # 只验证未验证的账号
+ need_verify = sum(1 for acc in accounts if acc.get("token") and not acc.get("account_id"))
+
+ if need_verify == 0:
+ await update.message.reply_text(
+ f"✅ 无需验证\n\n"
+ f"team.json 共 {total_accounts} 个账号\n"
+ f"有 Token: {has_token}\n"
+ f"已验证: {already_verified}\n"
+ f"待验证: 0\n\n"
+ f"💡 使用 /verify_all 强制重新验证所有账号",
+ parse_mode="HTML"
+ )
+ return
+
+ mode_text = "强制重新验证" if force_all else "验证"
+ await update.message.reply_text(
+ f"🔍 开始{mode_text}账号\n\n"
+ f"team.json 共 {total_accounts} 个账号\n"
+ f"有 Token: {has_token}\n"
+ f"已验证: {already_verified}\n"
+ f"待验证: {need_verify}\n\n"
+ f"⏳ 正在验证...",
+ parse_mode="HTML"
+ )
+
+ # 执行验证
+ await self._validate_and_cleanup_accounts(chat_id, force_all=force_all)
+
+ @admin_only
+ async def cmd_verify_all(self, update: Update, context: ContextTypes.DEFAULT_TYPE):
+ """强制重新验证所有账号"""
chat_id = update.effective_chat.id
# 检查是否有任务正在运行
@@ -2247,30 +2351,31 @@ class ProvisionerBot:
return
total_accounts = len(accounts)
- need_verify = sum(1 for acc in accounts if acc.get("token") and not acc.get("account_id"))
+ has_token = sum(1 for acc in accounts if acc.get("token"))
already_verified = sum(1 for acc in accounts if acc.get("account_id"))
- if need_verify == 0:
+ if has_token == 0:
await update.message.reply_text(
- f"✅ 无需验证\n\n"
+ f"❌ 无法验证\n\n"
f"team.json 共 {total_accounts} 个账号\n"
- f"已验证: {already_verified}\n"
- f"待验证: 0",
+ f"有 Token: 0\n\n"
+ f"没有可验证的账号",
parse_mode="HTML"
)
return
await update.message.reply_text(
- f"🔍 开始验证账号\n\n"
+ f"🔍 开始强制重新验证所有账号\n\n"
f"team.json 共 {total_accounts} 个账号\n"
+ f"有 Token: {has_token}\n"
f"已验证: {already_verified}\n"
- f"待验证: {need_verify}\n\n"
+ f"待验证: {has_token}\n\n"
f"⏳ 正在验证...",
parse_mode="HTML"
)
- # 执行验证
- await self._validate_and_cleanup_accounts(chat_id)
+ # 执行验证 (强制模式)
+ await self._validate_and_cleanup_accounts(chat_id, force_all=True)
async def _import_batch_timeout_callback(self, context: ContextTypes.DEFAULT_TYPE):
"""批量导入超时回调 - 由 job_queue 调用"""