Skip to content

Repository files navigation

File Stream Bot logo

📡 File Stream Bot™

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

Python Pyrogram aiohttp MongoDB Docker


Deploy To Various Platforms :)


Deploy to Heroku Deploy to Koyeb Deploy 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

Runtime Python 3.11
Telegram Pyrogram (pyrotgfork) + TgCrypto
Server aiohttp (web server + chunked streaming)
Database MongoDB (motor)
Deploy Docker → 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.

Var Required Description
API_ID from my.telegram.org — shared across ALL bot tokens, including MULTI_TOKEN*
API_HASH from my.telegram.org — same, shared
BOT_TOKEN main bot, from @BotFather
LOG_CHANNEL private channel used as file storage backend — every bot token (main + multi) must be admin here
DATABASE_URI MongoDB connection string
DATABASE_NAME MongoDB db name
URL public base URL of this deployment, e.g. https://yourapp.koyeb.app/
ADMINS space-separated admin user IDs
FSUB_CHANNEL force-subscribe channel id (0 = disabled)
PORT default 8080
SLEEP_THRESHOLD default 60
PING_INTERVAL self-ping interval in seconds, default 1200
SHORTLINK True/False, use Shortzy-based shortener
SHORTLINK_URL / SHORTLINK_API required if SHORTLINK=True
ISGD True/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

Fix Detail
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 token initialize_clients() now skips failed tokens instead of crashing the whole multi-client pool
GeneratorExit / "coroutine ignored" spam on client disconnect Prefetch 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 errors Now retried with backoff, same as FloodWait
Slow single-stream speed Chunks 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 jinja2 Switched to {{var}} jinja2 syntax
Download page render made a full self-HTTP GET just to read Content-Length Removed; reuses the already-known file size
MULTI_CLIENT flag never reached the route handler Route now checks live client count directly
detect_error() defined but never called Hooked into route handlers' exception path
info.py crashed with a bare ValueError if required vars missing Now 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 IDs Fixed 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