Skip to content

Fix forwarded media from private channels showing broken placeholder#126

Merged
GeiserX merged 2 commits intomainfrom
fix/forwarded-media-null-document
Apr 19, 2026
Merged

Fix forwarded media from private channels showing broken placeholder#126
GeiserX merged 2 commits intomainfrom
fix/forwarded-media-null-document

Conversation

@GeiserX
Copy link
Copy Markdown
Owner

@GeiserX GeiserX commented Apr 19, 2026

Summary

  • Fix _get_media_type() returning "document" when media.document is None (forwarded from private channels), causing broken media records with telegram_file_id = "None" and permanent download failures
  • Add safety guard in _process_media to catch any remaining str(None) file IDs

Fixes #125

Type of Change

  • Bug fix (non-breaking change that fixes an issue)
  • New feature (non-breaking change that adds functionality)
  • Breaking change (fix or feature that causes existing functionality to change)
  • Documentation update
  • Infrastructure/CI change

Database Changes

  • Schema changes (Alembic migration required)
  • Data migration script added in scripts/
  • No database changes

Data Consistency Checklist

  • All chat_id values use marked format (via _get_marked_id())
  • All datetime values pass through _strip_tz() before DB operations
  • INSERT and UPDATE operations handle the same fields identically

Testing

  • Tests pass locally (python -m pytest tests/ -v)
  • Linting passes (ruff check .)
  • Formatting passes (ruff format --check .)
  • Manually tested in development environment

Security Checklist

  • No secrets or credentials committed
  • User input properly validated/sanitized
  • Authentication/authorization properly checked

Deployment Notes

  • Docker image rebuild needed
  • Existing broken media records with telegram_file_id = "None" in the database will still show as broken; a future cleanup script or re-backup will fix those

Summary by CodeRabbit

  • Bug Fixes
    • Fixed handling of media forwarded from private channels or with unavailable document references to prevent errors in filename generation and download operations.
    • Corrected deduplication logic to properly treat missing media identifiers instead of using literal string placeholders.

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
@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented Apr 19, 2026

Warning

Rate limit exceeded

@GeiserX has exceeded the limit for the number of commits that can be reviewed per hour. Please wait 49 minutes and 32 seconds before requesting another review.

Your organization is not enrolled in usage-based pricing. Contact your admin to enable usage-based pricing to continue reviews beyond the rate limit, or try again in 49 minutes and 32 seconds.

⌛ How to resolve this issue?

After the wait time has elapsed, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

We recommend that you space out your commits to avoid hitting the rate limit.

🚦 How do rate limits work?

CodeRabbit enforces hourly rate limits for each developer per organization.

Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout.

Please see our FAQ for further information.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: c61e8b7f-e640-4e72-85ea-d6de67dac436

📥 Commits

Reviewing files that changed from the base of the PR and between 308200c and ec7515e.

📒 Files selected for processing (2)
  • tests/test_listener_extended.py
  • tests/test_telegram_backup.py
📝 Walkthrough

Walkthrough

Modified media handling in listener and backup modules to return None instead of "document" for MessageMediaDocument when document references are unavailable, and to prevent the literal string "None" from being treated as a valid Telegram file identifier during deduplication and download operations.

Changes

Cohort / File(s) Summary
Media handling for unavailable documents
src/listener.py, src/telegram_backup.py
Added guards to convert string "None" sentinel to actual None in deduplication IDs, and modified return values in _get_media_type() to return None instead of "document" when media references are unavailable (e.g., forwarded from private channels).

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~10 minutes

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Title check ✅ Passed Title directly and specifically describes the main bug fix: handling forwarded media from private channels that previously showed broken placeholders.
Description check ✅ Passed Description is well-structured, follows template, clearly explains the bug and fix, includes linked issue reference, and covers all required sections.
Linked Issues check ✅ Passed PR fixes the core coding issue from #125: preventing broken 'None' telegram_file_ids for inaccessible forwarded media by returning None instead of 'document' when document reference is unavailable.
Out of Scope Changes check ✅ Passed All changes are directly scoped to fixing the forwarded private media bug: modifications to _get_media_type() and _process_media() to handle None document references properly.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix/forwarded-media-null-document

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@github-actions
Copy link
Copy Markdown

🐳 Dev images published!

  • drumsergio/telegram-archive:dev
  • drumsergio/telegram-archive-viewer:dev

The dev/test instance will pick up these changes automatically (Portainer GitOps).

To test locally:

