Private, whitelist-only Telegram bot for downloading media with yt-dlp, optional timestamp clipping with ffmpeg, and SQLite-backed access control.
This project is designed for responsible use. It does not include cookies, login automation, DRM tooling, paywall bypasses, or platform-protection evasion. Only download media you have the right to download and share.
- aiogram 3.x async Telegram bot.
- Whitelist-only mode enabled by default.
- Admin dashboard commands for status, queue, storage, users, failed jobs, cleanup, and whitelist management.
- SQLite whitelist repository behind a service abstraction that can later be replaced by PostgreSQL.
- yt-dlp metadata extraction without downloading before showing options.
- Practical grouped quality choices: best, best under limit, common resolutions, and audio-only M4A/MP3.
- Timestamp clipping after download with
ffmpeg, including first/last shortcuts and multiple ranges. - Progress status updates by editing one Telegram message during metadata, queueing, download, clipping, upload, completion, failure, and cleanup.
- SQLite-backed cache for metadata, processed files, and Telegram
file_idreuse. - Per-user cooldown, concurrent job limit,
/cancel, temp directory cleanup, and filename sanitization. - Tests for timestamp parsing, format grouping, and whitelist behavior without Telegram/network/downloads.
- Python 3.12+
ffmpegavailable onPATH- A Telegram bot token from BotFather
uvrecommended, but standardpipalso works
cd /root/telegram-ytdlp-bot
cp .env.example .envEdit .env:
BOT_TOKEN=123456:your-token
ADMIN_IDS=123456789
WHITELIST_IDS=123456789
WHITELIST_ONLY=trueInstall and run:
uv sync --extra dev
uv run python -m app.botWith pip:
python -m venv .venv
. .venv/bin/activate
pip install -e ".[dev]"
python -m app.botcd /root/telegram-ytdlp-bot
cp .env.example .env
# edit .env
docker compose up --build -dThe compose file persists SQLite data in ./data, temporary downloads in ./downloads, and reusable processed-file cache in ./cache.
- Send the bot a supported
http://orhttps://video URL. - The bot extracts metadata and displays title, duration, uploader, thumbnail when available, and grouped download choices.
- Choose a quality option.
- Choose full video, a shortcut, or custom timestamp ranges.
- Confirm the final selection before processing starts.
- For custom ranges, send examples like:
00:01:20-00:03:45
1:20-3:45
80-225
1:20-
-3:45
first 60s
last 30s
00:10-00:30, 01:00-01:45
Multiple ranges are rendered as temporary normalized clips and merged into one final output with ffmpeg concat. Single ranges keep the faster stream-copy clipping path.
The bot registers its command menu with Telegram automatically on startup using the Bot API. Regular users see the safe user commands. Configured admins get a private-chat scoped command menu with admin commands when Telegram can resolve their chat ID.
User commands:
/startor/help- usage help./ping- measure Telegram Bot API response latency./cancel- cancels an active job when possible and clears pending selections.
Admin commands:
/admin- dashboard-style admin menu./status- job counters./queue- active queued/running jobs./jobs- recent jobs./failed_jobs- recent failed jobs./storage- disk/cache usage./cleanup- remove old temporary files./users- list whitelisted user count and IDs./whitelist_add <user_id>- add a user./whitelist_remove <user_id>- remove a user. Admins remain effectively allowed./whitelist_list- list persisted whitelist IDs.
Admin commands are restricted to ADMIN_IDS.
MAX_UPLOAD_BYTES defaults to about 49 MiB to stay conservative for bot uploads. If a processed result is larger, the bot refuses to upload it and asks the user to choose a lower quality or shorter timestamp range.
MAX_DOWNLOAD_BYTES is a separate guardrail for downloaded source media before clipping.
All runtime configuration comes from environment variables or .env.
| Variable | Default | Notes |
|---|---|---|
BOT_TOKEN |
empty | Required to run the bot |
ADMIN_IDS |
empty | Comma-separated Telegram user IDs |
WHITELIST_IDS |
empty | Comma-separated initial whitelist IDs persisted at startup |
WHITELIST_ONLY |
true |
Private mode by default |
DATABASE_PATH |
data/bot.sqlite3 |
SQLite database path |
DOWNLOADS_DIR |
downloads |
Temporary job directories |
CACHE_DIR |
cache |
Processed media cache directory |
CACHE_ENABLED |
true |
Enables metadata/media/file_id cache |
CACHE_TTL_HOURS |
24 |
Cache entry lifetime |
MAX_CACHE_SIZE_MB |
5000 |
Local cache size cap |
CLEANUP_ON_STARTUP |
true |
Cleanup temp/cache on bot startup |
MAX_UPLOAD_BYTES |
51380224 |
Upload limit guardrail |
MAX_DOWNLOAD_BYTES |
262144000 |
yt-dlp download guardrail |
YTDLP_PROXY |
empty | Optional HTTP proxy used for all yt-dlp operations; keep this value secret |
CLEANUP_MAX_AGE_SECONDS |
21600 |
Cleanup threshold |
CONCURRENT_JOBS |
2 |
Global worker limit |
PER_USER_COOLDOWN_SECONDS |
30 |
Simple per-user rate limit |
DEFAULT_AUDIO_FORMAT |
m4a |
Reserved default for audio workflows; both M4A and MP3 buttons are shown |
LOG_LEVEL |
INFO |
Python logging level |
Run tests:
uv run pytestRecommended checks:
uv run ruff format .
uv run ruff check .
uv run mypy appTests intentionally avoid Telegram tokens, network calls, and actual video downloads.
- The bot is intended primarily for private chats.
- File-size estimates depend on metadata supplied by extractors and may be missing or approximate.
- Single timestamp clipping uses stream copy for speed. Multiple ranges are normalized into temporary segment clips before concatenation for more reliable merging.
- PostgreSQL can be added later by implementing the
WhitelistRepositoryprotocol and wiring it inapp/bot.py.