The problem
Someone sends you a Reel. You want to keep it. Between those two facts sit a dozen sites that would rather you did not, each with its own player, its own markup and its own reasons to change both next week.
The bot collapses that into one move: send a link, get the file back. Instagram reels, posts and carousels, YouTube video, Shorts and audio, Pinterest, and roughly a thousand other sites through yt-dlp.
Constraints and tradeoffs
Two tools, one decision
yt-dlp handles video platforms, gallery-dl handles image galleries.
They overlap badly and fail differently. All the “what should download this?”
logic lives in one module, so adding a site means editing one function rather than hunting
through handlers.
The tools go stale, and that is normal
When a download breaks, the first move is to update yt-dlp and gallery-dl — not to read my own code. Platforms change their markup and their APIs on their own schedule, and the extractors follow days later. Treating breakage as an operations task instead of a bug saved me a lot of pointless debugging.
Downloading must not block the bot
A download is a subprocess that can run for minutes. Run it inside the update handler and the bot stops answering everyone — the same mistake I had already made in tekstlybot, which is why this one was built the other way round from the first version.
What I traded away
- Telegram's upload limit stays. Large videos cannot be sent by a bot at all. Saying so plainly, with the actual number, beats a generic failure — and beats running a local Bot API server just for the rare big file.
- No accounts, no cookies. Private and age-gated content needs a logged-in session. Storing someone's session is a liability I have no interest in holding.
- No queue of pending links. Unlike tekstlybot this one is thin: a download either starts now or the user is told to wait. Adding a queue would be the next step, not the first.
Architecture
Screens and states
Normal. The tool that was chosen is shown — when something breaks, that line is the first clue.
YouTube. Two buttons instead of a settings menu — video or just the sound.
Too large. The platform limit named out loud, with something to do next.
Operating it. One script for start, stop, status and logs, and a log that names the real cause.
Results and lessons
What I would tell myself at the start
- Put the routing decision in one place immediately. It started spread across handlers and every new site made it worse.
- Update before you debug. Most “bugs” here are an extractor that has not caught up with a site yet.
- Delete temporary files in a
finally. The disk fills long before anything else complains. - Name the platform limit in the error. “Failed” generates a question; “Telegram does not allow bots to upload files this large” does not.