Переписал бота с NestJS/TypeScript на Rust
Стек: teloxide + sqlx + axum + tokio-cron-scheduler. Вся логика перенесена: /start, /help, /settings, выбор частоты, cron-рассылка цитат, admin API. Совместимость с существующей БД сохранена (camelCase колонки). Старый TypeScript-код удалён. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
85
CLAUDE.md
Normal file
85
CLAUDE.md
Normal file
@@ -0,0 +1,85 @@
|
||||
# Mental Health Bot
|
||||
|
||||
Telegram-бот на Rust, который отправляет пользователям мотивирующие цитаты с настраиваемой периодичностью.
|
||||
|
||||
## Стек технологий
|
||||
|
||||
- **Язык**: Rust (edition 2021)
|
||||
- **Async runtime**: tokio
|
||||
- **Telegram**: teloxide 0.13
|
||||
- **База данных**: PostgreSQL через sqlx 0.8
|
||||
- **HTTP (admin API)**: axum 0.8
|
||||
- **Планировщик**: tokio-cron-scheduler 0.13
|
||||
|
||||
## Структура проекта
|
||||
|
||||
```
|
||||
mental_health/
|
||||
├── Cargo.toml
|
||||
├── .env # BOT_TOKEN, DATABASE_URL, ADMIN_PASSWORD, PORT
|
||||
├── migrations/
|
||||
│ └── 20260216000000_create_users.sql
|
||||
├── quotes.json # ~200 мотивирующих цитат на русском языке
|
||||
└── src/
|
||||
├── main.rs # Точка входа: pool + bot + axum + scheduler
|
||||
├── config.rs # Загрузка env vars в struct Config
|
||||
├── app_state.rs # Shared state: PgPool, Bot, Config, QuotesStore
|
||||
├── db.rs # SQL-запросы (User struct + CRUD функции)
|
||||
├── quotes.rs # Загрузка quotes.json, случайная цитата
|
||||
├── bot.rs # Teloxide: /start, /help, /settings, callback frequency_N
|
||||
├── scheduler.rs # Cron каждый час — рассылка цитат
|
||||
└── admin.rs # Axum: POST /admin/send-message
|
||||
```
|
||||
|
||||
## Архитектура runtime
|
||||
|
||||
```
|
||||
tokio::main
|
||||
├── tokio::spawn(axum) → HTTP-сервер на 0.0.0.0:PORT
|
||||
├── tokio::spawn(scheduler) → cron "0 0 * * * *"
|
||||
└── dispatcher.dispatch() → teloxide long-polling (блокирует main)
|
||||
```
|
||||
|
||||
Все три системы разделяют один tokio runtime, один `PgPool` и один `Bot` (через `Arc<AppState>`).
|
||||
|
||||
## Переменные окружения
|
||||
|
||||
| Переменная | Описание |
|
||||
|------------------|-----------------------------------|
|
||||
| `BOT_TOKEN` | Токен Telegram-бота |
|
||||
| `DATABASE_URL` | Строка подключения к PostgreSQL |
|
||||
| `ADMIN_PASSWORD` | Пароль для админского API |
|
||||
| `PORT` | Порт HTTP-сервера (по умолчанию 3000) |
|
||||
|
||||
## Ключевая логика
|
||||
|
||||
- **Регистрация**: при `/start` бот создаёт/обновляет пользователя в БД через `INSERT ON CONFLICT`
|
||||
- **Настройки**: пользователь выбирает частоту получения цитат (1, 3, 5, 7, 9, 12 часов) через inline-кнопки
|
||||
- **Рассылка**: cron каждый час — для каждого пользователя проверяется, прошло ли достаточно времени с последней отправки (с допуском 3 мин), и отправляется случайная цитата
|
||||
- **Админка**: REST endpoint `POST /admin/send-message` с JSON body `{ userId, password, message }` (camelCase)
|
||||
|
||||
## Команды
|
||||
|
||||
```bash
|
||||
cargo build # Сборка
|
||||
cargo run # Запуск (dev)
|
||||
cargo build --release # Релизная сборка
|
||||
cargo clippy # Линтер
|
||||
cargo fmt # Форматирование
|
||||
cargo test # Тесты
|
||||
cargo sqlx prepare # Подготовка офлайн-запросов для CI
|
||||
```
|
||||
|
||||
## Стиль кода
|
||||
|
||||
- `cargo fmt` — стандартный rustfmt
|
||||
- `cargo clippy` — без предупреждений
|
||||
- Комментарии в коде — на русском языке
|
||||
|
||||
## Особенности
|
||||
|
||||
- Имена колонок в БД — camelCase в кавычках (`"telegramId"`, `"lastQuoteSentAt"`) для совместимости с Prisma-схемой
|
||||
- SQL-запросы используют AS-алиасы для маппинга в snake_case поля Rust-структуры
|
||||
- Цитаты загружаются один раз при старте в `QuotesStore` (в отличие от TypeScript-версии, где файл читался при каждом запросе)
|
||||
- Постоянная кнопка "⚙️ Настройки" отображается через `KeyboardMarkup::resize_keyboard()`
|
||||
- Миграция использует `IF NOT EXISTS` — безопасна для существующей таблицы
|
||||
Reference in New Issue
Block a user