Как я «try|tried» написать на Rust

Моя цель - предложение широкого ассортимента товаров и услуг на постоянно высоком качестве обслуживания по самым выгодным ценам.
Вот так Chat GPT представила человека, если бы это был язык Rust
Вот так Chat GPT представила человека, если бы это был язык Rust

Я CEO своей компании MediaRise (компания только начала развиваться), с техническим бэкграундом. Сам люблю писать на разных языках, а вернее пробывать работать с ними. Давно уже слышал о таком языке как Rust.

Rust — это современный системный язык программирования, разработанный для обеспечения высокой производительности и безопасности, особенно при работе с конкурентными процессами. Изначально он был разработан компанией Mozilla, а сейчас поддерживается фондом Rust Foundation. Rust приобретает все большую популярность благодаря своей надежности и эффективности.

Ключевые особенности Rust:

Ключевые особенности Rust:

  1. Безопасность памяти: Rust устраняет общие ошибки программирования, такие как разыменование нулевого указателя и переполнение буфера, благодаря строгой проверке на этапе компиляции, без использования сборщика мусора.

  2. Система владения: Уникальная система владения Rust обеспечивает безопасность памяти без необходимости в сборщике мусора. Она использует систему владения с правилами, которые проверяются компилятором на этапе компиляции.

  3. Конкурентность: Rust упрощает написание конкурентных программ, предотвращая состояния гонки на этапе компиляции благодаря концепциям владения и заимствования.

  4. Производительность: Rust разрабатывался с целью быть таким же быстрым, как и C++, и часто демонстрирует сопоставимую производительность. Он может использоваться для системного программирования, где критична производительность.

  5. Выразительная типовая система: Rust обладает мощной типовой системой, включающей такие возможности, как сопоставление с образцом, алгебраические типы данных и обобщенные типы на основе трейтов, что позволяет писать более выразительный и безопасный код.

  6. Cargo: Rust поставляется с Cargo, системой сборки и менеджером пакетов, который упрощает управление зависимостями, сборку и распространение кода.

  7. Экосистема: Экосистема Rust включает растущую коллекцию библиотек и инструментов, которые помогают разработчикам писать надежный и эффективный код. Официальный реестр пакетов, crates.io, содержит тысячи библиотек с открытым исходным кодом.

Сферы применения Rust:

  1. Системное программирование: Rust идеально подходит для написания операционных систем, драйверов устройств и других низкоуровневых задач, где критичны контроль над оборудованием и производительность.

  2. WebAssembly: Rust может компилироваться в WebAssembly, что позволяет запускать код Rust в веб-браузерах с производительностью, близкой к нативной.

  3. Сетевое программирование: Особенности безопасности и производительность Rust делают его подходящим для написания сетевого ПО, включая веб-серверы и клиенты.

  4. Разработка игр: Производственные характеристики Rust делают его хорошим выбором для разработки игр, где скорость и эффективность критичны.

  5. Командные утилиты: Менеджер пакетов Cargo упрощает создание и распространение командных утилит.

Известные проекты, использующие Rust:

  1. Firefox Quantum: Mozilla использовала Rust для переписывания частей их движка браузера, что привело к значительному улучшению производительности.

  2. Dropbox: Dropbox использует Rust для некоторых своих серверных сервисов.

  3. Cloudflare: Cloudflare использует Rust для нескольких своих производительно критичных сервисов.

  4. Rustlings: Образовательный проект, который помогает изучать Rust через небольшие упражнения.

Комбинация безопасности, производительности и поддержки конкурентности делает Rust привлекательным выбором для многих видов разработки программного обеспечения. Его растущая популярность и активное сообщество гарантируют, что Rust продолжит развиваться и улучшаться.

Думал над идеей, что бы такого реализовать на данном языке. Так как у меня подруга Тайка, есть проблемы при общении в мессенджерах, захотелось написать телеграмм бота, который бы двунаправленно в чате группы переводил с русского на тайский и наоборот.

Понимаю что есть готовые решения, но захотел создать свой велосипед, опробовать новый язык rust.

Идея есть, с телеграмм ботом проблемы нет, но есть проблема с сервисом который будет переводить с одного языка на другой. Выбор пал на LibreTranslate. Что бы его использовать бесплатно, необходимо развернуть на своем сервере приложение.Я так и сделал, установил зависимости, развернул в Docker контейнере. Проблем не было. единственное приложение необходимо запускать с флагом: ./run.sh --api-keys, для того что бы можно получить api_key. Подробнее о настройке и получения api-key LiberTranslate можно почитать на официальном сайте

Развернув сервер LiberTranslate и получив токен телеграм бота, осталось реализовать приложение. Просмотрев официальную документацию по Rust и наработки на github, я начал творить. Установил rust и corgo (регистр(менеджер) пактов для Rust). Изучив документацию teloxide библиотеки для телеграмм бота написанной на rust, написал обработчик на события сообщений в чате.

#[tokio::main]
async fn main() -> ResponseResult<()> {
    dotenv().ok();
    env_logger::init();
    let token_bot = env::var("TELEGRAM_BOT_KEY").expect("TELEGRAM_BOT_KEY not found");

    let bot = teloxide::Bot::new(&token_bot).parse_mode(ParseMode::Html);

    // Create a handler for our bot, that will process updates from Telegram
    let handler = dptree::entry()
        .inspect(|u: Update| {
                    eprintln!("{u:#?}"); // Print the update to the console with inspect
        })

   ...

        .branch(
            Update::filter_message()
                .branch(
                    dptree::endpoint(translate_message),
                )
        );

    // Create a dispatcher for our bot
    Dispatcher::builder(bot, handler).enable_ctrlc_handler().build().dispatch().await;

    Ok(())
}

