Open source · GPL-3.0 · fork of mirror-leech-telegram-bot

Telegram mirror & leech bot with FUSE zero-double-storage

mirror-leech-telegram-bot-fuse mounts big archives straight into the Linux virtual file system with archivemount instead of extracting them to disk, lets you pick files from a Telegram inline keyboard, and uploads through a TDLib multi-session pool to Telegram, Google Drive or Rclone.

  • Python 3.12+
  • Docker + Compose v2
  • Linux with /dev/fuse
  • License GPL-3.0
  • Version 2.0.0
Animated pipeline: archive, FUSE engine, TDLib pool, Telegram and cloud A downloaded archive is mounted by the FUSE engine without extraction. Files then stream through four round-robin TDLib sessions to Telegram, with an asynchronous backup to Google Drive and Rclone. aria2c · qBittorrent · SABnzbd · JDownloader2 · yt-dlp archive.zip 33 GB on disk, no copy FUSE archivemount EXTRACTED 0 GB VFS MOUNT .mnt_xxx session 1 session 2 session 3 session 4 TDLib pool · round-robin uploads Telegram primary leech Google Drive async backup Rclone remotes
The problem it targets

The double-storage penalty on small VPS disks

Classic mirror bots download an archive, extract everything with 7z x, then pre-split the files before uploading. A 33 GB season pack can need roughly 70 to 100 GB of local disk. This fork mounts the archive with archivemount -o readonly,nosave instead, reads each file on the fly, uploads it and purges the temporary split chunk straight away.

Peak disk is capped at the archive size plus one transient split chunk.

Upstream flow (7z x + upfront splits)88.2 GB peak
This fork (FUSE + per-file split)35.4 GB peak

README benchmark profile (author-reported, not independently verified): a 33.0 GB ZIP with 16 episodes of about 2.06 GB each on an 80 GB SSD, 4-core VPS. The README lists a 59.8% smaller disk footprint and 0.0 GB written during extraction.

Key features

Built for big archives and busy Telegram accounts

Everything below comes from the project README and docs.

FUSE zero-double-storage engine

Archives are mounted through Linux VFS with archivemount (readonly,nosave) instead of being extracted. Peak storage is the archive plus one transient split chunk.

Inline Telegram ZIP picker

/leech <link> -e -s opens a paginated keyboard with live sizes, per-file toggles, select all / deselect all, and a 60-second auto-continue timer.

TDLib multi-session pool

Uploads rotate round-robin across several authenticated userbot sessions (tdlib_user, tdlib_user_2, ...). Supports files up to 4 GB with Premium.

Dual leech and Drive backup

Send the primary leech to Telegram, then asynchronously replicate the finished files to Google Drive or Rclone. Each destination has its own failure boundary.

Smart WZML captions

ffprobe and langcodes read duration, audio languages and subtitle tracks and fill a caption template with {filename}, {size}, {duration}, {languages} and {subtitles}.

Multi-engine ingestion

Direct HTTP(S) links, BitTorrent through aria2c and qBittorrent (with search plugins), Usenet via SABnzbd, JDownloader2 and yt-dlp.

Cloud storage options

Google Drive with OAuth or Service Account cycling, Team Drives, Mega.nz and 40+ Rclone storage backends.

Leech vs mirror guard

An is_leech guard keeps /leech tasks from leaking into Google Drive, and cleanup unmounts leftover FUSE mounts with fusermount -uz.

Docker-ready

Ships a Dockerfile and docker-compose.yml. FUSE needs cap_add: SYS_ADMIN and the /dev/fuse device.

How it works

From command to cleaned-up disk in six steps

The end-to-end execution pipeline, as described in the README and architecture docs.

  1. Command and download

    /leech <url> -e -s starts the task. A download engine (aria2c, qBittorrent, SABnzbd, JDownloader2, yt-dlp or direct) fetches the archive.

  2. FUSE mount

    The archive is mounted with archivemount (readonly,nosave) into a virtual .mnt_xxx directory. Nothing is extracted to disk.

  3. Pick your files

    With -s, an inline Telegram keyboard lists the files. Toggle what you want, or let the 60-second timer continue.

  4. Stream, split, upload

    Each selected file is read from the mount. Files over 2 GB (4 GB with Premium) are split on the fly and sent through the TDLib pool or a Pyrogram worker, with a WZML caption.

  5. Deliver

    Telegram is the primary destination. When configured, a secondary Google Drive backup runs asynchronously with an isolated failure boundary.

  6. Clean up

    fusermount -uz unmounts the virtual disk and the workspace is cleaned, so disk usage returns to baseline.