docker pull drumsergio/telegram-archive:dev
docker pull drumsergio/telegram-archive-viewer:dev

Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick comments (2)
src/telegram_backup.py (1)

1316-1319: Guard is correct but silent.

The "None" string guard works, but since this only fires for inaccessible media (forwarded from private sources), a logger.debug here would help diagnose why certain forwarded media get skipped without producing DB records. Purely optional.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/telegram_backup.py` around lines 1316 - 1319, The guard that converts the
literal string "None" to None for telegram_file_id is fine but lacks visibility;
update the block where telegram_file_id is checked (the variable
telegram_file_id in src/telegram_backup.py) to emit a logger.debug showing that
an inaccessible/forwarded media produced the "None" string and any contextual
identifiers available (e.g., message_id, chat_id, or user info) before setting
telegram_file_id = None so it's easier to trace skipped media in logs.
src/listener.py (1)

519-520: Mirrored fix — LGTM.

Both the _get_media_type return-None branch and the "None" string guard in _download_media mirror the backup module's fix, keeping behavior consistent across the real-time and scheduled paths. Good belt-and-suspenders approach.

Side note: in on_new_message (around line 879-887), when a MessageMediaDocument arrives without an accessible document, media_type is now None and the media block is skipped entirely — which is the desired behavior, but means forwarded-from-private media on the listener path will silently produce a message row with no media record. Worth a single logger.debug so users grepping logs can correlate missing media to the private-forward case.

Also applies to: 576-579

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/listener.py` around lines 519 - 520, When handling incoming messages in
on_new_message, add a logger.debug when a MessageMediaDocument arrives but
_get_media_type returns None and the media block is skipped; log enough context
(e.g., message id, sender id/username and a short note like "skipping media:
forwarded-from-private, document reference unavailable") so users can correlate
missing media rows to private-forward cases; place this debug immediately before
the branch that skips media (the same spot that checks for media_type is None
and calls/relies on _download_media).
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Nitpick comments:
In `@src/listener.py`:
- Around line 519-520: When handling incoming messages in on_new_message, add a
logger.debug when a MessageMediaDocument arrives but _get_media_type returns
None and the media block is skipped; log enough context (e.g., message id,
sender id/username and a short note like "skipping media:
forwarded-from-private, document reference unavailable") so users can correlate
missing media rows to private-forward cases; place this debug immediately before
the branch that skips media (the same spot that checks for media_type is None
and calls/relies on _download_media).

In `@src/telegram_backup.py`:
- Around line 1316-1319: The guard that converts the literal string "None" to
None for telegram_file_id is fine but lacks visibility; update the block where
telegram_file_id is checked (the variable telegram_file_id in
src/telegram_backup.py) to emit a logger.debug showing that an
inaccessible/forwarded media produced the "None" string and any contextual
identifiers available (e.g., message_id, chat_id, or user info) before setting
telegram_file_id = None so it's easier to trace skipped media in logs.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 1ac07b93-f118-41e0-bf04-c4a7e0ce9a49

📥 Commits

Reviewing files that changed from the base of the PR and between d76873a and 308200c.

📒 Files selected for processing (2)
  • src/listener.py
  • src/telegram_backup.py

Tests now assert None instead of "document" when media.document is None,
matching the fix for forwarded media from private channels.
@github-actions
Copy link
Copy Markdown

🐳 Dev images published!

  • drumsergio/telegram-archive:dev
  • drumsergio/telegram-archive-viewer:dev

The dev/test instance will pick up these changes automatically (Portainer GitOps).

To test locally:

docker pull drumsergio/telegram-archive:dev
docker pull drumsergio/telegram-archive-viewer:dev

@codecov
Copy link
Copy Markdown

codecov Bot commented Apr 19, 2026

Codecov Report

❌ Patch coverage is 87.50000% with 1 line in your changes missing coverage. Please review.
✅ Project coverage is 85.93%. Comparing base (d76873a) to head (ec7515e).
⚠️ Report is 1 commits behind head on main.

Files with missing lines Patch % Lines
src/listener.py 75.00% 1 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main     #126      +/-   ##
==========================================
- Coverage   85.93%   85.93%   -0.01%     
==========================================
  Files          21       21              
  Lines        5865     5871       +6     
==========================================
+ Hits         5040     5045       +5     
- Misses        825      826       +1     

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@GeiserX GeiserX merged commit e2ef9df into main Apr 19, 2026
10 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Question]: Downloading Media from Forwarded Private Group/Channel

1 participant