From 7dcf5bb2012ce7d5c818d0acffc962cf53117ec4 Mon Sep 17 00:00:00 2001 From: mace Date: Mon, 19 Jan 2026 19:38:19 +0100 Subject: [PATCH] improve error messages, edition upgrade --- Cargo.lock | 11 +++++++++-- Cargo.toml | 5 +++-- README.md | 27 ++++++++++++++------------- cli.yml | 2 +- src/engine/params.rs | 44 ++++++++++++++++++++------------------------ src/main.rs | 17 ++++++----------- 6 files changed, 53 insertions(+), 53 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index a7f8265..ed1d4bf 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1,6 +1,6 @@ # This file is automatically @generated by Cargo. # It is not intended for manual editing. -version = 3 +version = 4 [[package]] name = "ansi_term" @@ -11,6 +11,12 @@ dependencies = [ "winapi", ] +[[package]] +name = "anyhow" +version = "1.0.100" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a23eb6b1614318a8071c9b2521f36b424b2c83db5eb3a0fead4a6c0809af6e61" + [[package]] name = "atty" version = "0.2.14" @@ -86,8 +92,9 @@ checksum = "ea221b5284a47e40033bf9b66f35f984ec0ea2931eb03505246cd27a963f981b" [[package]] name = "deepl" -version = "1.0.1" +version = "1.0.2" dependencies = [ + "anyhow", "clap", "directories", "dotenv", diff --git a/Cargo.toml b/Cargo.toml index 9a7f6b6..57226d3 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "deepl" -version = "1.0.1" -edition = "2018" +version = "1.0.2" +edition = "2024" license = "MIT OR Apache-2.0" authors = ["Mathias Rothenhäusler +Cli API for deepl translations. Create a .env config file in your user config folder (e.g. ~/config/deepl/.env). +Required keys URI (eg. https://api-free.deepl.com/v2/translate) and KEY (eg. XYZ:rg). -Cli API for deepl translations. API-Key is required.
+USAGE: + deepl [OPTIONS] -USAGE:
- deepl [OPTIONS] \
+FLAGS: + -h, --help Prints help information + -V, --version Prints version information -FLAGS:
- -h, --help Prints help information
- -V, --version Prints version information
+OPTIONS: + -s, --source The language you want to translate. Default is autodetect. + -t, --target The language your text should be tranlated to. Default is DE. -OPTIONS:
- -s, --source The language you want to translate. Default is autodectect.
- -t, --target The language your text should be tranlated to. Default is DE.
- -ARGS:
- \ Text to translate
+ARGS: + Text to translate diff --git a/cli.yml b/cli.yml index 32d994d..2a592d6 100644 --- a/cli.yml +++ b/cli.yml @@ -1,7 +1,7 @@ name: deepl version: "1.0" author: Mathias Rothenhaeusler -about: Cli API for deepl translations. +about: Cli API for deepl translations. Create a .env config file in your user config folder (e.g. ~/config/deepl/.env). Required keys URI (eg. https://api-free.deepl.com/v2/translate) and KEY (eg. XYZ:rg). args: - source: short: s diff --git a/src/engine/params.rs b/src/engine/params.rs index 62a8622..8838409 100644 --- a/src/engine/params.rs +++ b/src/engine/params.rs @@ -1,3 +1,4 @@ +use anyhow::{anyhow, Context, Result}; use clap::{load_yaml, App, ArgMatches}; use directories::BaseDirs; use dotenv; @@ -13,23 +14,13 @@ pub struct Params { } impl Params { - pub fn new() -> Result { - let base_dir: BaseDirs = BaseDirs::new().unwrap(); + pub fn new() -> Result { + let base_dir: BaseDirs = BaseDirs::new().context("failed to determine base directories")?; let my_path: PathBuf = base_dir.config_dir().join("deepl/.env"); - match dotenv::from_path(my_path.as_path()) { - Ok(env) => env, - Err(_) => { - return Err(format!( - "Could not load .env file {:?}", - base_dir - .config_dir() - .join("deepl/.env") - .as_path() - .as_os_str() - )); - } - }; + + dotenv::from_path(my_path.as_path()) + .context(format!("Missing .env file {}", my_path.display()))?; let yaml = load_yaml!("./../../cli.yml"); let matches: ArgMatches = App::from_yaml(yaml).get_matches(); @@ -37,29 +28,34 @@ impl Params { Ok(Self { source_lang: matches.value_of("source").unwrap_or("0").to_string(), target_lang: matches.value_of("target").unwrap_or("DE").to_string(), - key: env::var("KEY").unwrap(), - uri: env::var("URI").unwrap(), - text: matches.value_of("INPUT").unwrap().to_string(), + key: env::var("KEY").context("KEY missing")?, + uri: env::var("URI").context("URI missing")?, + text: matches.value_of("INPUT").context("input missing")?.to_string(), }) } - pub fn url(&self) -> String { - sprintf!("%s?auth_key=%s", self.uri, self.key).unwrap() + + pub fn url(&self) -> Result { + let url = sprintf!("%s?auth_key=%s", self.uri, self.key) + .map_err(|e| anyhow!("could not create request body: {e:?}"))?; + + Ok(url) } - pub fn body(&self) -> String { + pub fn body(&self) -> Result { let mut body = sprintf!( "auth_key=%s&text=%s&target_lang=%s", self.key, self.text, self.target_lang ) - .unwrap(); + .map_err(|e| anyhow!("could not create request body: {e:?}"))?; if self.source_lang != "0" { - let add = sprintf!("&source_lang=%s", self.source_lang).unwrap(); + let add = sprintf!("&source_lang=%s", self.source_lang) + .map_err(|e| anyhow!("could not append source_lang: {e:?}"))?; body.push_str(&add); } - body + Ok(body) } } diff --git a/src/main.rs b/src/main.rs index 9bdd2ad..29a897b 100644 --- a/src/main.rs +++ b/src/main.rs @@ -4,29 +4,24 @@ use crate::engine::params::Params; use crate::engine::response::DeeplResponse; use hyper::{body, Body, Client, Method, Request}; use hyper_tls::HttpsConnector; +use anyhow::Result; #[tokio::main(flavor = "current_thread")] -async fn main() -> Result<(), Box> { +async fn main() -> Result<()> { let https = HttpsConnector::new(); let client = Client::builder().build::<_, hyper::Body>(https); - let params: Params = match Params::new() { - Ok(result) => result, - Err(e) => { - eprintln!("{}", e); - return Ok(()); - }, - }; + let params: Params = Params::new()?; let request = Request::builder() .method(Method::POST) - .uri(params.url()) + .uri(params.url()?) .header("content-type", "application/x-www-form-urlencoded") - .body(Body::from(params.body()))?; + .body(Body::from(params.body()?))?; let res = client.request(request).await?; let body_bytes = body::to_bytes(res.into_body()).await?; - let body = String::from_utf8(body_bytes.to_vec()).expect("response was not valid utf-8"); + let body = String::from_utf8(body_bytes.to_vec())?; let v: DeeplResponse = serde_json::from_str(&body)?; println!("{}", v.get_text(¶ms.target_lang)); Ok(())