# 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`). ## Переменные окружения | Переменная | Описание | |------------------|-----------------------------------| | `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` — безопасна для существующей таблицы