Skip to content

Repository files navigation

File Stream Bot logo

📡 File Stream Bot™

Send a file → get an instant streaming + download link.

PythonPyrogramaiohttpMongoDBDocker


Deploy To Various Platforms :)


Deploy to HerokuDeploy to KoyebDeploy to Render


✨ Features

  • ⚡ Instant direct-download links for any file
  • 🎬 In-browser video/audio streaming page — full HTTP Range support, resumable, cinema-style UI
  • 🎧 Audio track switching (multi-track AAC/AC3/Opus files) via native browser audioTracks API
  • 💬 Subtitle support — load external .srt/.vtt client-side, toggle on/off
  • 🔗 Short links — /watch/<hash+id> and /dl/<hash+id>, no filename or query string exposed in the shareable URL
  • 🔒 Force-subscribe gate (optional)
  • 🔗 Shortlink support — is.gd or Shortzy-based (gplinks, mdisk, etc.)
  • 🚀 Multi-client mode for higher throughput with extra bot tokens (MULTI_TOKEN1..N)
  • ⏩ Per-stream parallel chunk prefetch (CONCURRENT_FETCHES) — faster single-stream speed, not just more concurrent viewers
  • ♻️ Auto-retry on transient Telegram RPC errors (-503 Timeout etc.) and FloodWait, instead of killing the stream
  • 🧹 Graceful shutdown on SIGTERM — stops all clients + in-flight streams cleanly within the platform's grace window (fixes Heroku R12 / forced SIGKILL)
  • 🛠️ Admin tools — /stats, /broadcast, /restart
  • ♻️ Auto-restart every 12h, plus auto-restart on network errors
  • 💓 Self-ping keepalive for free-tier hosts (Heroku/Koyeb/Render)

🧱 Stack

RuntimePython 3.11
TelegramPyrogram (pyrotgfork) + TgCrypto
Serveraiohttp (web server + chunked streaming)
DatabaseMongoDB (motor)
DeployDocker → Koyeb / Heroku / Render

🚀 Setup

1. Install deps

pip install -r requirements.txt

2. Set environment variables

Required vars hard-fail with a clear error message if missing — no more cryptic tracebacks.

VarRequiredDescription
API_IDfrom my.telegram.org — shared across ALL bot tokens, including MULTI_TOKEN*
API_HASHfrom my.telegram.org — same, shared
BOT_TOKENmain bot, from @BotFather
LOG_CHANNELprivate channel used as file storage backend — every bot token (main + multi) must be admin here
DATABASE_URIMongoDB connection string
DATABASE_NAMEMongoDB db name
URLpublic base URL of this deployment, e.g. https://yourapp.koyeb.app/
ADMINSspace-separated admin user IDs
FSUB_CHANNELforce-subscribe channel id (0 = disabled)
PORTdefault 8080
SLEEP_THRESHOLDdefault 60
PING_INTERVALself-ping interval in seconds, default 1200
SHORTLINKTrue/False, use Shortzy-based shortener
SHORTLINK_URL / SHORTLINK_APIrequired if SHORTLINK=True
ISGDTrue/False, use is.gd shortener (no key needed)
MULTI_TOKEN1, MULTI_TOKEN2, ...extra bot tokens for multi-client load balancing — tokens can come from separate Telegram accounts (BotFather caps 20 bots/account), just add each new bot as admin in LOG_CHANNEL

3. Run

python bot.py

Or with Docker:

docker build -t filestreambot .
docker run -p 8080:8080 --env-file .env filestreambot

⚙️ How it works

User sends file
│
▼
Bot forwards file → LOG_CHANNEL
│
▼
Bot replies with short links:
• Stream link → /watch/<hash+id>
• Download link → /dl/<hash+id>
│
▼
Page resolves hash+id → serves req.html (player) or dl.html (download),
video/download button points at the raw byte-stream endpoint
│
▼
aiohttp pulls file from Telegram on-demand,
1MB chunks, 2 fetched in parallel per stream,
per-DC locked sessions, Range-aware → resumable,
auto-retries on FloodWait / transient Telegram errors

📊 Sizing multi-client

  • Each MULTI_TOKEN client ≈ comfortably serves 3-5 concurrent full-speed streams before Telegram FloodWaits it.
  • Rule of thumb: tokens_needed ≈ peak_concurrent_viewers / 4
  • Each live client ≈ 25-40MB RAM — on a 512MB dyno, 7-8 clients is the realistic ceiling; going higher risks Heroku R14 (memory) and R12 (SIGKILL on shutdown) errors. Upgrade dyno RAM before adding more tokens past that.

📁 Project layout

bot.py entrypoint, plugin loader, auto-restart, graceful shutdown
info.py env var config
Script.py bot text templates
utils.py shortlink helper, temp state
database/ MongoDB user store
lib/bot/clients.py multi-client manager — start + graceful stop_clients()
lib/util/custom_dl.py chunked file streaming from Telegram, retry logic, parallel prefetch
lib/util/render_template.py renders download/stream HTML pages
lib/template/ req.html (player page), dl.html (download page)
lib/server/exceptions.py InvalidHash / FIleNotFound
plugins/route.py /watch, /dl, and raw byte-stream routes
plugins/ command handlers (start, route, broadcast, stats, etc.)

📝 Notes

  • LOG_CHANNEL must be a channel/group every bot token (main + all MULTI_TOKEN*) is admin in — it's permanent file storage, not just a log.
  • Short links are hash-protected (first 6 chars of the file's unique_id) so IDs can't be brute-forced sequentially — no database lookup needed for link resolution.
  • DTS/DTS-HD/TrueHD audio tracks won't play in-browser regardless of what's in the file — no browser ships a decoder for them, that's a licensing wall, not a bug.

🩹 Changelog

FixDetail
Heroku R12 (Exit timeout / SIGKILL)Added graceful shutdown: on SIGTERM, stops aiohttp server, cancels in-flight stream tasks, stops every Pyrogram client within a bounded 20s window
dict(clients) crash on any failed multi-client tokeninitialize_clients() now skips failed tokens instead of crashing the whole multi-client pool
GeneratorExit / "coroutine ignored" spam on client disconnectPrefetch producer now stops cooperatively instead of being hard-cancelled mid-fetch; strong-ref set prevents early GC of pending tasks
Stream died instantly on [-503 Timeout] / transient Telegram RPC errorsNow retried with backoff, same as FloodWait
Slow single-stream speedChunks fetched 2-at-a-time per stream (CONCURRENT_FETCHES) instead of strictly sequential
Downloaded filename sometimes corrupted (+ vs space)URL path now uses quote() not quote_plus(); download= attribute also forces the exact real filename client-side
dl.html used Python %s placeholders but was rendered via jinja2Switched to {{var}} jinja2 syntax
Download page render made a full self-HTTP GET just to read Content-LengthRemoved; reuses the already-known file size
MULTI_CLIENT flag never reached the route handlerRoute now checks live client count directly
detect_error() defined but never calledHooked into route handlers' exception path
info.py crashed with a bare ValueError if required vars missingNow exits with a clear error message
Every plugin handler ran twice (double plugin load)Removed auto-load, kept only the manual loader
info.py's id_pattern failed on single-digit admin IDsFixed regex

👤 Maintainer

Goutham@GouthamSER

About

A Superfast File 2 link repo Tg files converts to url to downlaod faster

Topics

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages