update
This commit is contained in:
142
bot_notifier.py
142
bot_notifier.py
@@ -41,16 +41,21 @@ def make_progress_bar(current: int, total: int, width: int = 10) -> str:
|
||||
class ProgressTracker:
|
||||
"""进度跟踪器 - 用于实时更新 Telegram 消息显示进度"""
|
||||
|
||||
def __init__(self, bot: Bot, chat_ids: List[int], team_name: str, total: int):
|
||||
def __init__(self, bot: Bot, chat_ids: List[int], team_name: str, total: int,
|
||||
team_index: int = 0, teams_total: int = 0, include_owner: bool = False):
|
||||
self.bot = bot
|
||||
self.chat_ids = chat_ids
|
||||
self.team_name = team_name
|
||||
self.total = total
|
||||
self.team_index = team_index # 当前 Team 序号 (从 1 开始)
|
||||
self.teams_total = teams_total # Team 总数
|
||||
self.include_owner = include_owner # 是否包含 Owner
|
||||
self.current = 0
|
||||
self.success = 0
|
||||
self.failed = 0
|
||||
self.current_account = ""
|
||||
self.current_step = ""
|
||||
self.current_role = "" # 当前账号角色 (member/owner)
|
||||
self.messages: Dict[int, Message] = {} # chat_id -> Message
|
||||
self._last_update = 0
|
||||
self._update_interval = 2 # 最小更新间隔 (秒)
|
||||
@@ -60,17 +65,24 @@ class ProgressTracker:
|
||||
"""生成进度消息文本"""
|
||||
bar = make_progress_bar(self.current, self.total, 12)
|
||||
|
||||
# 标题行:显示 Team 序号
|
||||
if self.teams_total > 0:
|
||||
title = f"<b>📦 Team [{self.team_index}/{self.teams_total}]: {self.team_name}</b>"
|
||||
else:
|
||||
title = f"<b>📦 正在处理: {self.team_name}</b>"
|
||||
|
||||
lines = [
|
||||
f"<b>正在处理: {self.team_name}</b>",
|
||||
title,
|
||||
"",
|
||||
f"进度: {bar}",
|
||||
f"账号: {self.current}/{self.total}",
|
||||
f"账号: {self.current}/{self.total}" + (f" (含 Owner)" if self.include_owner else ""),
|
||||
f"成功: {self.success} | 失败: {self.failed}",
|
||||
]
|
||||
|
||||
if self.current_account:
|
||||
lines.append("")
|
||||
lines.append(f"当前: <code>{self.current_account}</code>")
|
||||
role_tag = " 👑" if self.current_role == "owner" else ""
|
||||
lines.append(f"当前: <code>{self.current_account}</code>{role_tag}")
|
||||
|
||||
if self.current_step:
|
||||
lines.append(f"步骤: {self.current_step}")
|
||||
@@ -105,10 +117,14 @@ class ProgressTracker:
|
||||
except TelegramError:
|
||||
pass
|
||||
|
||||
def _schedule_update(self):
|
||||
"""调度消息更新 (限流)"""
|
||||
def _schedule_update(self, force: bool = False):
|
||||
"""调度消息更新 (限流)
|
||||
|
||||
Args:
|
||||
force: 是否强制更新 (忽略限流)
|
||||
"""
|
||||
now = time.time()
|
||||
if now - self._last_update < self._update_interval:
|
||||
if not force and now - self._last_update < self._update_interval:
|
||||
return
|
||||
|
||||
self._last_update = now
|
||||
@@ -121,7 +137,7 @@ 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):
|
||||
def update(self, current: int = None, account: str = None, step: str = None, role: str = None):
|
||||
"""更新进度 (供同步代码调用)"""
|
||||
if current is not None:
|
||||
self.current = current
|
||||
@@ -129,6 +145,8 @@ class ProgressTracker:
|
||||
self.current_account = account
|
||||
if step is not None:
|
||||
self.current_step = step
|
||||
if role is not None:
|
||||
self.current_role = role
|
||||
|
||||
self._schedule_update()
|
||||
|
||||
@@ -141,13 +159,16 @@ class ProgressTracker:
|
||||
self.failed += 1
|
||||
self.current_account = ""
|
||||
self.current_step = ""
|
||||
self._schedule_update()
|
||||
self.current_role = ""
|
||||
# 最后一个账号完成时强制更新,确保显示 100%
|
||||
is_last = self.current >= self.total
|
||||
self._schedule_update(force=is_last)
|
||||
|
||||
def finish(self):
|
||||
"""完成进度跟踪,发送最终状态"""
|
||||
self.current_step = "已完成!"
|
||||
if self._loop:
|
||||
asyncio.run_coroutine_threadsafe(self._update_messages(), self._loop)
|
||||
# 强制更新最终状态
|
||||
self._schedule_update(force=True)
|
||||
|
||||
|
||||
class BotNotifier:
|
||||
@@ -197,8 +218,8 @@ class BotNotifier:
|
||||
text=message,
|
||||
parse_mode=parse_mode
|
||||
)
|
||||
except TelegramError:
|
||||
pass
|
||||
except TelegramError as e:
|
||||
print(f"[BotNotifier] 发送消息失败 (chat_id={chat_id}): {e}")
|
||||
|
||||
async def _send_photo_to_all(self, photo_path: str, caption: str = ""):
|
||||
"""发送图片到所有管理员"""
|
||||
@@ -232,10 +253,20 @@ class BotNotifier:
|
||||
"""直接发送通知 (阻塞)"""
|
||||
await self._send_to_all(message)
|
||||
|
||||
def create_progress(self, team_name: str, total: int) -> ProgressTracker:
|
||||
"""创建进度跟踪器"""
|
||||
def create_progress(self, team_name: str, total: int, team_index: int = 0,
|
||||
teams_total: int = 0, include_owner: bool = False) -> ProgressTracker:
|
||||
"""创建进度跟踪器
|
||||
|
||||
Args:
|
||||
team_name: Team 名称
|
||||
total: 账号总数
|
||||
team_index: 当前 Team 序号 (从 1 开始)
|
||||
teams_total: Team 总数
|
||||
include_owner: 是否包含 Owner
|
||||
"""
|
||||
self._current_progress = ProgressTracker(
|
||||
self.bot, self.chat_ids, team_name, total
|
||||
self.bot, self.chat_ids, team_name, total,
|
||||
team_index=team_index, teams_total=teams_total, include_owner=include_owner
|
||||
)
|
||||
if self._loop:
|
||||
self._current_progress.start(self._loop)
|
||||
@@ -286,6 +317,56 @@ class BotNotifier:
|
||||
|
||||
await self.notify(message)
|
||||
|
||||
async def notify_team_completed(self, team_name: str, results: list):
|
||||
"""通知单个 Team 处理完成
|
||||
|
||||
Args:
|
||||
team_name: Team 名称
|
||||
results: 处理结果列表 [{"email", "status", ...}]
|
||||
"""
|
||||
if not results:
|
||||
return
|
||||
|
||||
success_accounts = [r.get("email") for r in results if r.get("status") == "success"]
|
||||
failed_accounts = [r.get("email") for r in results if r.get("status") != "success"]
|
||||
|
||||
success_count = len(success_accounts)
|
||||
failed_count = len(failed_accounts)
|
||||
total = len(results)
|
||||
|
||||
# 状态图标
|
||||
if failed_count == 0:
|
||||
icon = "✅"
|
||||
status = "全部成功"
|
||||
elif success_count == 0:
|
||||
icon = "❌"
|
||||
status = "全部失败"
|
||||
else:
|
||||
icon = "⚠️"
|
||||
status = f"{failed_count} 个失败"
|
||||
|
||||
# 构建消息
|
||||
message = (
|
||||
f"<b>{icon} Team 处理完成</b>\n"
|
||||
f"Team: <code>{team_name}</code>\n"
|
||||
f"结果: {success_count}/{total} 成功\n"
|
||||
f"状态: {status}"
|
||||
)
|
||||
|
||||
# 列出成功的账号
|
||||
if success_accounts:
|
||||
message += "\n\n<b>✓ 成功:</b>"
|
||||
for email in success_accounts:
|
||||
message += f"\n <code>{email}</code>"
|
||||
|
||||
# 列出失败的账号
|
||||
if failed_accounts:
|
||||
message += "\n\n<b>✗ 失败:</b>"
|
||||
for email in failed_accounts:
|
||||
message += f"\n <code>{email}</code>"
|
||||
|
||||
await self.notify(message)
|
||||
|
||||
async def notify_error(self, message: str, details: str = ""):
|
||||
"""通知错误"""
|
||||
if not TELEGRAM_NOTIFY_ON_ERROR:
|
||||
@@ -343,17 +424,26 @@ def send_screenshot_sync(photo_path: str, caption: str = ""):
|
||||
|
||||
# ==================== 进度更新接口 (供 run.py 使用) ====================
|
||||
|
||||
def progress_start(team_name: str, total: int) -> Optional[ProgressTracker]:
|
||||
"""开始进度跟踪"""
|
||||
def progress_start(team_name: str, total: int, team_index: int = 0,
|
||||
teams_total: int = 0, include_owner: bool = False) -> Optional[ProgressTracker]:
|
||||
"""开始进度跟踪
|
||||
|
||||
Args:
|
||||
team_name: Team 名称
|
||||
total: 账号总数
|
||||
team_index: 当前 Team 序号 (从 1 开始)
|
||||
teams_total: Team 总数
|
||||
include_owner: 是否包含 Owner
|
||||
"""
|
||||
if _notifier:
|
||||
return _notifier.create_progress(team_name, total)
|
||||
return _notifier.create_progress(team_name, total, team_index, teams_total, include_owner)
|
||||
return None
|
||||
|
||||
|
||||
def progress_update(account: str = None, step: str = None):
|
||||
def progress_update(account: str = None, step: str = None, role: str = None):
|
||||
"""更新当前进度"""
|
||||
if _notifier and _notifier.get_progress():
|
||||
_notifier.get_progress().update(account=account, step=step)
|
||||
_notifier.get_progress().update(account=account, step=step, role=role)
|
||||
|
||||
|
||||
def progress_account_done(email: str, success: bool):
|
||||
@@ -366,3 +456,13 @@ def progress_finish():
|
||||
"""完成进度跟踪"""
|
||||
if _notifier:
|
||||
_notifier.clear_progress()
|
||||
|
||||
|
||||
def notify_team_completed_sync(team_name: str, results: list):
|
||||
"""同步方式通知单个 Team 完成 (供 run.py 使用)"""
|
||||
if _notifier and _notifier._loop:
|
||||
import asyncio
|
||||
asyncio.run_coroutine_threadsafe(
|
||||
_notifier.notify_team_completed(team_name, results),
|
||||
_notifier._loop
|
||||
)
|
||||
|
||||
Reference in New Issue
Block a user