Spaces:
Paused
Paused
| import asyncio | |
| import logging | |
| import os | |
| from pyrogram import Client, utils | |
| logger = logging.getLogger("pyrogram_clients") | |
| # ====================== 重要修復:Pyrogram PeerIdInvalid Bug ====================== | |
| # 針對大型 supergroup/channel ID(如 -10025xxxxxxxx)經常出現的問題 | |
| def get_peer_type_new(peer_id: int) -> str: | |
| """強制正確識別 -100 開頭的 chat_id 為 channel/supergroup""" | |
| peer_id_str = str(peer_id) | |
| if not peer_id_str.startswith("-"): | |
| return "user" | |
| elif peer_id_str.startswith("-100"): | |
| return "channel" | |
| else: | |
| return "chat" | |
| # 立即套用 patch(必須在任何 Pyrogram 操作前執行) | |
| utils.get_peer_type = get_peer_type_new | |
| logger.info("[PYRO-FIX] Monkey patch applied successfully: get_peer_type fixed for large supergroups/channels") | |
| # =============================================================================== | |
| async def perform_pyrogram_upload(client, file_path, file_name, chat_id, mime_type, size, thumbnail_path=None, task_id=None): | |
| """ | |
| 執行 Pyrogram 上傳(已加入 PeerIdInvalid 修復與進度回調) | |
| """ | |
| import time | |
| from database import db | |
| from models import UploadTask | |
| start_time = time.time() | |
| last_update_time = 0 | |
| async def progress_callback(current, total): | |
| nonlocal last_update_time | |
| now = time.time() | |
| # 每秒更新一次數據庫,避免頻繁寫入 | |
| if now - last_update_time >= 1.0 and task_id: | |
| elapsed = now - start_time | |
| speed_mb = (current / 1024 / 1024) / elapsed if elapsed > 0 else 0 | |
| speed_str = f"{speed_mb:.2f} MB/s" | |
| # 使用獨立的 session 更新,避免干擾主線程 | |
| try: | |
| task = UploadTask.query.get(task_id) | |
| if task: | |
| task.uploaded_bytes = current | |
| task.speed = speed_str | |
| db.session.commit() | |
| last_update_time = now | |
| except: | |
| db.session.rollback() | |
| try: | |
| if not os.path.exists(file_path): | |
| logger.error(f"[PYRO-FLOW] File not found: {file_path}") | |
| return [None] * 6 | |
| target_chat = int(chat_id) if isinstance(chat_id, str) else chat_id | |
| logger.info(f"[PYRO-FLOW] Starting upload: {file_name} → chat {target_chat} | mime: {mime_type}") | |
| # 嘗試預先獲取 chat(更新 access hash),失敗也不中斷 | |
| try: | |
| chat_obj = await client.get_chat(target_chat) | |
| logger.info(f"[PYRO-FLOW] get_chat success: {chat_obj.title} (type: {chat_obj.type})") | |
| except Exception as e: | |
| logger.warning(f"[PYRO-FLOW] get_chat failed (common with large IDs): {e}. Continuing with upload...") | |
| message = None | |
| if mime_type.startswith("video/"): | |
| message = await client.send_video( | |
| chat_id=target_chat, | |
| video=file_path, | |
| file_name=file_name, | |
| thumb=thumbnail_path, | |
| supports_streaming=True, | |
| progress=progress_callback | |
| ) | |
| else: | |
| message = await client.send_document( | |
| chat_id=target_chat, | |
| document=file_path, | |
| file_name=file_name, | |
| thumb=thumbnail_path, | |
| progress=progress_callback | |
| ) | |
| if message: | |
| # 兼容 video / document / audio 等 | |
| item = getattr(message, 'video', None) or \ | |
| getattr(message, 'document', None) or \ | |
| getattr(message, 'audio', None) or \ | |
| getattr(message, 'photo', None) | |
| if not item: | |
| logger.error("[PYRO-FLOW] Upload succeeded but could not extract file details.") | |
| return [None] * 6 | |
| file_id = item.file_id | |
| final_thumb_id = None | |
| if hasattr(item, 'thumbs') and item.thumbs: | |
| final_thumb_id = item.thumbs[-1].file_id | |
| elif hasattr(item, 'thumbnail') and item.thumbnail: | |
| final_thumb_id = item.thumbnail.file_id | |
| logger.info(f"[PYRO-FLOW] Upload SUCCESS! file_id: {file_id[:25]}... | msg_id: {message.id}") | |
| return file_id, file_name, mime_type, item.file_size, final_thumb_id, message.id | |
| else: | |
| logger.error("[PYRO-FLOW] send_video/send_document returned None") | |
| return [None] * 6 | |
| except Exception as e: | |
| logger.error(f"[PYRO-FLOW] Critical error during upload: {type(e).__name__}: {e}") | |
| # 如果還是出現 PeerIdInvalid,顯示更清楚的提示 | |
| if "Peer id invalid" in str(e) or "PEER_ID_INVALID" in str(e).upper(): | |
| logger.error("[PYRO-FLOW] PeerIdInvalid still occurred. Please check: " | |
| "1. Bot is added to the group as admin " | |
| "2. Chat ID is correct " | |
| "3. Try making the group public briefly then private again.") | |
| return [None] * 6 | |