Files
mental_health/CLAUDE.md
Mikhail Kilin b885fd39b9 Переписал бота с 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>
2026-02-16 01:55:20 +03:00

86 lines
4.6 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 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` — безопасна для существующей таблицы