Skip to content

Commit e2ef9df

Browse files
authored
Fix forwarded media from private channels showing broken placeholder (#126)
* Fix forwarded media from private channels producing broken records When a message is forwarded from a private channel and contains a document, media.document is None. The _get_media_type() method incorrectly returned "document" for this case because the fallback return was outside the `if media.document` block, causing telegram_file_id to become the string "None" and downloads to fail permanently. Move `return "document"` inside the truthy branch and return None when the document reference is inaccessible. Add a safety guard in _process_media to catch any remaining str("None") file IDs. Fixes #125 * Update tests to match new _get_media_type behavior for null documents Tests now assert None instead of "document" when media.document is None, matching the fix for forwarded media from private channels.
1 parent d76873a commit e2ef9df

4 files changed

Lines changed: 17 additions & 7 deletions

File tree

src/listener.py

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -516,7 +516,8 @@ def _get_media_type(self, media) -> str | None:
516516
return "sticker"
517517
if is_animated:
518518
return "animation"
519-
return "document"
519+
return "document"
520+
return None # document reference unavailable (e.g., forwarded from private channel)
520521
elif isinstance(media, MessageMediaContact):
521522
return "contact"
522523
elif isinstance(media, MessageMediaGeo):
@@ -572,6 +573,10 @@ async def _download_media(self, message, chat_id: int) -> str | None:
572573
elif hasattr(media, "document"):
573574
telegram_file_id = str(getattr(media.document, "id", None))
574575

576+
# Guard against inaccessible media producing "None" string IDs
577+
if telegram_file_id == "None":
578+
telegram_file_id = None
579+
575580
# Check file size
576581
file_size = 0
577582
if hasattr(media, "document") and media.document:

src/telegram_backup.py

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1313,6 +1313,10 @@ async def _process_media(self, message: Message, chat_id: int) -> dict | None:
13131313
elif hasattr(media, "document"):
13141314
telegram_file_id = str(getattr(media.document, "id", None))
13151315

1316+
# Guard against inaccessible media producing "None" string IDs
1317+
if telegram_file_id == "None":
1318+
telegram_file_id = None
1319+
13161320
# Check file size (estimated)
13171321
file_size = self._get_media_size(media)
13181322
max_size = self.config.get_max_media_size_bytes()
@@ -1483,7 +1487,8 @@ def _get_media_type(self, media) -> str | None:
14831487
# If animated but no video attribute, still an animation
14841488
if is_animated:
14851489
return "animation"
1486-
return "document"
1490+
return "document"
1491+
return None # document reference unavailable (e.g., forwarded from private channel)
14871492
elif isinstance(media, MessageMediaContact):
14881493
return "contact"
14891494
elif isinstance(media, MessageMediaGeo):

tests/test_listener_extended.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -433,13 +433,13 @@ def test_document_media_sticker(self):
433433
assert listener._get_media_type(media) == "sticker"
434434

435435
def test_document_media_no_document_body(self):
436-
"""MessageMediaDocument with document=None returns 'document'."""
436+
"""MessageMediaDocument with document=None returns None (inaccessible)."""
437437
from telethon.tl.types import MessageMediaDocument
438438

439439
listener = self._listener()
440440
media = MagicMock(spec=MessageMediaDocument)
441441
media.document = None
442-
assert listener._get_media_type(media) == "document"
442+
assert listener._get_media_type(media) is None
443443

444444
def test_contact_media(self):
445445
"""MessageMediaContact returns 'contact'."""

tests/test_telegram_backup.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -917,11 +917,11 @@ def test_unknown_media_returns_none(self):
917917
media = MagicMock()
918918
self.assertIsNone(self.backup._get_media_type(media))
919919

920-
def test_document_without_document_attr_returns_document(self):
921-
"""MessageMediaDocument with no .document returns document."""
920+
def test_document_without_document_attr_returns_none(self):
921+
"""MessageMediaDocument with no .document returns None (inaccessible)."""
922922
media = MagicMock(spec=MessageMediaDocument)
923923
media.document = None
924-
self.assertEqual(self.backup._get_media_type(media), "document")
924+
self.assertIsNone(self.backup._get_media_type(media))
925925

926926

927927
class TestGetMediaExtension(unittest.TestCase):

0 commit comments

Comments
 (0)