WZML-X started as a fork of a Telegram mirror bot — a tool that downloads files from the internet and uploads them to cloud storage, triggered by Telegram commands. It has since grown into something considerably more interesting: a general-purpose automation framework with a plugin architecture, a queued task system, multi-user access control, and a Docker-based deployment model.
This is the engineering story.
The Original Problem
The original bot was functional but fragile. It ran tasks synchronously, which meant one slow download blocked everything. It had no concept of a task queue or worker pool. Configuration was scattered across multiple files. Adding a new download source required modifying core logic.
The first thing I did was separate concerns.
Task Queue Architecture
The core of WZML-X is an async task queue built on top of Python’s asyncio. When a user sends a command, it creates a Task object with a unique ID, serializes it to Redis, and returns immediately with a “task queued” acknowledgment. A pool of async workers picks up tasks from the queue and executes them.
This gives you several things for free:
- Concurrency: Multiple tasks run simultaneously without blocking each other
- Persistence: Tasks survive bot restarts (they’re in Redis, not in memory)
- Progress tracking: Each task has a status field that the bot can report back to the user
- Cancellation: You can remove a task from the queue or interrupt a running worker
The worker pool size is configurable. On a low-resource VPS, 3-5 workers is typical. On a beefier server, 10-20 is reasonable depending on I/O vs. CPU mix.
Plugin Architecture
The original codebase had hardcoded support for specific download sources. I replaced this with a plugin system: each source (direct URL, torrent, YouTube, Google Drive, etc.) is a separate plugin class that implements a standard interface.
class BasePlugin:
async def can_handle(self, url: str) -> bool: ...
async def download(self, url: str, dest: Path, progress_cb) -> DownloadResult: ...
async def get_metadata(self, url: str) -> Metadata: ...
The bot’s core logic doesn’t know anything about specific sources — it iterates registered plugins, finds one that can handle the URL, and delegates. Adding a new source means writing a new plugin class and registering it. No core modifications required.
Multi-User Access Control
The original bot had no access control — anyone who found it could use it. WZML-X has a layered permission model:
- Owner: Full access, can manage users
- Sudo users: Admin-level access, defined in config
- Authorized users/chats: Can use the bot
- Trial users: Limited operations, time-gated access
Permissions are checked at the command handler level. The authorization layer is middleware that wraps every command handler.
Configuration Management
Configuration is now a Pydantic settings model loaded from environment variables or a .env file. Every field has a type, a default, and a description. Configuration errors are caught at startup with a clear error message rather than a cryptic KeyError at runtime.
This makes WZML-X much easier to deploy: copy the example env file, fill in your tokens, run docker-compose up. Done.
Docker Deployment
The entire stack runs in Docker: the bot process, Redis for the task queue, and optionally a web dashboard. The docker-compose.yml is the primary deployment artifact. On a fresh VPS:
git clone https://github.com/SilentDemonSD/WZML-X
cp .env.example .env
# edit .env with your tokens
docker-compose up -d
That’s it. Updates are git pull && docker-compose up -d --build.
What I Learned
Async Python is powerful but requires discipline. asyncio makes concurrency easy but debugging deadlocks and exception propagation requires careful design. The task queue isolates failures: a crashed worker doesn’t bring down the whole bot.
Plugin systems pay off slowly, then all at once. The first three plugins were more work than just hardcoding them. By plugin ten, the pattern was paying dividends.
Redis is the right choice for a Telegram bot task queue. It’s fast, the data structures map naturally to queue semantics, and persistence is handled automatically.
WZML-X has over 1,000 stars on GitHub and is actively used by a community of self-hosters. The issues tracker is the best source of feature ideas — users are creative about what they want to automate.