Как я «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 {
    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::>().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::().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

© Habrahabr.ru