{"id":35678550,"url":"https://github.com/geiserx/telegram-archive","last_synced_at":"2026-04-25T20:00:47.025Z","repository":{"id":326581229,"uuid":"1103497752","full_name":"GeiserX/Telegram-Archive","owner":"GeiserX","description":"Own your Telegram history. Automated, incremental backups with a local web viewer that feels just like the real app. Docker-ready and supports public chat sharing","archived":false,"fork":false,"pushed_at":"2026-04-25T18:00:12.000Z","size":2547,"stargazers_count":111,"open_issues_count":0,"forks_count":19,"subscribers_count":2,"default_branch":"main","last_synced_at":"2026-04-25T19:11:00.314Z","etag":null,"topics":["archive","automation","backup","chat-history","docker","docker-compose","hacktoberfest","homelab","incremental-backup","media","open-source","postgresql","privacy","python","self-hosted","sqlite","telegram","telegram-backup","web-viewer","websocket"],"latest_commit_sha":null,"homepage":"","language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"gpl-3.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/GeiserX.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":"CONTRIBUTING.md","funding":".github/FUNDING.yml","license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":".github/CODEOWNERS","security":"SECURITY.md","support":null,"governance":null,"roadmap":"docs/ROADMAP.md","authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":"AGENTS.md","dco":null,"cla":null},"funding":{"github":"geiserx","patreon":"geiser","buy_me_a_coffee":"geiser","thanks_dev":"u/gh/geiserx"}},"created_at":"2025-11-25T00:28:14.000Z","updated_at":"2026-04-25T17:59:59.000Z","dependencies_parsed_at":null,"dependency_job_id":"de73ca6d-1c0c-415f-ab41-ffb9e85d75e0","html_url":"https://github.com/GeiserX/Telegram-Archive","commit_stats":null,"previous_names":["geiserx/telegram-backup-automation"],"tags_count":151,"template":false,"template_full_name":null,"purl":"pkg:github/GeiserX/Telegram-Archive","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/GeiserX%2FTelegram-Archive","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/GeiserX%2FTelegram-Archive/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/GeiserX%2FTelegram-Archive/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/GeiserX%2FTelegram-Archive/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/GeiserX","download_url":"https://codeload.github.com/GeiserX/Telegram-Archive/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/GeiserX%2FTelegram-Archive/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":32274982,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-04-25T18:29:39.964Z","status":"ssl_error","status_checked_at":"2026-04-25T18:29:32.149Z","response_time":59,"last_error":"SSL_read: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["archive","automation","backup","chat-history","docker","docker-compose","hacktoberfest","homelab","incremental-backup","media","open-source","postgresql","privacy","python","self-hosted","sqlite","telegram","telegram-backup","web-viewer","websocket"],"created_at":"2026-01-05T20:15:39.388Z","updated_at":"2026-04-25T20:00:47.008Z","avatar_url":"https://github.com/GeiserX.png","language":"Python","readme":"\u003cp align=\"center\"\u003e\n  \u003cimg src=\"docs/images/banner.svg\" alt=\"Telegram Archive banner\" width=\"900\"/\u003e\n\u003c/p\u003e\n\n\u003cp align=\"center\"\u003e\n  \u003cimg src=\"assets/Telegram-Archive.png\" alt=\"Telegram Archive Logo\" width=\"150\"/\u003e\n\u003c/p\u003e\n\n\u003ch1 align=\"center\"\u003eTelegram Archive\u003c/h1\u003e\n\n\u003cp align=\"center\"\u003e\n  \u003ca href=\"https://hub.docker.com/r/drumsergio/telegram-archive\"\u003e\u003cimg src=\"https://img.shields.io/docker/pulls/drumsergio/telegram-archive?style=flat-square\u0026logo=docker\" alt=\"Docker Pulls\"\u003e\u003c/a\u003e\n  \u003ca href=\"https://github.com/GeiserX/Telegram-Archive/stargazers\"\u003e\u003cimg src=\"https://img.shields.io/github/stars/GeiserX/Telegram-Archive?style=flat-square\u0026logo=github\" alt=\"GitHub Stars\"\u003e\u003c/a\u003e\n  \u003ca href=\"LICENSE\"\u003e\u003cimg src=\"https://img.shields.io/github/license/GeiserX/Telegram-Archive?style=flat-square\" alt=\"License\"\u003e\u003c/a\u003e\n  \u003ca href=\"https://github.com/GeiserX/Telegram-Archive/releases\"\u003e\u003cimg src=\"https://img.shields.io/github/v/release/GeiserX/Telegram-Archive?style=flat-square\" alt=\"Release\"\u003e\u003c/a\u003e\n  \u003ca href=\"https://codecov.io/gh/GeiserX/Telegram-Archive\"\u003e\u003cimg src=\"https://codecov.io/gh/GeiserX/Telegram-Archive/graph/badge.svg\" alt=\"codecov\"\u003e\u003c/a\u003e\n\u003c/p\u003e\n\n\u003cp align=\"center\"\u003e\n  \u003cstrong\u003eAutomated Telegram backup with Docker. Performs incremental backups of messages and media on a configurable schedule.\u003c/strong\u003e\n\u003c/p\u003e\n\n## Features\n\n### 📦 Backup Engine\n- **Incremental backups** — Only downloads new messages since last backup\n- **Scheduled execution** — Configurable cron schedule (default: every 6 hours)\n- **Real-time listener** — Catch edits, deletions, and new messages instantly between backups\n- **Album support** — Groups photos/videos sent together as albums\n- **Service messages** — Tracks group photo changes, title changes, user joins/leaves\n- **Forwarded message info** — Shows original sender name for forwarded messages\n- **Channel signatures** — Displays post author when channels have signatures enabled\n- **Media deduplication** — Symlinks identical files to save disk space\n- **Avatars always fresh** — Profile photos updated on every backup run\n\n### 🎬 Media Support\n- Photos, videos, documents, stickers, GIFs\n- Voice messages and audio files with in-browser player\n- Polls with vote counts and results\n- Configurable size limits and selective download\n\n### 🌐 Web Viewer\n- **Telegram-like dark UI** — Feels like the real app\n- **Mobile-friendly** — Responsive design with iOS/Android optimizations\n- **Integrated lightbox** — View photos and videos without leaving the page\n- **Keyboard navigation** — Arrow keys to browse media, Esc to close\n- **Real-time updates** — WebSocket sync shows new messages instantly\n- **Push notifications** — Get notified even when browser is closed\n- **Chat search** — Find messages by text content\n- **JSON export** — Download chat history with date range filters\n\n### 🔒 Security \u0026 Privacy\n- **Multi-user access control** — Master account + DB-backed viewer accounts with per-user chat whitelists\n- **Admin panel** — Create, edit, delete viewer accounts with fine-grained chat permissions\n- **Audit logging** — Track all login attempts, admin actions, and API access\n- **Authenticated media** — Media files require login and respect per-user permissions\n- **Mass deletion protection** — Rate limiting prevents accidental data loss\n- **Runs as non-root** — Docker best practices\n\n### 🗄️ Database\n- **SQLite** (default) — Zero config, single file\n- **PostgreSQL** — For larger deployments with real-time LISTEN/NOTIFY\n\n## 🗺️ Roadmap\n\nSee **[docs/CHANGELOG.md](docs/CHANGELOG.md)** for complete version history.\n\nHave a feature request? [Open an issue](https://github.com/GeiserX/Telegram-Archive/issues)!\n\n## 📸 Screenshots\n\n\u003cdetails\u003e\n\u003csummary\u003eClick to view Desktop and Mobile screenshots\u003c/summary\u003e\n\n### Desktop\n![Desktop View](assets/Telegram-Archive-1.png)\n\n### Mobile\n\u003cimg src=\"assets/Telegram-Archive-2.png\" width=\"300\" alt=\"Mobile View\"\u003e\n\n\u003c/details\u003e\n\n## Docker Images\n\nTwo separate Docker images are available (v4.0+):\n\n| Image | Purpose | Size |\n|-------|---------|------|\n| `drumsergio/telegram-archive` | Backup scheduler (requires Telegram credentials) | ~300MB |\n| `drumsergio/telegram-archive-viewer` | Web viewer only (no Telegram client) | ~150MB |\n\n\u003e 📦 **Upgrading from v3.x?** See [Upgrading from v3.x to v4.0](#upgrading-from-v3x-to-v40) for migration instructions.\n\n## Quick Start\n\n### 1. Get Telegram API Credentials\n\n1. Go to https://my.telegram.org/apps\n2. Log in with your phone number\n3. Create a new application (any name/platform)\n4. Note your **API ID** (numbers) and **API Hash** (letters+numbers)\n\n### 2. Deploy with Docker\n\n```bash\n# Clone the repository\ngit clone https://github.com/GeiserX/Telegram-Archive\ncd Telegram-Archive\n\n# Create data directories\nmkdir -p data/session data/backups\nchmod -R 755 data/\n\n# Configure environment\ncp .env.example .env\n```\n\n**Edit `.env`** with your credentials:\n```bash\nTELEGRAM_API_ID=12345678          # Your API ID\nTELEGRAM_API_HASH=abcdef123456    # Your API Hash  \nTELEGRAM_PHONE=+1234567890        # Your phone (with country code)\n```\n\n**Optional: enable a SOCKS5 proxy for all Telegram connections** (useful in regions where Telegram is blocked or behind corporate firewalls)\n```bash\nTELEGRAM_PROXY_TYPE=socks5\nTELEGRAM_PROXY_ADDR=127.0.0.1\nTELEGRAM_PROXY_PORT=1080\nTELEGRAM_PROXY_USERNAME=\nTELEGRAM_PROXY_PASSWORD=\nTELEGRAM_PROXY_RDNS=false\n```\n\n### 3. Authenticate with Telegram\n\n**Option A: Using the provided scripts (recommended for fresh installs)**\n\n```bash\n# Run authentication\n./init_auth.sh    # Linux/Mac\n# init_auth.bat   # Windows\n```\n\n**Option B: Direct Docker command (for existing deployments or re-authentication)**\n\nIf your session expires or you need to re-authenticate an existing container:\n\n```bash\n# Generic command - adjust volume paths and credentials\ndocker run -it --rm \\\n  -e TELEGRAM_API_ID=YOUR_API_ID \\\n  -e TELEGRAM_API_HASH=YOUR_API_HASH \\\n  -e TELEGRAM_PHONE=+YOUR_PHONE_NUMBER \\\n  -e SESSION_NAME=telegram_backup \\\n  -v /path/to/your/session:/data/session \\\n  drumsergio/telegram-archive:latest \\\n  python -m src auth\n```\n\n**Example for docker compose deployment:**\n\n```bash\n# If using docker compose with a session volume\ndocker run -it --rm \\\n  --env-file .env \\\n  -v telegram-archive_session:/data/session \\\n  drumsergio/telegram-archive:latest \\\n  python -m src auth\n\n# Then restart the backup container\ndocker compose restart telegram-backup\n```\n\n**What happens during authentication:**\n1. The script connects to Telegram's servers\n2. Telegram sends a verification code to your Telegram app (check \"Telegram\" chat)\n3. Enter the code when prompted\n4. If you have 2FA enabled, enter your password when prompted\n5. Session is saved to the mounted volume for future use\n\n### 4. Start Services\n\n```bash\ndocker compose up -d\n```\n\n**View your backup** at http://localhost:8000\n\n### Common Issues\n\n| Problem | Solution |\n|---------|----------|\n| `Permission denied` | Run `chmod -R 755 data/` |\n| `init_auth.sh: command not found` | Run `chmod +x init_auth.sh` first |\n| Viewer shows no data | Both containers need same database path - see [Database Configuration](#database-configuration) |\n| `Failed to authorize` | Re-run `./init_auth.sh` |\n\n## Web Viewer\n\nThe standalone viewer image (`drumsergio/telegram-archive-viewer`) lets you browse backups without running the backup scheduler.\n\n```yaml\n# Example: Viewer-only deployment\nservices:\n  telegram-viewer:\n    image: drumsergio/telegram-archive-viewer:latest\n    ports:\n      - \"8000:8000\"\n    environment:\n      BACKUP_PATH: /data/backups\n      DATABASE_DIR: /data/db\n      VIEWER_USERNAME: admin\n      VIEWER_PASSWORD: your-secure-password\n      VIEWER_TIMEZONE: Europe/Madrid\n    volumes:\n      - /path/to/backups:/data/backups:ro\n      - /path/to/db:/data/db:ro\n```\n\nBrowse your backups at **http://localhost:8000**\n\n## Configuration\n\nAll settings are configured via environment variables. Set them in your `.env` file or as `environment:` entries in `docker-compose.yml`. See [`.env.example`](.env.example) for a ready-to-use template.\n\n\u003e **`ENABLE_LISTENER` is a master switch.** When set to `false` (the default), all `LISTEN_*` and `MASS_OPERATION_*` variables have no effect. You only need to configure those when you set `ENABLE_LISTENER=true`.\n\n### Environment Variables\n\nThe **Scope** column shows whether each variable applies to the backup scheduler (**B**), the web viewer (**V**), or both (**B/V**).\n\n| Variable | Default | Scope | Description |\n|----------|---------|:-----:|-------------|\n| **Telegram Credentials** | | | |\n| `TELEGRAM_API_ID` | *required* | B | API ID from [my.telegram.org](https://my.telegram.org/apps) |\n| `TELEGRAM_API_HASH` | *required* | B | API Hash from [my.telegram.org](https://my.telegram.org/apps) |\n| `TELEGRAM_PHONE` | *required* | B | Phone number with country code (e.g., `+1234567890`) |\n| `TELEGRAM_PROXY_TYPE` | - | B | Optional proxy type for all Telegram clients. Currently supports `socks5` |\n| `TELEGRAM_PROXY_ADDR` | - | B | SOCKS5 proxy host or IP address |\n| `TELEGRAM_PROXY_PORT` | - | B | SOCKS5 proxy port |\n| `TELEGRAM_PROXY_USERNAME` | - | B | Optional SOCKS5 username |\n| `TELEGRAM_PROXY_PASSWORD` | - | B | Optional SOCKS5 password |\n| `TELEGRAM_PROXY_RDNS` | `false` | B | Use remote DNS resolution through the SOCKS5 proxy |\n| **Backup Schedule \u0026 Storage** | | | |\n| `SCHEDULE` | `0 */6 * * *` | B | Cron expression for backup frequency |\n| `BACKUP_PATH` | `/data/backups` | B/V | Base path for backup data and media |\n| `DOWNLOAD_MEDIA` | `true` | B | Download media files (photos, videos, documents) |\n| `MAX_MEDIA_SIZE_MB` | `100` | B | Skip media files larger than this (MB) |\n| `BATCH_SIZE` | `100` | B | Messages processed per database batch |\n| `CHECKPOINT_INTERVAL` | `1` | B | Save backup progress every N batch inserts (lower = safer resume after crash) |\n| `DATABASE_TIMEOUT` | `60.0` | B/V | Database operation timeout in seconds |\n| `SESSION_NAME` | `telegram_backup` | B | Telethon session file name |\n| `DEDUPLICATE_MEDIA` | `true` | B | Symlink identical media files across chats to save disk space |\n| `SYNC_DELETIONS_EDITS` | `false` | B | Batch-check ALL messages for edits/deletions each run (expensive!) |\n| `VERIFY_MEDIA` | `false` | B | Re-download missing or corrupted media files |\n| `STATS_CALCULATION_HOUR` | `3` | B | Hour (0-23) to recalculate backup statistics daily |\n| `PRIORITY_CHAT_IDS` | - | B | Comma-separated chat IDs to process first in all operations |\n| `SKIP_MEDIA_CHAT_IDS` | - | B | Skip media downloads for specific chats (messages still backed up with text) |\n| `SKIP_MEDIA_DELETE_EXISTING` | `true` | B | Delete existing media files and DB records for chats in skip list to reclaim storage |\n| `SKIP_TOPIC_IDS` | - | B | Skip specific topics in forum supergroups (format: `chat_id:topic_id,...`) |\n| `LOG_LEVEL` | `INFO` | B/V | Logging verbosity: `DEBUG`, `INFO`, `WARNING`/`WARN`, `ERROR` |\n| **Chat Filtering** | | | See [Chat Filtering](#chat-filtering) below |\n| `CHAT_IDS` | - | B | **Whitelist mode**: backup ONLY these chats (ignores all other filters) |\n| `CHAT_TYPES` | `private,groups,channels` | B | **Type-based mode**: comma-separated chat types to backup |\n| `GLOBAL_EXCLUDE_CHAT_IDS` | - | B | Exclude specific chats (any type) |\n| `GLOBAL_INCLUDE_CHAT_IDS` | - | B | Force-include specific chats (any type) |\n| `PRIVATE_EXCLUDE_CHAT_IDS` | - | B | Exclude specific private chats |\n| `PRIVATE_INCLUDE_CHAT_IDS` | - | B | Force-include specific private chats |\n| `GROUPS_EXCLUDE_CHAT_IDS` | - | B | Exclude specific groups |\n| `GROUPS_INCLUDE_CHAT_IDS` | - | B | Force-include specific groups |\n| `CHANNELS_EXCLUDE_CHAT_IDS` | - | B | Exclude specific channels |\n| `CHANNELS_INCLUDE_CHAT_IDS` | - | B | Force-include specific channels |\n| **Real-time Listener** | | | See [Real-time Listener](#real-time-listener) below |\n| `ENABLE_LISTENER` | `false` | B | **Master switch** — enables all `LISTEN_*` features below |\n| `LISTEN_EDITS` | `true` | B | Apply text edits in real-time |\n| `LISTEN_DELETIONS` | `true` | B | Mirror deletions (protected by [mass operation rate limiting](#mass-operation-protection)) |\n| `LISTEN_NEW_MESSAGES` | `true` | B | Save new messages in real-time between scheduled backups |\n| `LISTEN_NEW_MESSAGES_MEDIA` | `false` | B | Also download media immediately (vs. next scheduled backup) |\n| `LISTEN_CHAT_ACTIONS` | `true` | B | Track chat photo, title, and member changes |\n| `MASS_OPERATION_THRESHOLD` | `10` | B | Max operations per chat before rate limiting triggers |\n| `MASS_OPERATION_WINDOW_SECONDS` | `30` | B | Sliding window for counting operations (seconds) |\n| `MASS_OPERATION_BUFFER_DELAY` | `2.0` | B | Seconds to buffer operations before applying |\n| **Database** | | | See [Database Configuration](#database-configuration) below |\n| `DATABASE_URL` | - | B/V | Full database URL (highest priority, overrides all below) |\n| `DB_TYPE` | `sqlite` | B/V | Database engine: `sqlite` or `postgresql` |\n| `DB_PATH` | `$BACKUP_PATH/telegram_backup.db` | B/V | Path to SQLite database file |\n| `DATABASE_PATH` | - | B/V | Full path to SQLite file (v2 compatible alias for `DB_PATH`) |\n| `DATABASE_DIR` | - | B/V | Directory containing `telegram_backup.db` (v2 compatible) |\n| `POSTGRES_HOST` | `localhost` | B/V | PostgreSQL host |\n| `POSTGRES_PORT` | `5432` | B/V | PostgreSQL port |\n| `POSTGRES_USER` | `telegram` | B/V | PostgreSQL username |\n| `POSTGRES_PASSWORD` | - | B/V | PostgreSQL password (required when using PostgreSQL) |\n| `POSTGRES_DB` | `telegram_backup` | B/V | PostgreSQL database name |\n| **Viewer \u0026 Authentication** | | | |\n| `VIEWER_USERNAME` | - | V | Web viewer username (both username and password required to enable auth) |\n| `VIEWER_PASSWORD` | - | V | Web viewer password |\n| `AUTH_SESSION_DAYS` | `30` | V | Days before re-authentication is required |\n| `DISPLAY_CHAT_IDS` | - | V | Restrict viewer to specific chats (comma-separated IDs) |\n| `VIEWER_TIMEZONE` | `Europe/Madrid` | V | Timezone for displayed timestamps ([tz database names](https://en.wikipedia.org/wiki/List_of_tz_database_time_zones)) |\n| `SHOW_STATS` | `true` | V | Show backup statistics dropdown in viewer header |\n| **Security** | | | |\n| `CORS_ORIGINS` | `*` | V | Allowed CORS origins, comma-separated (e.g., `https://my.domain.com`). Credentials auto-disabled when `*` |\n| `SECURE_COOKIES` | `auto` | V | `Secure` flag on auth cookies. Auto-detects from request protocol (`X-Forwarded-Proto` / scheme). Override with `true` or `false` |\n| **Notifications** | | | |\n| `PUSH_NOTIFICATIONS` | `basic` | V | `off` = disabled, `basic` = in-browser only, `full` = Web Push (works with browser closed) |\n| `VAPID_PRIVATE_KEY` | *auto-generated* | V | Custom VAPID private key for Web Push |\n| `VAPID_PUBLIC_KEY` | *auto-generated* | V | Custom VAPID public key for Web Push |\n| `VAPID_CONTACT` | `mailto:admin@example.com` | V | Contact email included in Web Push requests |\n\n### Chat Filtering\n\nThere are **two modes** for selecting which chats to backup:\n\n**Mode 1 — Whitelist** (simple): set `CHAT_IDS` to backup **only** those specific chats. All other filtering variables are ignored.\n\n```bash\nCHAT_IDS=-1001234567890,-1009876543210    # Only these 2 chats, nothing else\n```\n\n**Mode 2 — Type-based** (default): use `CHAT_TYPES` to backup all chats of certain types, then fine-tune with include/exclude lists:\n\n```bash\n# Backup all private chats and groups (no channels)\nCHAT_TYPES=private,groups\n\n# Backup all channels except one\nCHAT_TYPES=channels\nCHANNELS_EXCLUDE_CHAT_IDS=-1001234567890\n\n# Backup all groups plus one specific channel\nCHAT_TYPES=groups\nCHANNELS_INCLUDE_CHAT_IDS=-1001234567890\n```\n\n\u003e `*_INCLUDE_*` variables are **additive** — they add chats to what `CHAT_TYPES` already selects. For exclusive selection, use `CHAT_IDS` instead.\n\n**Chat ID format** — Telegram uses \"marked\" IDs:\n- **Users**: positive numbers (`123456789`)\n- **Basic groups**: negative (`-123456789`)\n- **Supergroups/Channels**: negative with `-100` prefix (`-1001234567890`)\n\nFind a chat's ID by forwarding a message to [@userinfobot](https://t.me/userinfobot).\n\n**Topic filtering** — For forum-enabled supergroups, you can exclude specific topics without excluding the entire chat using `SKIP_TOPIC_IDS`:\n\n```bash\n# Skip topics 42 and 1337 in one chat, and topic 7 in another\nSKIP_TOPIC_IDS=-1001234567890:42,-1001234567890:1337,-1009876543210:7\n```\n\n\u003e Note: The topic-creating service message (1 per topic) may still be backed up since it lacks `reply_to` metadata. This does not affect user-generated content.\n\n### Real-time Listener\n\nThe scheduled backup only captures new messages. To also track edits and deletions between backups, enable the real-time listener:\n\n```yaml\nENABLE_LISTENER: \"true\"        # Master switch — required\nLISTEN_EDITS: \"true\"           # Track text edits (safe, default: true)\nLISTEN_DELETIONS: \"true\"       # Mirror deletions (default: true, protected by rate limiting)\nLISTEN_NEW_MESSAGES: \"true\"    # Save new messages instantly (default: true)\n```\n\n**How it works:** stays connected to Telegram between scheduled backups, captures changes as they happen, and automatically reconnects if disconnected.\n\n**Backup protection:** when `LISTEN_DELETIONS=true`, deletions are protected by the [mass operation rate limiter](#mass-operation-protection). Set `LISTEN_DELETIONS=false` to never delete anything from your backup.\n\n**Alternative — batch sync:** set `SYNC_DELETIONS_EDITS=true` to check ALL backed-up messages on each scheduled run. This is expensive and slow — only use for a one-time catch-up, then switch to the real-time listener.\n\n### Mass Operation Protection\n\nWhen the listener is enabled and `LISTEN_DELETIONS=true`, a sliding-window rate limiter protects against mass deletion attacks:\n\n1. Operations are **buffered** for `MASS_OPERATION_BUFFER_DELAY` seconds before being applied\n2. A sliding window tracks operations per chat over `MASS_OPERATION_WINDOW_SECONDS`\n3. When `MASS_OPERATION_THRESHOLD` is exceeded, the **entire buffer is discarded** — zero changes written\n\n**Example:** someone deletes 50 messages in 10 seconds with default settings (threshold=10, window=30s) — the first 10 are applied, remaining 40 are blocked. For **zero** deletions from your backup, set `LISTEN_DELETIONS=false`.\n\n### Database Configuration\n\nTelegram Archive supports **SQLite** (default, zero-config) and **PostgreSQL** (better for large deployments with real-time LISTEN/NOTIFY).\n\n\u003e **Viewer shows no data?** Both backup and viewer containers must access the **same database**. Ensure `DB_TYPE` and `DB_PATH` (or `DATABASE_URL`) match in both services.\n\n**SQLite path resolution** (highest priority first): `DATABASE_URL` → `DATABASE_PATH` → `DATABASE_DIR` → `DB_PATH` → `$BACKUP_PATH/telegram_backup.db`\n\n**Using PostgreSQL:**\n\n1. Uncomment the `postgres` service in `docker-compose.yml`\n2. Set `DB_TYPE=postgresql` and `POSTGRES_PASSWORD` in your `.env`\n3. Uncomment `depends_on` in both backup and viewer services\n4. Run `docker compose up -d`\n\n## Updating to Latest Version\n\n### Using Pre-built Images (Recommended)\n\nIf you're using the default `docker-compose.yml` with images from Docker Hub:\n\n```bash\n# Pull latest images and recreate containers\ndocker compose pull\ndocker compose up -d\n```\n\nOr in one command:\n```bash\ndocker compose up -d --pull always\n```\n\n\u003e **Note:** Running `git pull` only updates source code, not Docker images. You must use `docker compose pull` to get new container versions.\n\n### Building from Source\n\nIf you've modified the code or prefer building locally:\n\n```bash\ngit pull\ndocker build -t drumsergio/telegram-archive:latest .\ndocker build -t drumsergio/telegram-archive-viewer:latest -f Dockerfile.viewer .\ndocker compose up -d\n```\n\n### Pinning Versions\n\nFor production stability, pin to specific versions instead of `latest`:\n\n```yaml\nservices:\n  telegram-backup:\n    image: drumsergio/telegram-archive:v7.1.7  # Pin to specific version\n```\n\nCheck [Releases](https://github.com/GeiserX/Telegram-Archive/releases) for available versions.\n\n## ⚠️ Upgrading (Breaking Changes)\n\nFor major version upgrades with breaking changes and migration scripts, see **[docs/CHANGELOG.md](docs/CHANGELOG.md)**.\n\n## CLI Commands\n\n### Local Development\n\n#### Option 1: Install with pip (Recommended)\n\nInstall the package in editable mode to get the `telegram-archive` command:\n\n```bash\n# Install in editable mode\npip install -e .\n\n# Now telegram-archive is available system-wide\ntelegram-archive --help\ntelegram-archive --data-dir ./data list-chats\ntelegram-archive --data-dir ./data stats\ntelegram-archive --data-dir ./data backup\n\n# Export to JSON\ntelegram-archive --data-dir ./data export -o backup.json -s 2024-01-01 -e 2024-12-31\n```\n\n#### Option 2: Run directly without installation\n\nFor development without installing, use the `telegram-archive` executable script:\n\n```bash\n# Show all available commands\n./telegram-archive --help\n\n# Use custom data directory (instead of /data)\n./telegram-archive --data-dir ./data list-chats\n./telegram-archive --data-dir ./data stats\n./telegram-archive --data-dir ./data backup\n\n# Or symlink to PATH for easier access\nsudo ln -s $(pwd)/telegram-archive /usr/local/bin/telegram-archive\ntelegram-archive --data-dir ./data list-chats\n```\n\n### Docker Usage\n\nAll commands use the unified `python -m src` interface inside containers:\n\n```bash\n# Show all available commands\ndocker compose exec telegram-backup python -m src --help\n\n# View statistics\ndocker compose exec telegram-backup python -m src stats\n\n# List chats\ndocker compose exec telegram-backup python -m src list-chats\n\n# Export to JSON\ndocker compose exec telegram-backup python -m src export -o backup.json\n\n# Export date range\ndocker compose exec telegram-backup python -m src export -o backup.json -s 2024-01-01 -e 2024-12-31\n\n# Manual backup run (one-time)\ndocker compose exec telegram-backup python -m src backup\n\n# Re-authenticate (if session expires)\ndocker compose exec -it telegram-backup python -m src auth\n```\n\n## Data Storage\n\n```\ndata/\n├── session/\n│   └── telegram_backup.session\n└── backups/\n    ├── telegram_backup.db\n    └── media/\n        └── {chat_id}/\n            └── {files}\n```\n\n## Troubleshooting\n\n| Problem | Solution |\n|---------|----------|\n| \"Failed to authorize\" | Run `./init_auth.sh` again |\n| \"Permission denied\" | `chmod -R 755 data/` |\n| Media files missing/corrupted | Set `VERIFY_MEDIA=true` to re-download them |\n| Backup interrupted | Set `VERIFY_MEDIA=true` once to recover missing files |\n| \"duplicate key value violates unique constraint reactions_pkey\" | See [Reactions Sequence Fix](#reactions-sequence-fix-postgresql) below |\n\n### Reactions Sequence Fix (PostgreSQL)\n\nIf you see this error during backup:\n```\nduplicate key value violates unique constraint \"reactions_pkey\"\nDETAIL: Key (id)=(XXXX) already exists\n```\n\n**Cause:** The PostgreSQL sequence for `reactions.id` got out of sync with the actual data. This commonly occurs after database restores or migrations.\n\n**Solutions:**\n\n1. **Upgrade to v4.1.2+** (recommended) - The code automatically detects and recovers from this issue.\n\n2. **Manual fix** - Run this SQL command:\n   ```bash\n   docker exec -i \u003cpostgres-container\u003e psql -U telegram -d telegram_backup -c \\\n     \"SELECT setval('reactions_id_seq', COALESCE((SELECT MAX(id) FROM reactions), 0) + 1, false);\"\n   ```\n\n   Or use the provided script:\n   ```bash\n   curl -O https://raw.githubusercontent.com/GeiserX/Telegram-Archive/master/scripts/fix_reactions_sequence.sql\n   docker exec -i \u003cpostgres-container\u003e psql -U telegram -d telegram_backup \u003c fix_reactions_sequence.sql\n   ```\n\n## Limitations\n\n- Secret chats not supported (API limitation)\n- Edit history not tracked (only latest version stored; enable `ENABLE_LISTENER=true` to track edits in real-time)\n- Deleted messages before first backup cannot be recovered\n\n## Ecosystem\n\n| Project | Type | Description |\n|---------|------|-------------|\n| [telegram-archive-mcp](https://github.com/GeiserX/telegram-archive-mcp) | MCP Server | Query archived messages from AI assistants |\n| [n8n-nodes-telegram-archive](https://github.com/GeiserX/n8n-nodes-telegram-archive) | n8n Node | Workflow automation for Telegram Archive |\n\n## Other Telegram Projects by GeiserX\n\n- [paperless-telegram-bot](https://github.com/GeiserX/paperless-telegram-bot) — Manage Paperless-NGX documents through Telegram\n- [AskePub](https://github.com/GeiserX/AskePub) — Telegram bot for ePub annotation with GPT-4\n- [telegram-delay-channel-cloner](https://github.com/GeiserX/telegram-delay-channel-cloner) — Relay messages between channels with configurable delay\n- [jellyfin-telegram-channel-sync](https://github.com/GeiserX/jellyfin-telegram-channel-sync) — Sync Jellyfin access with Telegram channel membership\n- [telegram-slskd-local-bot](https://github.com/GeiserX/telegram-slskd-local-bot) — Automated music discovery and download via Telegram\n\n## Supporters\n\n\u003e This project is made possible by generous supporters:\n\u003e **Calvin**\n\n## License\n\nGPL-3.0. See [LICENSE](LICENSE) for details.\n\nBuilt with [Telethon](https://github.com/LonamiWebs/Telethon).\n","funding_links":["https://github.com/sponsors/geiserx","https://patreon.com/geiser","https://buymeacoffee.com/geiser","https://thanks.dev/u/gh/geiserx"],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fgeiserx%2Ftelegram-archive","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fgeiserx%2Ftelegram-archive","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fgeiserx%2Ftelegram-archive/lists"}