Disk usage through the pipeline, upstream flow versus FUSE flow Illustrative chart based on the README benchmark profile. The upstream flow climbs from 32.8 GB to 88.2 GB and hits the 80 GB disk limit. The FUSE flow stays near 35.4 GB and returns to baseline after cleanup. 0 40 80 80 GB disk 88.2 GB needed: ENOSPC 35.4 GB peak DownloadMountSplitUploadClean
Upstream: extract all, then split allFUSE: mount, stream one file, purge

Illustrative. Figures come from the README benchmark profile (33.0 GB ZIP, 80 GB SSD). Peak on the FUSE path is the archive plus one active split chunk.

TDLib session pool

Round-robin uploads across userbot sessions

Telegram throttles upload concurrency per account and can issue FloodWait penalties. The pool spreads multi-part uploads over several authenticated TDLib sessions managed by bot/core/tdlib_manager.py.

  • Round-robin client acquisition under concurrency locks, so no single session carries every upload.
  • Tunable limits: TG_FILE_UPLOAD_CONCURRENCY (8), TG_SPLIT_UPLOAD_CONCURRENCY (4) and TG_UPLOAD_WORKERS (16) are the defaults documented in the config dictionary.
  • Setup helpers: setup_tdlib_pool.py authenticates extra sessions interactively, and clone_tdlib_pool.py clones an authorized database into new slots.
  • Honest scaling note: the docs say linear speed-up needs a distinct Telegram account per slot. Cloned sessions of one account share that account's bandwidth.
Interactive ZIP picker

Choose episodes inside Telegram, not on the server

After the archive is mounted, the bot sends a paginated inline keyboard. Callback data is compacted to fit Telegram's 64-byte limit (zipsel <mid> <action> [args]).

  • Toggle files with instant checked / unchecked feedback, or select / deselect all.
  • 8 files per page with previous / next navigation and live selected-size totals.
  • 60-second auto-continue: every file starts selected, and if nobody confirms the picker proceeds with the current selection.
  • Small-file pipeline: when only files under 2 GB are chosen, they are uploaded sequentially to avoid choking the single-threaded archivemount daemon.
  • Authorization: the task owner, the bot owner and sudo users can use the picker (documented in the docs).
Select files from ZIPSelected: 3/16 (5.8 GB / 33.2 GB)Page 1/2Tap to toggle. Done to continue (auto Done in 60s).
  • [x] The.K2.S01E01.1080p.NF.WEB-DL.mkv (1.9 GB)
  • [x] The.K2.S01E02.1080p.NF.WEB-DL.mkv (1.9 GB)
  • [x] The.K2.S01E03.1080p.NF.WEB-DL.mkv (2.0 GB)
  • [ ] The.K2.S01E04.1080p.NF.WEB-DL.mkv (1.9 GB)
Ep 01 (1.9 GB)
Ep 02 (1.9 GB)
Ep 03 (2.0 GB)
Ep 04 (1.9 GB)
Prev Page
Next Page
Select All
Deselect All
Done (Start Leech)  |  Cancel Task
The.K2.S01E01.1080p.NF.WEB-DL.DDP2.0.H.264.mkv 1.94 GB duration 01:04:12 | Korean [Original], English SUBTITLES : English, Spanish, French, Bengali

Mock-up reproduced from the README example, including the WZML caption output (shown without emoji).

Project visuals

Architecture and demo, straight from the repo

These images ship in the repository's docs/assets folder. The project README also links a full HD promo video.

Five-stage architecture diagram: archive ingestion, FUSE VFS mount, Telegram ZIP picker, split and TDLib pool, dual delivery, plus the automated teardown lifecycle
Repository architecture diagram: ingestion, FUSE mount, ZIP picker, split and TDLib pool, dual delivery and teardown.
Frame from the project demo showing the Select files directly inside Telegram ZIP picker with Ep 01 to Ep 04
A frame from the repo's demo.gif: the ZIP picker inside Telegram.
Want the full demo?

The README links a 1080p 60 fps promo video and an animated demo GIF. Both are large files, so they stay on GitHub.

Open the promo video on GitHub · demo.gif

Versus upstream

What changed compared with upstream MLTB

The README compares this fork with anasty17/mirror-leech-telegram-bot.

SubsystemUpstream MLTB (anasty17)This forkBenefit
Archive decompressionFull disk extract (7z x)Linux FUSE (archivemount)50%+ disk savings, no raw extraction overhead
Selective extractionCLI flags / all-or-nothingInteractive Telegram ZIP pickerPaginated GUI, checkboxes, size preview
Archive splittingExtract all, then split allStreaming per-file split and purgePeak storage capped at archive + 1 chunk (under 2.5 GB)
Telegram upload coreSingle client / PyrogramTDLib multi-session poolRound-robin account load balancing
Secondary backupTelegram or cloud onlyDual leech + Drive backupIndependent failure boundary
Dynamic captionsBasic static textWZML ffprobe engineCodecs, duration, audio and subtitle tracks
Download enginesaria2, qBit, Sabnzbdaria2, qBit, Sabnzbd, JD2, yt-dlpBroader protocol and media-site coverage
Cloud syncGDrive / RcloneGDrive OAuth + SA + RcloneMulti-remote management, SA rotation

