-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathpyrogram_clients.py
More file actions
executable file
·127 lines (106 loc) · 4.96 KB
/
Copy pathpyrogram_clients.py
File metadata and controls
executable file
·127 lines (106 loc) · 4.96 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
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