From b4a03f5e5417958660381acd959de420cdfe6b5b Mon Sep 17 00:00:00 2001 From: Alex Janka Date: Tue, 26 Dec 2023 08:58:14 +1100 Subject: [PATCH] better errors + generate default config --- src/config.rs | 15 ++++++++++++--- src/errors.rs | 38 ++++++++++++++++++++++++++++++++++++++ src/main.rs | 42 +++++++++++++++++++----------------------- 3 files changed, 69 insertions(+), 26 deletions(-) create mode 100644 src/errors.rs diff --git a/src/config.rs b/src/config.rs index afac3b5..575951b 100644 --- a/src/config.rs +++ b/src/config.rs @@ -1,7 +1,16 @@ +use std::time::Duration; + use serde::{Deserialize, Serialize}; #[derive(Serialize, Deserialize, Clone, Debug)] -pub struct Config {} +pub struct Config { + watch_interval: Duration, +} -#[derive(Serialize, Deserialize, Clone, Debug)] -pub struct Auth {} +impl Default for Config { + fn default() -> Self { + Self { + watch_interval: Duration::from_secs(60), + } + } +} diff --git a/src/errors.rs b/src/errors.rs new file mode 100644 index 0000000..0eb5d4e --- /dev/null +++ b/src/errors.rs @@ -0,0 +1,38 @@ +use thiserror::Error; + +#[derive(Error, Debug)] +pub enum AuthLoadError { + #[error("stdio error")] + StdIo(#[from] std::io::Error), + #[error("ron - spanned error")] + RonSpanned(#[from] ron::error::SpannedError), +} + +impl AuthLoadError { + pub fn error_string(&self) -> String { + match self { + AuthLoadError::StdIo(e) => format!("Error reading access token from disk: {e:?}"), + AuthLoadError::RonSpanned(e) => format!("Error deserialising access token: {e:?}"), + } + } +} + +#[derive(Error, Debug)] +pub enum LoginError { + #[error("teslatte error")] + Teslatte(#[from] teslatte::error::TeslatteError), + #[error("ron error")] + Ron(#[from] ron::Error), + #[error("stdio error")] + StdIo(#[from] std::io::Error), +} + +impl LoginError { + pub fn error_string(&self) -> String { + match self { + LoginError::Teslatte(e) => format!("Authentication flow error: {e:?}"), + LoginError::Ron(e) => format!("Error serialising access token: {e:?}"), + LoginError::StdIo(e) => format!("Error saving access token to disk: {e:?}"), + } + } +} diff --git a/src/main.rs b/src/main.rs index eadea0a..d46ea04 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,10 +1,11 @@ -use std::{io::BufRead, path::PathBuf}; - use clap::{Parser, Subcommand}; +use std::{io::BufRead, path::PathBuf}; use teslatte::{auth::AccessToken, OwnerApi}; -use thiserror::Error; + +use crate::{config::Config, errors::*}; mod config; +mod errors; #[derive(Parser, Debug, Clone)] #[clap(author, version, about, long_about = None)] @@ -20,7 +21,9 @@ enum Commands { /// Run charge controller server Watch, /// Authenticate with Tesla login - Auth {}, + Auth, + /// Print the default config file + GenerateConfig, } fn press_y_to_continue() -> bool { @@ -41,8 +44,15 @@ async fn main() { let args = Args::parse(); let auth_path = args.config_dir.join("auth"); let config_path = args.config_dir.join("config"); + match args.command { - Commands::Auth {} => { + Commands::GenerateConfig => { + println!( + "{}", + ron::ser::to_string_pretty(&Config::default(), Default::default()).unwrap() + ); + } + Commands::Auth => { if auth_path.exists() { println!("Auth file already exists"); if !press_y_to_continue() { @@ -50,38 +60,24 @@ async fn main() { } } if let Err(e) = log_in(auth_path).await { - println!("Error: {e:#?}") + println!("{}", e.error_string()); } } Commands::Watch => match get_auth(auth_path) { Ok(api) => { println!("got products: {:#?}", api.products().await) } - Err(e) => println!("error getting auth: {e:#?}"), + Err(e) => println!("{}", e.error_string()), }, } } -#[derive(Error, Debug)] -pub enum TeslaError { - #[error("teslatte error")] - Teslatte(#[from] teslatte::error::TeslatteError), - #[error("ron error")] - Ron(#[from] ron::Error), - #[error("stdio error")] - StdIo(#[from] std::io::Error), - #[error("ron - spanned error")] - RonSpanned(#[from] ron::error::SpannedError), - #[error("unknown error")] - Unknown, -} - -fn get_auth(auth_path: PathBuf) -> Result { +fn get_auth(auth_path: PathBuf) -> Result { let key: AccessToken = ron::from_str(&std::fs::read_to_string(auth_path)?)?; Ok(OwnerApi::new(key, None)) } -async fn log_in(auth_path: PathBuf) -> Result<(), TeslaError> { +async fn log_in(auth_path: PathBuf) -> Result<(), LoginError> { let v = OwnerApi::from_interactive_url().await?; std::fs::write(auth_path, ron::ser::to_string(&v.access_token)?)?;