Benchmark profile reported in the README

33.0 GB ZIP with 16 episodes (about 2.06 GB each) on an 80 GB SSD, 4-core VPS. These are the author's figures and were not independently reproduced here.

MetricUpstream (7z x)This forkDelta reported
Peak disk allocation88.2 GB (ENOSPC crash)35.4 GB (archive + 1 split)-59.8%
Extraction-phase disk writes35.2 GB0.0 GB-100%
Extraction latency6 to 12 min decompression waitunder 800 ms (virtual mount)99.8% faster readiness
Transient split overhead+20.0 GB+2.4 GB-88.0%
Resident RAM (FUSE)n/a (writes to disk)20 to 50 MB (index cache)Low memory footprint
Upload concurrency1 accountUp to 10+ accounts round-robin10x headroom
Split upload throughputSequential blockingConcurrent multi-worker3.2x real-world throughput
Quick start

Deploy with Docker Compose

Commands below are copied from the README. Run them on a Linux host.

Prerequisites. Linux (Ubuntu 22.04 / 24.04 LTS or Debian 12 recommended, kernel 6.8+), Docker Engine 24+ with Docker Compose v2, host support for /dev/fuse, plus a bot token from @BotFather and API credentials from my.telegram.org.

1 Clone the repository

git clone https://github.com/MHJoy99/mirror-leech-telegram-bot-fuse.git
cd mirror-leech-telegram-bot-fuse

2 Configure environment variables

cp config_sample.py config.py
# or cp config_sample.env config.env
nano config.py

3 Initialize the TDLib pool (optional)

python3 setup_tdlib_pool.py 3 tdlib_user

4 Deploy with Docker Compose

Make sure cap_add: [SYS_ADMIN] and the /dev/fuse device mapping are present in docker-compose.yml:

services:
  app:
    build: .
    command: bash start.sh
    restart: on-failure
    cap_add:
      - SYS_ADMIN
    devices:
      - /dev/fuse
    security_opt:
      - apparmor:unconfined
    volumes:
      - ./downloads:/app/downloads
      - ./accounts:/app/accounts
      - ./thumbnails:/app/thumbnails
      - ./tokens:/app/tokens
      - ./rclone:/app/rclone
      - ./qBittorrent:/app/qBittorrent
      - ./sabnzbd:/app/sabnzbd
      - ./token.pickle:/app/token.pickle
      - ./credentials.json:/app/credentials.json
      - ./cookies.txt:/app/cookies.txt
      - ./.netrc:/app/.netrc
docker compose up -d --build

Operate and inspect

# real-time container logs
docker compose logs -f app

# filter FUSE and upload events
docker compose logs --tail=100 -f app | grep -E "FUSE|archivemount|Upload|Leech"

# check active FUSE virtual mounts
grep "archivemount" /proc/mounts

