- Python 3.12+
- Docker
- docker-compose
- make
- uv
- Rename
.env.distto.envand configure it - Rename
docker-compose.example.ymltodocker-compose.yml - Run
make app-buildcommand thenmake app-runto start the bot
Use make to see all available commands
uv syncMake migration script:
make migration message=MESSAGE_WHAT_THE_MIGRATION_DOESRun migrations:
make migrate- uv (an extremely fast Python package and project manager)
- Aiogram 3.x (Telegram bot framework)
- Dishka (async DI container)
- FastAPI (best python web framework for building APIs)
- PostgreSQL (persistent relational database)
- SQLAlchemy (working with database from Python)
- Alembic (lightweight database migration tool)
- Redis (in-memory database for FSM and caching)
- Project Fluent (modern localization system)
Each Telegram update flows through Handler → Flow → Interactor → Presenter → View → Renderer:
handlers only parse the update and call a flow; flows orchestrate interactors and presenters;
interactors hold use-case logic and know nothing about Telegram; presenters build a View
(text + keyboard + render mode); the renderer is the only place that actually calls the Bot API.
Dependencies are wired with dishka and resolved via FromDishka[...].
app/
├── domain/ # SQLAlchemy entities used directly as domain models (no DTOs)
├── application/ # Framework-agnostic core: use cases, ports (protocols), config,
│ cache decorators, storage keys — no aiogram/FastAPI/SQLAlchemy imports
│ ├── interactors/ # use-case logic, one folder per feature
│ ├── ports/ # repository/cache/storage protocols implemented by infrastructure
│ ├── storage/keys/ # typed StorageKey[T] definitions for Redis
│ ├── models/config/ # AppConfig / Assets (env + yaml settings)
│ └── errors/ # application/bot/HTTP error hierarchy
├── infrastructure/ # Implementations of application ports
│ ├── postgres/ # UoW, SqlRepositoryHelper[T], repositories
│ ├── redis/ # cache service + key-value repository
│ ├── localization/ # aiogram-i18n manager, Fluent helpers/patches
│ └── telegram/ # LifespanService — polling/webhook/commands setup
├── presentation/ # Everything that talks to Telegram / HTTP
│ ├── telegram/
│ │ ├── handlers/ # thin routers — one call into a Flow per handler
│ │ ├── flows/ # orchestrate interactors + presenters, call the renderer
│ │ ├── presenters/ # build View objects (text, keyboard, render mode)
│ │ ├── view/ # View/RenderMode/Effect models + Renderer
│ │ ├── keyboards/, callbacks/ # keyboard builders and callback data factories
│ │ ├── filters/, middlewares/ # aiogram filters and middlewares
│ │ └── helpers/ # MessageHelper implementation
│ └── fastapi/ # webhook endpoint + healthcheck
├── providers/ # dishka Provider classes, grouped the same way as the layers above,
│ # wired together in providers/container.py
├── runners/ # run_polling / run_webhook + FastAPI lifespan context managers
└── utils/ # framework-agnostic helpers (json, time, logging, yaml)
Supporting top-level directories:
migrations/— Alembic migration scriptsassets/— static bot assets (e.g.commands.yml)scripts/— dev/ops helper scripts (run-bot.sh,extract-ftl.sh)nginx/,systemd/— example deployment configs for reverse proxy / systemd service
If you want to report a bug or request a new feature, feel free to open a new issue.
If you want to help us improve the bot, you can create a new Pull Request.
This project is licensed under the MIT License - see the LICENSE file for details.