Skip to content

Releases: GeiserX/Telegram-Archive

v7.6.1

19 Apr 19:44

Choose a tag to compare

Fixed

  • Forwarded media from private channels no longer creates broken placeholders — When a message forwarded from a private channel contains a document with an inaccessible file reference (media.document=None), _get_media_type() now correctly returns None instead of "document". Previously this caused a broken telegram_file_id of "None", a failed download attempt, and a misleading "Will download on next backup" placeholder that would never resolve. Applies to both scheduled backup and real-time listener (#125)

📋 Full changelog: docs/CHANGELOG.md

v7.6.0 — Topic Filtering & Symlink Fix

18 Apr 13:01

Choose a tag to compare

Added

  • Topic filtering for forum supergroups — New SKIP_TOPIC_IDS environment variable to exclude specific topics from backup while keeping the rest of the chat. Format: chat_id:topic_id,.... Works in both scheduled backup and real-time listener flows (#117)

Fixed

  • Dangling dedup symlinks no longer cause infinite redownload loops — When DEDUPLICATE_MEDIA is enabled and VERIFY_MEDIA runs, dangling symlinks (where the target was renamed by Telethon) are now detected via os.path.lexists() instead of os.path.exists(), which follows symlinks. The download return value is now captured to use the actual on-disk filename for symlink targets. Stale symlinks are removed before recreation to prevent Errno 17 (file exists) errors. Applies to both scheduled backup and real-time listener (#115)

📋 Full changelog: docs/CHANGELOG.md

v7.5.0 — SOCKS5 Proxy Support

13 Apr 10:31

Choose a tag to compare

What's New

SOCKS5 Proxy Support (#104)

You can now route all Telegram connections through a SOCKS5 proxy — useful in regions where Telegram is blocked or behind corporate firewalls.

Configuration (all optional):

TELEGRAM_PROXY_TYPE=socks5
TELEGRAM_PROXY_ADDR=127.0.0.1
TELEGRAM_PROXY_PORT=1080
TELEGRAM_PROXY_USERNAME=
TELEGRAM_PROXY_PASSWORD=
TELEGRAM_PROXY_RDNS=false

Proxy support is applied consistently across all code paths: backup, real-time listener, auth setup, and standalone scripts.

Improvements

  • Validation hardening: port range (1–65535), username/password pairing, boolean RDNS parsing, and case-insensitive proxy type
  • Security: proxy endpoint details logged at DEBUG (not INFO) to avoid exposing infrastructure topology
  • Test isolation: proxy integration tests use scoped fixtures instead of global sys.modules mutation
  • Dependency: added python-socks[asyncio]>=2.7.1 (required by Telethon for SOCKS5 transport)

Contributors

Thanks to @samnyan for the proxy feature contribution!

What's Changed

New Contributors

Full Changelog: v7.4.2...v7.5.0

v7.4.2 — Correctness & Hygiene

31 Mar 11:47
dfa165b

Choose a tag to compare

Correctness & Release Hygiene

Fixes

  • Listener shutdown KeyError (Medium): _log_stats() referenced non-existent keys from MassOperationProtector.get_stats(). A clean shutdown would raise KeyError. Fixed to use actual keys (rate_limits_triggered, operations_blocked, chats_rate_limited).
  • Pin/unpin realtime (Low): Full pipeline now works end-to-end: listener emits PIN → notifier delivers → handle_realtime_notification() forwards to WebSocket → browser reloads pinned messages. Previously the relay in main.py was missing, making the frontend handler dead code.
  • pyproject.toml version sync (Low): Was stuck at 7.2.0 since v7.2.0. Now synced with __init__.py at 7.4.2.
  • WebSocket subscribe ACL (Low): Server now sends subscribe_denied (instead of subscribed) when a restricted user attempts to subscribe to a chat outside their allowed list. Frontend logs the denial.

What's Changed

  • fix: correctness and release hygiene (v7.4.2) by @GeiserX in #100

Full Changelog: v7.4.1...v7.4.2

v7.4.1 — Security Hardening Round 2

31 Mar 11:22
1242bf1

Choose a tag to compare

Security Hardening (Round 2)

Fixes

  • Avatar ACL bypass (Medium): Restricted users can no longer access avatars outside their allowed chats. serve_media() and serve_thumbnail() now extract chat_id from avatar filenames and enforce per-chat scoping.
  • Push endpoint spoofing (Medium): /internal/push now supports an optional INTERNAL_PUSH_SECRET env var as a bearer token. Prevents co-tenant containers from spoofing live events to connected browsers.
  • Reaction recovery data loss (Medium): insert_reactions() now retries ALL reactions after a sequence reset, not just the row that triggered the duplicate-key error. Previously, the return after a single retry silently dropped remaining reactions.
  • Push unsubscribe ownership (Low): POST /api/push/unsubscribe is now scoped to the requesting user's username, preventing cross-user endpoint removal.

New Environment Variable

  • INTERNAL_PUSH_SECRET: Optional shared secret for /internal/push endpoint. Set the same value on both backup and viewer containers in multi-tenant Docker environments. If unset, IP-only auth is used (backward compatible).

What's Changed

  • fix: security hardening round 2 (v7.4.1) by @GeiserX in #99

Full Changelog: v7.4.0...v7.4.1

v7.4.0 — Security Hardening

31 Mar 11:06
0897f54

Choose a tag to compare

Security Hardening

Addresses multiple security findings from code review.

Fixes

  • XSS (High): linkifyText() now percent-encodes raw " and ' in URLs before inserting into href attributes. escapeHtml() via textContent/innerHTML does not escape quotes.
  • Stats filter (Medium): Fixed JSON string-key vs int type mismatch that caused per-chat filtering to silently fail. Also removes media_files/total_size_mb for restricted users (no per-chat breakdown available).
  • Deletion path (Medium): Unknown-chat deletions now resolve the chat ID from DB first, apply rate limiting, skip ambiguous message IDs (same ID in multiple chats), and send viewer notifications.
  • Folders (Low): Restricted users no longer see empty folder names/emoticons for folders with 0 accessible chats.
  • Push endpoint (Low): /internal/push accepts loopback + RFC1918/Docker private IPs to support split-container SQLite mode via VIEWER_HOST/VIEWER_PORT.

Breaking Changes

  • delete_message_by_id_any_chat() replaced by resolve_message_chat_id() in the database adapter. The old method deleted from ALL chats with a matching message ID — the new approach resolves to a single chat first and skips ambiguous cases.

What's Changed

  • fix: security hardening — XSS, push spoofing, metadata leaks, deletion bugs by @GeiserX in #98

Full Changelog: v7.3.2...v7.4.0

v7.3.2

26 Mar 19:30

Choose a tag to compare

What's Changed

  • fix(viewer): display caption for album posts with grouped messages by @vadimvolk in #97

New Contributors

Full Changelog: v7.3.1...v7.3.2

v7.3.1

25 Mar 13:22

Choose a tag to compare

What's Changed

  • fix: skip get_dialogs() in whitelist mode to prevent hanging by @GeiserX in #96

Full Changelog: v7.1.7...v7.3.1

v7.3.0

15 Mar 11:53
a915c69

Choose a tag to compare

What's New

Gap-fill recovery

  • Detects gaps in message ID sequences using SQL LAG() window function
  • Recovers skipped messages from Telegram API automatically
  • Available as CLI subcommand (fill-gaps --chat-id --threshold) and scheduler option (FILL_GAPS=true)
  • Respects all backup config rules (CHAT_IDS, CHAT_TYPES, exclude lists)
  • Robust error handling: continues on per-chat/per-gap errors, reports summary with error count
  • Stats automatically recalculated after recovery

Token URL auto-login

  • Shareable links with ?token=XXX parameter for direct viewer access
  • Token is stripped from URL after login via history.replaceState
  • Warning note about token exposure in server access logs

UX improvements

  • @username display in chat list and message headers
  • Shareable link generation UI in admin panel

Testing

  • 31 new tests for gap-fill (detect gaps, fill gaps, config, edge cases)
  • Full async test coverage with real SQLite + AsyncMock for Telegram client

v7.2.1 — Database Error Handling

13 Mar 17:25

Choose a tag to compare

Bug Fixes

  • Login: When the database is unreachable, the login endpoint now falls through to master env var credentials instead of returning a generic "Unexpected error". Viewer-only users see a clear "Database temporarily unavailable" message (HTTP 503).
  • All data endpoints: Connection errors now return HTTP 503 "Database temporarily unavailable" instead of generic HTTP 500 "Internal server error".
  • Audit log resilience: Audit log writes in the login flow are wrapped in try/except so they never crash the response.

New Features

  • Global exception handler: Catches unhandled DB connection errors across all endpoints (including admin) and returns 503.
  • Health endpoint: GET /api/health returns {"status": "ok", "database": "connected"} (200) or {"status": "degraded", "database": "unreachable"} (503). Useful for Docker healthchecks and monitoring.

Internal

  • Added _is_db_connection_error() helper that walks the exception chain looking for OSError (covers socket.gaierror, ConnectionRefusedError, etc.)

Closes #92