Я CEO своей компании MediaRise (компания только начала развиваться), с техническим бэкграундом. Сам люблю писать на разных языках, а вернее пробовать работать с ними. Давно уже слышал о таком языке как Rust.
Rust — это современный системный язык программирования, разработанный для обеспечения высокой производительности и безопасности, особенно при работе с конкурентными процессами. Изначально он был разработан компанией Mozilla, а сейчас поддерживается фондом Rust Foundation. Rust приобретает все большую популярность благодаря своей надежности и эффективности.
Ключевые особенности Rust:
Ключевые особенности Rust:
-
Безопасность памяти: Rust устраняет общие ошибки программирования, такие как разыменование нулевого указателя и переполнение буфера, благодаря строгой проверке на этапе компиляции, без использования сборщика мусора.
-
Система владения: Уникальная система владения Rust обеспечивает безопасность памяти без необходимости в сборщике мусора. Она использует систему владения с правилами, которые проверяются компилятором на этапе компиляции.
-
Конкурентность: Rust упрощает написание конкурентных программ, предотвращая состояния гонки на этапе компиляции благодаря концепциям владения и заимствования.
-
Производительность: Rust разрабатывался с целью быть таким же быстрым, как и C++, и часто демонстрирует сопоставимую производительность. Он может использоваться для системного программирования, где критична производительность.
-
Выразительная типовая система: Rust обладает мощной типовой системой, включающей такие возможности, как сопоставление с образцом, алгебраические типы данных и обобщенные типы на основе трейтов, что позволяет писать более выразительный и безопасный код.
-
Cargo: Rust поставляется с Cargo, системой сборки и менеджером пакетов, который упрощает управление зависимостями, сборку и распространение кода.
-
Экосистема: Экосистема Rust включает растущую коллекцию библиотек и инструментов, которые помогают разработчикам писать надежный и эффективный код. Официальный реестр пакетов, crates.io, содержит тысячи библиотек с открытым исходным кодом.
Сферы применения Rust:
-
Системное программирование: Rust идеально подходит для написания операционных систем, драйверов устройств и других низкоуровневых задач, где критичны контроль над оборудованием и производительность.
-
WebAssembly: Rust может компилироваться в WebAssembly, что позволяет запускать код Rust в веб-браузерах с производительностью, близкой к нативной.
-
Сетевое программирование: Особенности безопасности и производительность Rust делают его подходящим для написания сетевого ПО, включая веб-серверы и клиенты.
-
Разработка игр: Производственные характеристики Rust делают его хорошим выбором для разработки игр, где скорость и эффективность критичны.
-
Командные утилиты: Менеджер пакетов Cargo упрощает создание и распространение командных утилит.
Известные проекты, использующие Rust:
-
Firefox Quantum: Mozilla использовала Rust для переписывания частей их движка браузера, что привело к значительному улучшению производительности.
-
Dropbox: Dropbox использует Rust для некоторых своих серверных сервисов.
-
Cloudflare: Cloudflare использует Rust для нескольких своих производительно критичных сервисов.
-
Rustlings: Образовательный проект, который помогает изучать Rust через небольшие упражнения.
Комбинация безопасности, производительности и поддержки конкурентности делает Rust привлекательным выбором для многих видов разработки программного обеспечения. Его растущая популярность и активное сообщество гарантируют, что Rust продолжит развиваться и улучшаться.
Думал над идеей, что бы такого реализовать на языке Rust. Мне захотелось написать Telegram-бота, который бы двунаправленно переводил сообщения в чате группы с русского на тайский и наоборот.
Понимаю, что существуют готовые решения, но захотелось создать свой «велосипед» и опробовать новый для себя язык — Rust.
Идея есть, с созданием Telegram-бота проблем нет, но возникла проблема с сервисом, который будет переводить с одного языка на другой. Выбор пал на LibreTranslate. Чтобы использовать его бесплатно, необходимо развернуть приложение на своем сервере. Я так и сделал: установил зависимости и развернул в Docker-контейнере. Проблем не возникло, единственное, что приложение необходимо запускать с флагом: `./run.sh —api-keys`, чтобы можно было получить `api_key`. Подробнее о настройке и получении `api-key` для LibreTranslate можно прочитать на официальном сайте.
Развернув сервер LibreTranslate и получив токен для Telegram-бота, осталось реализовать приложение. Просмотрев официальную документацию по Rust и наработки на GitHub, я начал творить. Установил Rust и Cargo (регистр/менеджер пакетов для Rust). Изучив документацию библиотеки teloxide для создания Telegram-ботов на 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(()) }
Далее саму функцию для запроса перевода с API 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.
ссылка на оригинал статьи https://habr.com/ru/articles/830336/
Добавить комментарий