fix: guard against missing messages and reaction issues

Added a guard in `api_server.download_media_file` to detect `None` or empty messages and return a 404 error, preventing downstream failures.

Enhanced `PostParser._extract_reactions` to handle paid reactions, custom emojis, and unknown types, aggregating counts correctly. Updated `_extract_flags` to skip paid and custom emoji reactions, ensuring flag detection works reliably.
This commit is contained in:
vvzvlad
2026-05-17 23:12:11 +03:00
parent 40fa9797e8
commit dd5999b51f
2 changed files with 26 additions and 4 deletions
+6 -1
View File
@@ -360,7 +360,12 @@ async def download_media_file(channel: Union[str, int], post_id: int, file_uniqu
except asyncio.TimeoutError:
logger.error(f"Timeout getting messages for {channel}/{post_id}")
raise HTTPException(status_code=504, detail="Request timeout")
# Guard: message may be None (deleted) or an empty stub returned by Pyrogram
if not message or getattr(message, 'empty', False):
logger.warning(f"Message {post_id} not found or empty in channel {channel}")
raise HTTPException(status_code=404, detail="Post not found or deleted")
if message.media == MessageMediaType.POLL:
return None, False
+20 -3
View File
@@ -309,7 +309,20 @@ class PostParser:
def _extract_reactions(self, message: Message) -> Union[Dict[str, int], None]:
if reactions := getattr(message, 'reactions', None):
return {r.emoji: r.count for r in reactions.reactions}
result: Dict[str, int] = {}
for r in reactions.reactions:
# Resolve emoji key using the same logic as _reactions_views_links()
if getattr(r, "is_paid", False):
emoji = ""
elif hasattr(r, "emoji") and r.emoji:
emoji = r.emoji
elif hasattr(r, "custom_emoji_id"):
emoji = "" # custom emoji — no text representation available
else:
emoji = "" # unknown reaction type
# Accumulate counts in case multiple reactions resolve to the same key
result[emoji] = result.get(emoji, 0) + r.count
return result
return None
def _extract_flags(self, message: Message) -> List[str]: #Tests: tests/postparser_extract_flags.py
@@ -365,10 +378,14 @@ class PostParser:
# Check if the post's reactions contain more clown emojis (🤡) or poo emojis (💩).
if reactions := getattr(message, "reactions", None):
for reaction in getattr(reactions, "reactions", []):
if reaction.emoji == "🤡" and reaction.count >= 30:
# Skip paid reactions and custom emoji — they have no .emoji attribute
if getattr(reaction, "is_paid", False) or not hasattr(reaction, "emoji"):
continue
emoji = reaction.emoji # attribute existence is guaranteed by hasattr guard above
if emoji == "🤡" and reaction.count >= 30:
flags.append("clownpoo")
break
if reaction.emoji == "💩" and reaction.count >= 30:
if emoji == "💩" and reaction.count >= 30:
flags.append("clownpoo")
break