Releases: GeiserX/Telegram-Archive
Releases · GeiserX/Telegram-Archive
v7.7.5
What's Changed
- ENH: idempotent rerun on git-annex'ed archives (symlinks etc) by @yarikoptic-gitmate in #146
- fix: address CodeRabbit nitpicks from PR #146 by @GeiserX in #150
New Contributors
- @yarikoptic-gitmate made their first contribution in #146
Full Changelog: v7.7.4...v7.7.5
v7.7.4
What's Changed
Full Changelog: v7.7.3...v7.7.4
v7.7.3
What's Changed
Full Changelog: v7.7.2...v7.7.3
v7.7.2
What's Changed
- Update Podman run command for user namespace to map into 1000:1000 by @yarikoptic in #140
Full Changelog: v7.7.1...v7.7.2
v7.7.1
What's Changed
Full Changelog: v7.7.0...v7.7.1
v7.7.0
Security
- Viewer now fails closed when credentials are missing — If
VIEWER_USERNAME/VIEWER_PASSWORDare not configured, the HTTP API and WebSocket endpoint reject access unlessALLOW_ANONYMOUS_VIEWER=trueis explicitly set. - Restricted media access is enforced consistently — Media, thumbnails, avatars, and non-chat folders now share centralized chat ACL checks, preventing restricted users from reading
_sharedfiles or unrelated chat media. - No-download users can no longer fetch original or thumbnail bytes — Accounts and share tokens with
no_download=truereceive metadata only; direct original media and generated thumbnail URLs return 403, while UI avatars remain available. - Internal push events require a secret off-loopback —
/internal/pushrequiresINTERNAL_PUSH_SECRETfor non-loopback/private-network callers, reducing spoofing risk between co-located containers. - WebSocket upgrades validate origin — Cross-origin WebSocket connections must be same-origin or explicitly allowed by
CORS_ORIGINS. - Non-interactive auth hash files are owner-only — Persisted
phone_code_hashsidecar files are now created with0600permissions.
Fixed
- Scheduled backups no longer overlap — The scheduler uses a backup lock so initial and cron-triggered jobs cannot run concurrently.
- FloodWait handling is explicit and bounded — One-shot Telegram API calls now retry through shared helpers and abort instead of sleeping when Telegram asks for waits above
MAX_FLOOD_WAIT_SECONDS. - FloodWait env parsing is resilient — Invalid
MAX_FLOOD_RETRIESandMAX_FLOOD_WAIT_SECONDSvalues fall back to safe defaults instead of crashing imports. - Media downloads finalize atomically — Temporary
.partfiles are moved into place only when an actual file exists, preserving Telethon-selected extensions and avoiding bogus stored paths. - Telegram contact, geo, and poll media are metadata-only — These message types no longer trigger file download attempts.
- Database URL precedence is consistent — Entrypoint migrations and realtime notifier/listener mode detection now honor
DATABASE_URLbeforeDB_TYPE, includingpostgres://,postgresql://,postgresql+asyncpg://, and SQLite URLs. - Database migration coverage includes app-state tables — SQLite-to-PostgreSQL migration now includes viewer accounts, sessions, tokens, folders, forum topics, push subscriptions, and settings.
- Share token URLs avoid query-string leakage — Generated links use
#token=fragments and preserve subpath deployments.
Changed
- Deletion listening is safer by default —
LISTEN_DELETIONSnow defaults tofalseso archives do not mirror Telegram deletions unless explicitly configured. - Docker examples pin the 7.7.0 release — Compose and README snippets now reference
drumsergio/telegram-archive:7.7.0anddrumsergio/telegram-archive-viewer:7.7.0. - Viewer compose binds to localhost by default — The example viewer service binds
127.0.0.1:8000:8000and documents reverse-proxy/auth requirements before public exposure. - CI and release checks are stricter — Docker publish workflows run ruff and pytest before publishing, shellcheck tracks
main, Docker Hub description sync covers both images, and release checks match the documented local test command.
Documentation
- Viewer authentication setup is documented — README and
.env.examplenow show required viewer credentials and the explicit anonymous opt-in. - Chat include filters are documented as allow-lists — Examples now correctly show
CHAT_TYPES=groups,channelswhen including one specific channel alongside groups. - Operational safety docs were refreshed — README and
.env.examplenow describe deletion mirroring, flood-wait controls, proxy header trust, and internal push secrets.
Tests
- Added regression coverage for fail-closed viewer auth, no-download media restrictions, thumbnail ACLs, WebSocket subscription filtering, internal push auth, scheduler locking, flood-wait aborts, atomic downloads,
DATABASE_URLbehavior, non-interactive auth hash reuse, and migration model enumeration.
📋 Full changelog: docs/CHANGELOG.md
v7.6.4
Fixed
- Improved General topic test suite — Renamed unprofessional test data, removed redundant
@pytest.mark.asynciodecorators (project usesasyncio_mode = "auto"), converted setup to a proper pytest fixture, and added edge case tests for nonexistent topics,topic_id=0, and topic+search filter interaction. Contributed by @tondeaf in #122 (follow-up).
📋 Full changelog: docs/CHANGELOG.md
v7.6.3
Fixed
- Edit notifications no longer silently dropped on long messages — The 500-char truncation guard only protected
data["message"]["text"](new_message path), leavingdata["new_text"](edit path) unprotected. A 4096-char emoji edit could produce a 16KB payload exceeding PostgreSQL's 8KB NOTIFY limit, causing a silentpg_notifyerror. Both paths are now truncated via a shared_truncate_notify_data()helper. (#123 follow-up) - Use
pg_notify()with bound parameters for PostgreSQL NOTIFY — Replaces f-string SQL interpolation that was vulnerable to asyncpg$Nplaceholder parsing and fragile manual single-quote escaping. Contributed by @tondeaf in #123. - Push secret comparison is now timing-safe —
/internal/pushendpoint used!=for bearer token comparison; switched tosecrets.compare_digest()consistent with the rest of the auth layer. - Test assertions use stable
TextClause.textattribute — Replacedstr(stmt)withstmt.textfor SQLAlchemy SQL assertions, avoiding reliance on undocumented__str__behavior.
📋 Full changelog: docs/CHANGELOG.md
v7.6.2
Fixed
- FloodWaitError no longer crashes
get_dialogs()orget_me()— PR #124 setflood_sleep_threshold=0globally but only wrapped 2 of ~20 API call sites. The unwrappedget_dialogs()andget_me()calls could crash the entire backup or prevent startup. Both are now wrapped with bounded flood-wait retry logic. - Negative
e.secondsfrom Telegram no longer causes zero-delay retry storms — Sleep duration is now clamped tomax(0, ...)on both the iterator wrapper and the new one-shot retry helper. - Invalid
FLOOD_WAIT_LOG_THRESHOLDenv var no longer crashes mid-backup — Bareint()parsing replaced with defensivetry/exceptthat falls back to the default of 10 seconds. iter_messages_with_flood_retrynow rejectsreverse=False— The resume tracking (max(resume_from, msg.id)) is only correct for ascending iteration. AValueErroris now raised ifreverse=Trueis not passed, preventing silent data corruption from future misuse.- Documented
FLOOD_WAIT_LOG_THRESHOLD— Added to.env.examplealongside the other logging variables.
📋 Full changelog: docs/CHANGELOG.md
v7.6.1
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 returnsNoneinstead of"document". Previously this caused a brokentelegram_file_idof"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