mirror of
https://github.com/djimboy/djimbo_template_aio3.git
synced 2026-07-25 09:44:29 +00:00
303 lines
11 KiB
Markdown
303 lines
11 KiB
Markdown
# Djimbo Template для Telegram-ботов на aiogram 3
|
|
|
|
Шаблон для быстрого старта Telegram-бота на `aiogram 3`, `SQLAlchemy`, `aiosqlite`, `Alembic` и `.env`-настройках через `pydantic-settings`.
|
|
|
|
Внутри уже есть базовая структура проекта, подключение роутеров, middleware для пользователя, админские фильтры, логирование, миграции БД и пример пользовательского/админского меню.
|
|
|
|
## Стек
|
|
|
|
- Python 3.11
|
|
- aiogram 3.28.2
|
|
- SQLAlchemy 2.x
|
|
- aiosqlite
|
|
- Alembic
|
|
- APScheduler
|
|
- aiohttp
|
|
- pydantic-settings
|
|
- pytz
|
|
|
|
## Быстрый старт
|
|
|
|
1. Создание виртуального окружения:
|
|
|
|
```bash
|
|
python3.11 -m venv .venv
|
|
source .venv/bin/activate
|
|
```
|
|
|
|
2. Установка зависимостей:
|
|
|
|
```bash
|
|
pip install -r requirements.txt
|
|
```
|
|
|
|
|
|
3. Создание локального конфига:
|
|
|
|
```bash
|
|
cp .env.example .env
|
|
```
|
|
|
|
4. Заполнение `.env`:
|
|
|
|
```env
|
|
BOT_TOKEN=123456:telegram_bot_token
|
|
BOT_ADMIN_IDS=123456789
|
|
BOT_DATABASE_EXPORT=False
|
|
```
|
|
|
|
`BOT_ADMIN_IDS` можно указать через запятую: `123456789,987654321`.
|
|
|
|
5. Применение миграций:
|
|
|
|
```bash
|
|
python migrate.py up
|
|
```
|
|
|
|
Без аргументов `python migrate.py` только показывает подсказки. Бот сам миграции при старте не запускает, чтобы не менять схему базы неожиданно.
|
|
|
|
6. Запуск бота:
|
|
|
|
```bash
|
|
python main.py
|
|
```
|
|
|
|
## Docker Compose
|
|
|
|
Запуск через compose:
|
|
|
|
```bash
|
|
docker compose up --build
|
|
```
|
|
|
|
Остановка:
|
|
|
|
```bash
|
|
docker compose down
|
|
```
|
|
|
|
`docker-compose.yml` использует `Dockerfile`: Dockerfile собирает образ, а compose управляет запуском, `.env`, volume и restart-политикой.
|
|
|
|
При запуске контейнер сначала применяет миграции командой `python migrate.py up`, а потом запускает бота через `python main.py`.
|
|
|
|
Volume `./tgbot/data:/app/tgbot/data` нужен, чтобы база и логи не пропадали после остановки контейнера.
|
|
|
|
Если compose не нужен, можно запустить Docker вручную:
|
|
|
|
```bash
|
|
docker build -t djimbo-template .
|
|
docker run --rm --env-file .env -v "$(pwd)/tgbot/data:/app/tgbot/data" djimbo-template
|
|
```
|
|
|
|
## pyproject.toml
|
|
|
|
`pyproject.toml` описывает проект для современных Python-инструментов.
|
|
|
|
В этом шаблоне он нужен для:
|
|
|
|
- указания версии Python;
|
|
- описания зависимостей проекта;
|
|
- установки проекта как пакета через `pip install -e .`;
|
|
- настройки сборки через `setuptools`.
|
|
|
|
`requirements.txt` оставлен для простого запуска и Docker. Если коротко: `requirements.txt` удобен для установки зависимостей, а `pyproject.toml` описывает сам проект.
|
|
|
|
## Настройки
|
|
|
|
| Параметр | Что делает |
|
|
| --- | --- |
|
|
| `BOT_TOKEN` | Токен Telegram-бота от BotFather |
|
|
| `BOT_ADMIN_IDS` | Telegram ID админов, один или несколько через запятую |
|
|
| `BOT_DATABASE_EXPORT` | Разрешает отправку файла БД админам через `/db` и ежедневный автобэкап |
|
|
| `BOT_STATUS_NOTIFICATION` | Включает уведомление админов о запуске |
|
|
| `BOT_TIMEZONE` | Временная зона бота |
|
|
| `BOT_USER_CACHE_TTL` | Время кеширования пользователя в middleware |
|
|
| `BOT_THROTTLE_RATE` | Базовая задержка антиспама |
|
|
| `PATH_DATABASE` | Путь к SQLite-базе |
|
|
| `PATH_LOGS` | Путь к файлу логов |
|
|
|
|
По умолчанию `BOT_DATABASE_EXPORT=False`. Это специально: база может содержать персональные данные, поэтому экспорт надо включать руками и осознанно.
|
|
|
|
## Структура проекта
|
|
|
|
```text
|
|
.
|
|
├── main.py # Точка входа
|
|
├── migrate.py # Удобная CLI-обертка для Alembic
|
|
├── Dockerfile # Запуск шаблона в Docker
|
|
├── docker-compose.yml # Удобный запуск Docker-контейнера
|
|
├── .dockerignore # Что не попадет в Docker-образ
|
|
├── pyproject.toml # Метаданные проекта
|
|
├── alembic.ini # Настройки Alembic
|
|
├── migrations/ # Миграции базы данных
|
|
├── .env.example # Пример локального .env
|
|
├── tgbot/
|
|
│ ├── data/config.py # Настройки и пути
|
|
│ ├── database/ # SQLAlchemy-модели и репозитории
|
|
│ ├── keyboards/ # Reply и inline-клавиатуры
|
|
│ ├── middlewares/ # Middleware
|
|
│ ├── routers/ # Обработчики aiogram
|
|
│ ├── services/ # Внешние сервисы и aiohttp-сессия
|
|
│ └── utils/ # Общие утилиты
|
|
└── requirements.txt
|
|
```
|
|
|
|
## База данных
|
|
|
|
Проект использует SQLite через `aiosqlite`, но работа с таблицами идёт через async `SQLAlchemy`.
|
|
|
|
Ключевые файлы БД:
|
|
|
|
- `core.py` - `Base`, `engine`, `session_factory`, `session_scope`
|
|
- `repository.py` - базовый репозиторий и проверка готовности БД
|
|
- `migration_runner.py` - запуск Alembic из кода
|
|
- `db_users.py` - пользователи Telegram
|
|
- `db_settings.py` - настройки бота в БД
|
|
|
|
### UNIQUE
|
|
|
|
В таблице пользователей поле `user_id` уникальное.
|
|
|
|
Это значит, что один Telegram-пользователь не может появиться в таблице два раза. Если пользователь уже есть, база не создаст дубль.
|
|
|
|
### UPSERT
|
|
|
|
UPSERT - это логика “создай запись, а если она уже есть, обнови”.
|
|
|
|
В шаблоне пользователь добавляется по `user_id`. Если он уже есть, обновляются только изменившиеся поля: username, имя, фамилия и полное имя. Если данные не поменялись, лишнего UPDATE в БД не будет.
|
|
|
|
## Миграции
|
|
|
|
Миграции управляются через Alembic, но запускать их удобнее через готовый CLI.
|
|
|
|
Показать справку:
|
|
|
|
```bash
|
|
python migrate.py
|
|
```
|
|
|
|
Применить все миграции:
|
|
|
|
```bash
|
|
python migrate.py up
|
|
```
|
|
|
|
То же самое длинной командой:
|
|
|
|
```bash
|
|
python migrate.py upgrade
|
|
```
|
|
|
|
Посмотреть текущую версию БД:
|
|
|
|
```bash
|
|
python migrate.py status
|
|
```
|
|
|
|
Посмотреть историю:
|
|
|
|
```bash
|
|
python migrate.py history
|
|
```
|
|
|
|
Создать новую миграцию вручную:
|
|
|
|
```bash
|
|
python migrate.py new "add payments table"
|
|
```
|
|
|
|
Создать миграцию по изменениям SQLAlchemy-моделей:
|
|
|
|
```bash
|
|
python migrate.py auto "add payments table"
|
|
```
|
|
|
|
Откатить последнюю миграцию:
|
|
|
|
```bash
|
|
python migrate.py down
|
|
```
|
|
|
|
Полные Alembic-команды тоже доступны: `upgrade`, `downgrade`, `revision`, `current`, `history`, `heads`.
|
|
|
|
Короткие алиасы: `up`, `down`, `new`, `auto`, `autogen`, `cur`, `hist`, `st`.
|
|
|
|
## Роутеры
|
|
|
|
Роутеры подключаются в `tgbot/routers/__init__.py`.
|
|
|
|
Текущие группы:
|
|
|
|
- `main_start.py` - старт и главное меню
|
|
- `user/user_menu.py` - пользовательские обработчики
|
|
- `admin/admin_menu.py` - админские обработчики
|
|
- `main_missed.py` - fallback на неизвестные сообщения и callback
|
|
- `main_errors.py` - обработка безопасных Telegram-ошибок
|
|
|
|
Админский роутер уже закрыт фильтром `IsAdmin()` и для сообщений, и для callback query.
|
|
|
|
## Middleware
|
|
|
|
`ExistsUserMiddleware` добавляет или обновляет пользователя в БД и прокидывает объект пользователя в обработчик как `User`.
|
|
|
|
Чтобы не писать в БД на каждый одинаковый update, middleware кеширует пользователя по `user_id`.
|
|
|
|
Пример:
|
|
|
|
```python
|
|
async def handler(message: Message, User: UserModel):
|
|
await message.answer(User.user_fullname)
|
|
```
|
|
|
|
## Логирование
|
|
|
|
Логи пишутся в `tgbot/data/logs.log`.
|
|
|
|
Файл не растёт бесконечно: используется `RotatingFileHandler`, который вращает логи по размеру.
|
|
|
|
Админ может получить логи командой:
|
|
|
|
```text
|
|
/log
|
|
```
|
|
|
|
Очистить логи:
|
|
|
|
```text
|
|
/clear_log
|
|
```
|
|
|
|
## Админские команды
|
|
|
|
| Команда | Что делает |
|
|
| --- | --- |
|
|
| `/log` | Отправляет файл логов |
|
|
| `/clear_log` | Очищает файлы логов |
|
|
| `/db` | Отправляет файл БД, только если `BOT_DATABASE_EXPORT=True` |
|
|
|
|
Команда `/db` скрывается из меню команд, если экспорт БД выключен.
|
|
|
|
## Как добавить новую таблицу
|
|
|
|
1. Создать модель в `tgbot/database/`.
|
|
2. Импортировать её в `tgbot/database/__init__.py`.
|
|
3. Создать миграцию:
|
|
|
|
```bash
|
|
python migrate.py auto "add new table"
|
|
```
|
|
|
|
4. Проверить созданный файл в `migrations/versions/`.
|
|
5. Применить миграцию:
|
|
|
|
```bash
|
|
python migrate.py up
|
|
```
|
|
|
|
## Важно
|
|
|
|
- Не коммить `.env`, базу данных и логи.
|
|
- Если токен попал в Git, его надо перевыпустить у BotFather.
|
|
- Перед деплоем проверь `BOT_DATABASE_EXPORT`: на проде лучше держать `False`, если экспорт БД реально не нужен.
|
|
- Для нового проекта сначала менять тексты, команды и клавиатуры под свою логику, а потом уже добавлять бизнес-код.
|