# force-unmount lingering virtual mountpoints
fusermount -uz /app/downloads/*/.mnt_*
Usage and configuration

Commands and key settings

Bot commands

CommandWhat it does
/leech <url>Download and upload to Telegram
/leech <url> -eMount via FUSE and leech all files
/leech <url> -e -sMount via FUSE and show the inline ZIP picker
/mirror <url>Download and upload to Google Drive or Rclone
/mirror <url> -eExtract and mirror contents to cloud
/ytdl <url>Download media via yt-dlp, leech or mirror
/statusActive downloads, speeds, ETA, progress
/cancel <gid> or allCancel one task or all
/bsettingsGlobal bot settings (admin only)
/usettingsUser settings: captions, split sizes, prefixes

config.py highlights

# Telegram bot credentials (placeholders)
BOT_TOKEN = "1234567890:ABCdefGHIjklMNOpqrsTUVwxyz"
OWNER_ID = 987654321
TELEGRAM_API = 1234567
TELEGRAM_HASH = "0123456789abcdef0123456789abcdef"

# TDLib multi-session pool
TDLIB_USER_DB_PATH = "tdlib_user"
TDLIB_USER_DB_PATHS = ["tdlib_user_2", "tdlib_user_3", "tdlib_user_4"]
TDLIB_USER_UPLOAD = True

# Concurrency tuning
TG_FILE_UPLOAD_CONCURRENCY = 8
TG_SPLIT_UPLOAD_CONCURRENCY = 4
TG_UPLOAD_WORKERS = 16
LEECH_SPLIT_SIZE = 2097152000  # 2GB (4194304000 for 4GB Premium)

Full variable list: config_sample.py and the configuration dictionary.

Documentation hub

FAQ

Frequently asked questions

How does FUSE achieve zero double storage on huge archives?

Conventional Telegram mirror bots extract the whole archive to disk with 7z x, which can double storage use (for example a 35 GB ZIP plus 35 GB of extracted files). mirror-leech-telegram-bot-fuse instead mounts the archive read-only through a virtual file system directory with archivemount -o readonly,nosave. Files are read on the fly and uploaded one after another, so total disk use is bounded by the archive size plus a single active split chunk of about 2 GB.

Does archivemount decompress the whole archive into RAM?

No. According to the README, archivemount only parses the archive index headers into memory, roughly 20 to 50 MB. When ffmpeg or the uploader reads a specific file offset, archivemount seeks to that byte range and decompresses only the active stream buffer, so memory stays small and stable during multi-gigabyte transfers.

How does the TDLib multi-session pool improve uploads?

Telegram throttles upload concurrency per account and can issue FloodWait penalties under heavy load. The pool distributes multi-part uploads across several authenticated userbot sessions (tdlib_user, tdlib_user_2, tdlib_user_3 and so on) in round-robin rotation, and supports files up to 4 GB with a Premium account.

The setup guide notes that linear speed-up needs a distinct Telegram account for each pool slot. Sessions cloned from one account share that account’s bandwidth quota.

What happens if a file inside a mounted ZIP is larger than 2 GB?

The streaming engine reads the file from the FUSE mount, writes split chunks one at a time into a temporary workspace, uploads each chunk through the worker pool, and purges each chunk from disk before starting the next. Disk usage therefore does not balloon, whatever the archive size. The split size is set with LEECH_SPLIT_SIZE (2 GB by default, 4 GB for Telegram Premium).

How does the dual Telegram leech plus Google Drive backup work?

When it is configured, the bot first completes the primary Telegram leech and then starts an asynchronous secondary upload to Google Drive. The two destinations have independent failure boundaries: if Google Drive hits a quota limit or a timeout, the Telegram leech is still completed and delivered.

Why are small files uploaded one at a time?

The archivemount daemon is single-threaded. Opening many concurrent file handles on the FUSE layer causes I/O contention and stalled transfers. For small files the bot uses an anti-choke sequential dispatcher that symlinks each file into an isolated temporary workspace and uploads them one by one.

What happens if I do not answer the ZIP picker?

The inline ZIP picker has a 60-second safety timer. Every file starts selected, and if nobody confirms in time the picker continues with the current selection so that automated batch tasks do not freeze indefinitely. Tapping Cancel Task aborts the task instead.

What do I need to run it?

A Linux host (Ubuntu 22.04 or 24.04 LTS or Debian 12 recommended, kernel 6.8+), Docker Engine 24+ with Docker Compose v2, and FUSE support through /dev/fuse. The compose file must grant cap_add SYS_ADMIN and map the /dev/fuse device. You also need a bot token from @BotFather and API credentials from my.telegram.org. The bot targets Python 3.12+ and ships a Dockerfile.

Is this a fork of mirror-leech-telegram-bot, and what is the license?

Yes. It builds on python-aria-mirror-bot and anasty17’s mirror-leech-telegram-bot and adds the FUSE engine, ZIP picker, TDLib pool, dual backup and WZML captions. It is distributed under the GNU General Public License v3.0 and maintained by MHJoy99 and the MHJoyBots team. It is not affiliated with Telegram or Google.

Which download engines and cloud destinations are supported?

Ingestion covers direct HTTP(S) links, BitTorrent through aria2c and qBittorrent, Usenet through SABnzbd, JDownloader2, Mega and yt-dlp for video and audio sites. Destinations include Telegram chats and channels, Google Drive (OAuth or Service Accounts, Team Drives) and Rclone remotes.

Credits, license and responsible use

Built on open-source work

License. Distributed under the GNU General Public License v3.0 (GPL-3.0).
Upstream ecosystem. Built on foundational work from python-aria-mirror-bot and mirror-leech-telegram-bot.
FUSE engine and innovations. Engineered and maintained by MHJoy99 and the MHJoyBots team.
Use responsibly. This is a self-hosted tool that moves files between services you configure. Only download, mirror or upload content you have the right to handle, and respect the terms of service of Telegram, Google Drive, any download source and every other service you use, as well as applicable law. You are responsible for how your own instance is used.