async fn translate_message(bot: Bot, msg: Message) -> ResponseResult<()> {
    if let Some(text) = msg.text() {

        match translate(text).await {
            Ok(translated_word) => {
                bot.send_message(msg.chat.id, translated_word).await?;
            }
            Err(e) => {
                bot.send_message(msg.chat.id, format!("Translation error: {}", e)).await?;
            }
        }
    } else {
        bot.send_message(msg.chat.id, "Send me plain text.").await?;
    }

    Ok(())
}

Далее саму функцию для запроса перевода с приложения LiberTranslate. Суть такова, приложение по переводу определяет на каком языке сообщение и переводит на необходимый (ru -> th, th -> ru)

async fn translate(text: &str) -> ResponseResult<String> {
    let client = reqwest::Client::new();

    let api_translate_url = env::var("API_TRANSLATE_URL").expect("API_TRANSLATE_URL not found");
    let api_translate_key = env::var("API_TRANSLATE_KEY").expect("API_TRANSLATE_KEY not found");
    let api_detect_url = env::var("API_DETECT_URL").expect("API_DETECT_URL not found");
    eprintln!("{text:#?}");

    let detect_request = DetectRequest {
        q: String::from(text),
        api_key: String::from(api_translate_key.clone()),
    };

    let res = client.post(api_detect_url)
        .header("Content-Type", "application/x-www-form-urlencoded")
        .form(&detect_request)
        .send()
        .await?;
    let resp_json = res.json::<Vec<DetectResponse>>().await?;

    let lang = &resp_json[0].language;

    eprintln!("{lang:#?}");
    let target_lang = if lang == "ru" { "th" } else { "ru" };

    let json_object = json!({
                "q": text,
                "source": "auto",
                "target": target_lang,
                "format": "text",
                "alternatives": 3,
                "api_key": api_translate_key
            });

    let json_string = serde_json::to_string(&json_object).unwrap();


    let res = client.post(api_translate_url)
        .body(json_string)
        .header("Content-Type", "application/json")
        .send()
        .await?;

    let resp_json = res.json::<TranslateResult>().await?;
    let translated_word = resp_json.translatedText;
    Ok(translated_word)
}

Вот такой результат в самом Telegram чате

Изображение с чата
Изображение с чата

Были проблемы с багами, которые были из за того что я использовал старые библиотеки на Rust, когда пытался проблему решить с помощью ChatGPT. Но больше помог живой опыт разработчиков с GitHub, где я смотрел реализацию какого либо функционала: API документация бота, работа с env (файлами окружения), примеры работы с json, отправка rest запросов и также работу конструкции языка.

Я очень рад рабочему приложению, потому что ранее не писал на Rust и это меня вдохновило изучать его дальше. Опытные разработчики наверняка подскажу как можно оптимизировать код, чему я буду очень рад.

Осталось сбилдить приложение и запустить его в режиме демона на сервере

Настройка systemd

Соберите ваше приложение с помощью команды:

cargo build --release

Создайте файл юнита для systemd. Например, создадим файл /etc/systemd/system/translate_bot.service

[Unit]
Description=Translate Bot
After=network.target

[Service]
ExecStart=/path/to/your/application
Restart=always
User=yourusername
Group=yourgroupname
Environment=/path/to/your/.env
WorkingDirectory=/path/to/your/application/directory

[Install]
WantedBy=multi-user.target

Перезагрузите конфигурацию systemd, чтобы он узнал о новом сервисе:

sudo systemctl daemon-reload

Запустите сервис:

sudo systemctl start translate_bot

Убедитесь, что сервис запущен и работает:

sudo systemctl status translate_bot

Чтобы ваш сервис автоматически запускался при старте системы, выполните команду:

sudo systemctl enable rust_service

Ваше приложение на Rust будет работать как системный сервис, управляемый systemd. Вы можете контролировать его с помощью стандартных команд systemd, таких как start, stop, restart, и status.

P.S. Хотел бы также решить проблему с env файлами, чтобы доступ к ним был в функции из main.

Далее в планах: я бы хотел реализовать, обработку события если в чате появится новый user (а также ливнет). User может выбрать язык на котором бы он хотел получать перевод. Сами юзеры и их настройки будут хранится в базе PostgreSQL

Всем спасибо за внимание! Исходники выложил на GitHub.

Исходник на GitHub

Источник: https://habr.com/ru/articles/830336/


Интересные статьи

Интересные статьи

Я — большой фанат Rust, так как в этом языке предоставляется отличное инструментальное оснащение, и, когда я пишу на этом языке, я могу быть вполне уверен, что этот код будет работать надёжно. Но ...
Привет, Хабр!Axum была создана командой Tokio, которая уже получила свой +rep за создание асинхронной платформы Tokio для Rust. Axum является микрофреймворком, ориентированным на упрощение задач, связ...
По работе попалась несложная, но достаточно интересная задачка из области обработки данных. Так как она была связана с вычислениями над массивами, то я по-быстрому запрограммировал её на Фортране. Но ...
Неделю назад OpenAI отменила список ожидания для доступа к нейросети GPT-3. Теперь разработчики из 152 стран, где поддерживается сервис, могут зарегистрироваться и свободно пользова...
Rust - это быстрый, надежный и экономичный, с точки зрения памяти, язык программирования. Его признавали одним из самых любимых языков программирования шесть лет подряд (на ос...