TeleFileDB_DEMO / pyrogram_clients.py
3v324v23's picture
Initial launch: Cleaned history
ee2e500
Raw
History Blame Contribute Delete
5.08 kB
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