Как я «try|tried» написать на Rust
Вот так Chat GPT представила человека, если бы это был язык Rust
Я 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.
Идея есть, с телеграмм ботом проблемы нет, но есть проблема с сервисом который будет переводить с одного языка на другой. Выбор пал на 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