
Введение
В данной статье мы рассмотрим архитектуру и реализацию Telegram-бота Kalorik, написанного на языке программирования Rust. Этот бот предоставляет пользователям возможность анализировать свой рацион питания, получая автоматический расчёт калорий, макроэлементов и индекса массы тела. Особенностью проекта является использование современного стека на основе tokio, sqlx, teloxide, а также продуманная архитектура с учётом масштабируемости.
Задачи, решаемые ботом
Kalorik реализует следующие функции:
- Обработка текстовых сообщений с описанием приёма пищи 
- Распознавание изображений и голосовых сообщений 
- Подсчёт калорий, БЖУ, ИМТ 
- Хранение истории и профиля пользователя 
- Настройка целей и отслеживание прогресса 
Архитектура проекта
Проект состоит из следующих ключевых модулей:
- main.rs— точка входа, инициализация окружения и запуск бота
- telegram/- handlers.rs— обработка входящих сообщений Telegram
- db/- queries.rs— доступ к базе данных (PostgreSQL через- sqlx)
- db/- models.rs— структура таблиц и моделей
- services/- nutrition.rs— логика анализа продуктов и подсчёта нутриентов
Проект построен с использованием OnceLock для глобального пула соединений с базой данных и асинхронного исполнения через tokio.
Пример: Регистрация пользователя
pub async fn register_user(chat_id: i64) -> Result<(), sqlx::Error> {
    let Some(pool) = DB_POOL.get() else {
        return Err(sqlx::Error::PoolTimedOut);
    };
    sqlx::query!(
        r#"
        INSERT INTO users (chat_id, created_at)
        VALUES ($1, $2)
        ON CONFLICT (chat_id) DO NOTHING
        "#,
        chat_id,
        Utc::now()
    )
    .execute(pool)
    .await?;
    Ok(())
}
Здесь реализуется вставка пользователя в таблицу, если он отсутствует. Используется UPSERT-подход, обеспечивающий идемпотентность.
Работа с Telegram
match &msg.kind {
    MessageKind::Common(msg) => match &msg.media_kind {
        MediaKind::Text { text, .. } => {
            if text == "/start" {
                register_user(msg.chat.id).await?;
                bot.send_message(msg.chat.id, "Введите описание приёма пищи").await?;
            } else {
                let result = analyze_food_description(text).await;
                bot.send_message(msg.chat.id, result).await?;
            }
        }
        MediaKind::Photo { photo, .. } => {
            // Обработка фото через модель
        }
        MediaKind::Voice { voice, .. } => {
            // Обработка голосовых сообщений
        }
        _ => {}
    }
    _ => {}
}
Здесь представлен разбор варианта обработки текста и мультимедиа. Используется teloxide, который предоставляет удобный API для работы с Telegram Bot API.
Хранение и миграции
let db_url = env::var("DATABASE_URL").expect("DATABASE_URL not set");
let pool = PgPoolOptions::new().connect(&db_url).await?;
sqlx::migrate!("./migrations").run(&pool).await?;Проект использует sqlx с автоматическим применением миграций. Миграции хранятся в отдельной папке и обеспечивают прозрачность в изменениях схемы.
Развёртывание
Бот может быть запущен как systemd-сервис или Docker-контейнер. Пример systemd unit-файла:
[Unit]
Description=Kalorik Telegram Bot
After=network.target
[Service]
ExecStart=/usr/local/bin/kalorik
WorkingDirectory=/var/www/kalorik
Restart=always
Environment=DATABASE_URL=postgres://...
[Install]
WantedBy=multi-user.target
Также возможно подключение GitHub Actions для CI/CD и обновления контейнера при пуше в main ветку.
Заключение
Kalorik демонстрирует, как на Rust можно создать безопасного и надёжного Telegram-бота с использованием производительных и типобезопасных библиотек. Благодаря sqlx, tokio и teloxide, разработка получилась эффективной и лаконичной. Проект легко масштабируется и адаптируется под другие задачи, связанные с пользовательскими данными или обработкой сообщений.
Проект открыт для расширений: можно добавить мини-приложение, авторизацию через Telegram Web App, отчёты по питанию, интеграцию с OpenAI или Hugging Face для анализа описаний еды.
Попробовать бота @kalorikbot
Репозиторий проект, где находится весь код https://github.com/digkill/Kalorik
Комментарии (5)
 - JBFW17.05.2025 16:06- А где функция анализа сообщения пользователя? - Ну например, "я сьел 24 штуки острых крыльев KFC и выпил же чаю" = 114342 калорий? - На Rust. 
 - Cerberuser17.05.2025 16:06- ...надо признать, настолько халтурная КДПВ действительно привлекает внимание. Смысла в статье, впрочем, не видно. 
 
           
 
redfox0
Единственная польза от статьи:
Прям как в pl/sql - ранее связывание sql-кода и проверка валидности sql-запроса (и не много прав доступа) в compile-time.
redfox0
Ну так неинтересно: держать пустую БД с идентичной схемой, только ради compile-time проверок: