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

4.6 KiB
Raw Permalink Blame History

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)

Команды

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 — безопасна для существующей таблицы