{"id":50843145,"url":"https://github.com/GeiserX/paperless-telegram-bot","last_synced_at":"2026-07-01T18:01:06.735Z","repository":{"id":338401208,"uuid":"1157447582","full_name":"GeiserX/paperless-telegram-bot","owner":"GeiserX","description":"Manage Paperless-NGX documents entirely through Telegram - upload, search, tag, and organize","archived":false,"fork":false,"pushed_at":"2026-07-01T09:42:44.000Z","size":119,"stargazers_count":10,"open_issues_count":1,"forks_count":1,"subscribers_count":1,"default_branch":"main","last_synced_at":"2026-07-01T11:24:21.238Z","etag":null,"topics":["automation","dms","docker","docker-compose","document-management","document-scanner","fastapi","hacktoberfest","homelab","ocr","open-source","paperless","paperless-ngx","productivity","python","search","self-hosted","telegram","telegram-bot","upload"],"latest_commit_sha":null,"homepage":null,"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":null,"funding":".github/FUNDING.yml","license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"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":null,"dco":null,"cla":null},"funding":{"github":"geiserx","patreon":"geiser","buy_me_a_coffee":"geiser","thanks_dev":"u/gh/geiserx"}},"created_at":"2026-02-13T20:39:49.000Z","updated_at":"2026-07-01T09:42:46.000Z","dependencies_parsed_at":null,"dependency_job_id":"022c8f16-dcee-45c5-832b-9eeacca9e45a","html_url":"https://github.com/GeiserX/paperless-telegram-bot","commit_stats":null,"previous_names":["geiserx/paperless-telegram-bot"],"tags_count":9,"template":false,"template_full_name":null,"purl":"pkg:github/GeiserX/paperless-telegram-bot","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/GeiserX%2Fpaperless-telegram-bot","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/GeiserX%2Fpaperless-telegram-bot/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/GeiserX%2Fpaperless-telegram-bot/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/GeiserX%2Fpaperless-telegram-bot/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/GeiserX","download_url":"https://codeload.github.com/GeiserX/paperless-telegram-bot/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/GeiserX%2Fpaperless-telegram-bot/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":35017091,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-26T15:22:16.424Z","status":"online","status_checked_at":"2026-07-01T02:00:05.325Z","response_time":130,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"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":["automation","dms","docker","docker-compose","document-management","document-scanner","fastapi","hacktoberfest","homelab","ocr","open-source","paperless","paperless-ngx","productivity","python","search","self-hosted","telegram","telegram-bot","upload"],"created_at":"2026-06-14T08:00:22.751Z","updated_at":"2026-07-01T18:01:06.729Z","avatar_url":"https://github.com/GeiserX.png","language":"Python","funding_links":["https://github.com/sponsors/geiserx","https://patreon.com/geiser","https://buymeacoffee.com/geiser","https://thanks.dev/u/gh/geiserx"],"categories":["Bots"],"sub_categories":[],"readme":"\u003cp align=\"center\"\u003e\n  \u003cimg src=\"https://raw.githubusercontent.com/GeiserX/paperless-telegram-bot/main/docs/images/banner.svg\" alt=\"paperless-telegram-bot banner\" width=\"900\"/\u003e\n\u003c/p\u003e\n\n\u003cp align=\"center\"\u003e\n  \u003cstrong\u003eManage Paperless-NGX documents entirely through Telegram.\u003c/strong\u003e\n\u003c/p\u003e\n\n\u003cp align=\"center\"\u003e\n  \u003ca href=\"https://github.com/GeiserX/paperless-telegram-bot/actions/workflows/docker-publish.yml\"\u003e\u003cimg src=\"https://img.shields.io/github/actions/workflow/status/GeiserX/paperless-telegram-bot/docker-publish.yml?style=flat-square\u0026logo=github\u0026label=build\" alt=\"Docker Build\"\u003e\u003c/a\u003e\n  \u003ca href=\"https://github.com/GeiserX/paperless-telegram-bot/actions/workflows/tests.yml\"\u003e\u003cimg src=\"https://img.shields.io/github/actions/workflow/status/GeiserX/paperless-telegram-bot/tests.yml?style=flat-square\u0026logo=github\u0026label=tests\" alt=\"Tests\"\u003e\u003c/a\u003e\n  \u003ca href=\"https://hub.docker.com/r/drumsergio/paperless-telegram-bot\"\u003e\u003cimg src=\"https://img.shields.io/docker/pulls/drumsergio/paperless-telegram-bot?style=flat-square\u0026logo=docker\" alt=\"Docker Pulls\"\u003e\u003c/a\u003e\n  \u003ca href=\"https://pypi.org/project/paperless-telegram-bot/\"\u003e\u003cimg src=\"https://img.shields.io/pypi/v/paperless-telegram-bot?style=flat-square\u0026logo=pypi\u0026logoColor=white\" alt=\"PyPI\"\u003e\u003c/a\u003e\n  \u003ca href=\"https://github.com/GeiserX/paperless-telegram-bot/blob/main/LICENSE\"\u003e\u003cimg src=\"https://img.shields.io/github/license/GeiserX/paperless-telegram-bot?style=flat-square\" alt=\"License\"\u003e\u003c/a\u003e\n  \u003cimg src=\"https://img.shields.io/badge/python-3.11%2B-blue?style=flat-square\u0026logo=python\u0026logoColor=white\" alt=\"Python 3.11+\"\u003e\n  \u003ca href=\"https://codecov.io/gh/GeiserX/paperless-telegram-bot\"\u003e\u003cimg src=\"https://codecov.io/gh/GeiserX/paperless-telegram-bot/graph/badge.svg\" alt=\"codecov\"\u003e\u003c/a\u003e\n\u003c/p\u003e\n\n---\n\nA full-featured Telegram bot that integrates with [Paperless-NGX](https://docs.paperless-ngx.com/), giving you complete document management from your phone or desktop -- no web UI required. Upload documents and photos, search your archive with full-text search, manage metadata, review your inbox, and download files, all within Telegram.\n\n## Features\n\n- **Document Upload** -- Send any file or photo to the bot and it gets uploaded to Paperless-NGX automatically. Duplicates are detected and linked.\n- **Full-Text Search** -- Search across all your documents with `/search`. Results are paginated with inline keyboard navigation.\n- **Metadata Management** -- After uploading (or on any document), assign tags, correspondents, and document types through interactive inline keyboards.\n- **Inbox Review** -- `/inbox` lists all documents tagged with your inbox tag. Mark them as reviewed with a single tap.\n- **Document Download** -- Download original files directly to Telegram (up to 50 MB).\n- **Recent Documents** -- `/recent` shows the latest documents added to your archive.\n- **System Statistics** -- `/stats` displays document counts, tag usage, and storage information.\n- **Health Endpoint** -- Built-in `/health` HTTP endpoint for Docker health checks and monitoring.\n- **User Authorization** -- Restrict bot access to specific Telegram user IDs via allowlist.\n- **Non-Root Docker** -- Runs as an unprivileged user inside the container.\n\n## Quick Start\n\n### Docker (Recommended)\n\n```bash\ndocker run -d \\\n  --name paperless-telegram-bot \\\n  --restart unless-stopped \\\n  -e TELEGRAM_BOT_TOKEN=your_bot_token \\\n  -e PAPERLESS_URL=http://your-paperless:8000 \\\n  -e PAPERLESS_TOKEN=your_api_token \\\n  -e TELEGRAM_ALLOWED_USERS=123456789 \\\n  drumsergio/paperless-telegram-bot:latest\n```\n\n### Docker Compose\n\n```yaml\nservices:\n  paperless-telegram-bot:\n    image: drumsergio/paperless-telegram-bot:latest\n    container_name: paperless-telegram-bot\n    restart: unless-stopped\n    environment:\n      TELEGRAM_BOT_TOKEN: \"${TELEGRAM_BOT_TOKEN}\"\n      PAPERLESS_URL: \"http://paperless:8000\"\n      PAPERLESS_TOKEN: \"${PAPERLESS_TOKEN}\"\n      TELEGRAM_ALLOWED_USERS: \"${TELEGRAM_ALLOWED_USERS}\"\n    healthcheck:\n      test: [\"CMD\", \"python\", \"-c\", \"import urllib.request; urllib.request.urlopen('http://localhost:8080/health')\"]\n      interval: 30s\n      timeout: 5s\n      retries: 3\n```\n\n### Manual Installation\n\n```bash\ngit clone https://github.com/GeiserX/paperless-telegram-bot.git\ncd paperless-telegram-bot\npython -m venv .venv \u0026\u0026 source .venv/bin/activate\npip install -r requirements.txt\ncp .env.example .env   # Edit with your values\npython -m paperless_bot run\n```\n\n## Configuration\n\nAll configuration is done through environment variables. Copy `.env.example` to `.env` for local development.\n\n| Variable | Required | Default | Description |\n|----------|----------|---------|-------------|\n| `TELEGRAM_BOT_TOKEN` | Yes | -- | Telegram Bot API token from [@BotFather](https://t.me/BotFather) |\n| `PAPERLESS_URL` | Yes | -- | Paperless-NGX instance URL (e.g. `http://localhost:8000`) |\n| `PAPERLESS_TOKEN` | Yes | -- | Paperless-NGX API authentication token |\n| `TELEGRAM_ALLOWED_USERS` | No | *(open)* | Comma-separated Telegram user IDs allowed to use the bot |\n| `PAPERLESS_PUBLIC_URL` | No | `PAPERLESS_URL` | User-facing URL for clickable document links |\n| `MAX_SEARCH_RESULTS` | No | `10` | Number of results per page in search, recent, and inbox |\n| `REMOVE_INBOX_ON_DONE` | No | `true` | Remove inbox tag when clicking \"Done\" in metadata flow |\n| `INBOX_TAG` | No | *(auto-detect)* | Explicit inbox tag name. If unset, auto-detects via Paperless API |\n| `LOG_LEVEL` | No | `INFO` | Logging level (`DEBUG`, `INFO`, `WARNING`, `ERROR`) |\n| `HEALTH_PORT` | No | `8080` | Port for the `/health` HTTP endpoint |\n\n## Commands\n\n| Command | Description |\n|---------|-------------|\n| `/search \u003cquery\u003e` | Full-text search across all documents |\n| `/recent` | Show recently added documents |\n| `/inbox` | List documents in the inbox with review actions |\n| `/stats` | Display Paperless-NGX statistics |\n| `/help` | Show available commands and usage |\n\nIn addition to commands, you can send any **file or photo** directly to the bot to upload it to Paperless-NGX. After upload, an interactive keyboard lets you assign tags, a correspondent, and a document type.\n\n## Architecture\n\n```\npaperless-telegram-bot\n|-- src/paperless_bot/\n|   |-- __main__.py         # Entry point, health server, CLI\n|   |-- config.py           # Environment variable loading and validation\n|   |-- api/\n|   |   +-- client.py       # Async Paperless-NGX API client with caching\n|   +-- bot/\n|       |-- handlers.py     # Command handlers, callback routing, upload flow\n|       +-- keyboards.py    # Inline keyboard builders for metadata selection\n+-- tests/                  # pytest + respx test suite\n```\n\n**Key design decisions:**\n\n- **Async throughout** -- Uses `python-telegram-bot` with `httpx` for fully asynchronous I/O.\n- **Metadata caching** -- Tags, correspondents, and document types are cached in memory and refreshed on demand, minimizing API calls.\n- **Callback data encoding** -- Telegram limits `callback_data` to 64 bytes. All prefixes are kept short (`meta:tags:`, `dl:`, `sp:`, etc.) and long search queries are stored server-side per chat.\n- **Inbox auto-detection** -- The bot reads the `is_inbox_tag` field from the Paperless API rather than matching by name, so it works with any language or custom tag name.\n- **Duplicate handling** -- Upload failures containing \"duplicate\" are parsed to extract and link to the existing document.\n\n## Security\n\n- **User allowlist** -- Set `TELEGRAM_ALLOWED_USERS` to restrict access. When empty, the bot accepts messages from anyone (not recommended for production).\n- **Non-root container** -- The Docker image runs as an unprivileged `paperlessbot` user (UID 1000).\n- **No secrets in code** -- All credentials are loaded from environment variables. Never commit `.env` files.\n- **API token scoping** -- The bot uses a single Paperless-NGX API token. Create a dedicated user/token with appropriate permissions.\n\n## Development\n\n```bash\n# Install dev dependencies\npip install -e \".[dev]\"\n\n# Run linter and formatter\nruff check src/ \u0026\u0026 ruff format src/\n\n# Run tests\npython -m pytest tests/ -v\n\n# Run tests with coverage\npython -m pytest tests/ --cov=paperless_bot --cov-report=term-missing\n```\n\n## Contributing\n\nContributions are welcome. Please:\n\n1. Fork the repository\n2. Create a feature branch (`feat/my-feature` or `fix/my-bug`)\n3. Follow the existing code style (enforced by `ruff`)\n4. Add tests for new functionality\n5. Submit a pull request\n\nThis project follows [Conventional Commits](https://conventionalcommits.org) and [Semantic Versioning](https://semver.org).\n\n\n## Related Projects\n\n| Project | Description |\n|---------|-------------|\n| [Telegram-Archive](https://github.com/GeiserX/Telegram-Archive) | Automated, incremental Telegram backups with a local web viewer |\n| [telegram-delay-channel-cloner](https://github.com/GeiserX/telegram-delay-channel-cloner) | Telegram bot that relays messages between channels with configurable delay |\n| [telegram-slskd-local-bot](https://github.com/GeiserX/telegram-slskd-local-bot) | Automated music discovery and download via Telegram bot with Soulseek |\n| [AskePub](https://github.com/GeiserX/AskePub) | Telegram bot for ePub annotation with GPT-4 |\n| [jellyfin-telegram-channel-sync](https://github.com/GeiserX/jellyfin-telegram-channel-sync) | Sync Jellyfin access with Telegram channel membership |\n| [telegram-archive-mcp](https://github.com/GeiserX/telegram-archive-mcp) | MCP Server for Telegram-Archive |\n| [n8n-nodes-telegram-archive](https://github.com/GeiserX/n8n-nodes-telegram-archive) | n8n community node for Telegram-Archive |\n\n## License\n\nThis project is licensed under the [GNU General Public License v3.0](LICENSE).\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2FGeiserX%2Fpaperless-telegram-bot","html_url":"https://awesome.ecosyste.ms/projects/github.com%2FGeiserX%2Fpaperless-telegram-bot","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2FGeiserX%2Fpaperless-telegram-bot/lists"}