From 64742a0e21769faee85809a27993bd117b69566e Mon Sep 17 00:00:00 2001 From: Teascade Date: Sat, 29 Aug 2020 02:50:10 +0300 Subject: [PATCH] Separate cmd.rs, and make errorparsing generic --- src/cmd.rs | 100 ++++++++++++++++++++++++++++++++ src/main.rs | 116 ++------------------------------------ thingy_lib/src/api/mod.rs | 29 ++++++---- thingy_lib/src/lib.rs | 16 +++++- 4 files changed, 136 insertions(+), 125 deletions(-) create mode 100644 src/cmd.rs diff --git a/src/cmd.rs b/src/cmd.rs new file mode 100644 index 0000000..2d56ca0 --- /dev/null +++ b/src/cmd.rs @@ -0,0 +1,100 @@ +use super::args::*; +use super::errors::GenericError; +use super::gpx; +use thingy_lib::api::API; +use thingy_lib::chrono::NaiveDateTime; +use thingy_lib::{try_get_datetime, Config, MessagedError}; + +pub fn from_env(env: EnvOpt) -> Result<(), GenericError> { + match env.subcommand { + Subcommand::Between(opt) => { + let config = Config::from_path(&env.config)?; + let mut api = API::new(config.clone()); + + let since = + Some(try_get_datetime(opt.since, &config).with_msg("Failed to parse since")?); + + let until = match opt.until { + Some(until) => { + Some(try_get_datetime(until, &config).with_msg("Failed to parse until")?) + } + None => None, + }; + + let (tag, locs) = thingy_lib::between(&mut api, opt.device, since, until)?; + + let gpx = gpx::generate_gpx(&tag, &locs, &api.config)?; + gpx::write_gpx(&gpx)?; + + dbg!( + &locs.iter().map(|loc| loc.0).collect::>(), + locs.len(), + ); + Ok(()) + } + Subcommand::Init(opt) => { + thingy_lib::init(&env.config, opt.api_key)?; + Ok(()) + } + Subcommand::Api(_) => { + let config = Config::from_path(&env.config)?; + let api = API::new(config.clone()); + match thingy_lib::check_api(&api) { + Ok(_) => { + println!("API verified, no issues"); + Ok(()) + } + Err(e) => Err(GenericError::MessagedError( + "API integrity failed, or API-key is not valid. ".to_owned(), + Some(Box::new(e.into())), + )), + } + } + Subcommand::ShareToken(opt) => { + let config = Config::from_path(&env.config)?; + let api = API::new(config.clone()); + println!("{}", thingy_lib::sharetoken(&api, opt.device)?); + Ok(()) + } + Subcommand::Nick(opt) => { + let config = Config::from_path(&env.config)?; + let mut api = API::new(config.clone()); + + match opt.subcommand { + NickSub::List(_) => { + for ((idx, nick), tag) in thingy_lib::nick_list(&api)? { + println!("{}. {}\n{}", idx, nick, tag); + } + } + NickSub::Set(opt) => { + thingy_lib::nick_set(&mut api, opt.device, opt.nickname)?; + api.config.write_to(&env.config)?; + } + } + Ok(()) + } + + #[cfg(debug_assertions)] + Subcommand::Get(opt) => { + let config = Config::from_path(&env.config)?; + let api = API::new(config.clone()); + match opt.subcommand { + GetSub::Tag(opt) => { + let tags = api.get_tag(&opt.device); + dbg!(&tags); + } + GetSub::Tags(_) => { + let tags = api.get_tags()?; + dbg!(&tags); + } + GetSub::States(opt) => { + API::print_list(thingy_lib::get_states(&api, opt.device)); + } + GetSub::Locations(opt) => { + API::print_list(thingy_lib::get_locations(&api, opt.device, opt.state)) + } + } + Ok(()) + } + } +} diff --git a/src/main.rs b/src/main.rs index 0d0df55..2540dc5 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,127 +1,19 @@ #![windows_subsystem = "windows"] mod args; +mod cmd; mod errors; mod gpx; use args::*; use errors::GenericError; -use thingy_lib::api::{LocationModel, TagModel, API}; -use thingy_lib::chrono::offset::Local; -use thingy_lib::chrono::{NaiveDate, NaiveDateTime, NaiveTime, ParseError}; -use thingy_lib::{Config, MessagedError}; +use thingy_lib::api::{LocationModel, TagModel}; +use thingy_lib::Config; fn main() { let env: EnvOpt = argh::from_env(); - if let Err(e) = from_env(env) { + if let Err(e) = cmd::from_env(env) { eprintln!("Critical Error: {}", e); std::process::exit(1); } } - -fn from_env(env: EnvOpt) -> Result<(), GenericError> { - match env.subcommand { - Subcommand::Between(opt) => { - let config = Config::from_path(&env.config)?; - let mut api = API::new(config.clone()); - - let since = - Some(try_get_datetime(opt.since, &config).with_msg("Failed to parse since")?); - - let until = match opt.until { - Some(until) => { - Some(try_get_datetime(until, &config).with_msg("Failed to parse until")?) - } - None => None, - }; - - let (tag, locs) = thingy_lib::between(&mut api, opt.device, since, until)?; - - let gpx = gpx::generate_gpx(&tag, &locs, &api.config)?; - gpx::write_gpx(&gpx)?; - - dbg!( - &locs.iter().map(|loc| loc.0).collect::>(), - locs.len(), - ); - Ok(()) - } - Subcommand::Init(opt) => { - thingy_lib::init(&env.config, opt.api_key)?; - Ok(()) - } - Subcommand::Api(_) => { - let config = Config::from_path(&env.config)?; - let api = API::new(config.clone()); - match thingy_lib::check_api(&api) { - Ok(_) => { - println!("API verified, no issues"); - Ok(()) - } - Err(e) => Err(GenericError::MessagedError( - "API integrity failed, or API-key is not valid. ".to_owned(), - Some(Box::new(e.into())), - )), - } - } - Subcommand::ShareToken(opt) => { - let config = Config::from_path(&env.config)?; - let api = API::new(config.clone()); - println!("{}", thingy_lib::sharetoken(&api, opt.device)?); - Ok(()) - } - Subcommand::Nick(opt) => { - let config = Config::from_path(&env.config)?; - let mut api = API::new(config.clone()); - - match opt.subcommand { - NickSub::List(_) => { - for ((idx, nick), tag) in thingy_lib::nick_list(&api)? { - println!("{}. {}\n{}", idx, nick, tag); - } - } - NickSub::Set(opt) => { - thingy_lib::nick_set(&mut api, opt.device, opt.nickname)?; - api.config.write_to(&env.config)?; - } - } - Ok(()) - } - - #[cfg(debug_assertions)] - Subcommand::Get(opt) => { - let config = Config::from_path(&env.config)?; - let api = API::new(config.clone()); - match opt.subcommand { - GetSub::Tag(opt) => { - let tags = api.get_tag(&opt.device); - dbg!(&tags); - } - GetSub::Tags(_) => { - let tags = api.get_tags()?; - dbg!(&tags); - } - GetSub::States(opt) => { - API::print_list(thingy_lib::get_states(&api, opt.device)); - } - GetSub::Locations(opt) => { - API::print_list(thingy_lib::get_locations(&api, opt.device, opt.state)) - } - } - Ok(()) - } - } -} - -fn try_get_datetime(parsed: String, config: &Config) -> Result { - match NaiveDateTime::parse_from_str(&parsed, &config.timedate_format) { - Ok(timedate) => Ok(timedate), - Err(_) => match NaiveDate::parse_from_str(&parsed, &config.date_format) { - Ok(date) => Ok(date.and_hms(0, 0, 0)), - Err(_) => match NaiveTime::parse_from_str(&parsed, &config.time_format) { - Ok(time) => Ok(Local::today().naive_local().and_time(time)), - Err(e) => Err(e), - }, - }, - } -} diff --git a/thingy_lib/src/api/mod.rs b/thingy_lib/src/api/mod.rs index 4da0f6d..b595ced 100644 --- a/thingy_lib/src/api/mod.rs +++ b/thingy_lib/src/api/mod.rs @@ -5,6 +5,7 @@ use super::LibError; use chrono::format::ParseError; use chrono::NaiveDateTime; use minreq::Response; +use serde::Deserialize; use std::fmt::Display; use std::sync::mpsc; use std::sync::mpsc::Receiver; @@ -37,28 +38,22 @@ impl API { APIUrl::Sharetoken(tag_id.clone()), &self.config, ))?; - Ok(response.json()?) + Ok(API::or_err(&response)?) } pub fn get_tags(&self) -> Result, LibError> { let response = self.request(API::api_url(APIUrl::Tags, &self.config))?; - let tags = response.json(); - if let Err(_) = tags { - let err: ErrorModel = response.json()?; - Err(LibError::from(err)) - } else { - tags.map_err(LibError::from) - } + Ok(API::or_err(&response)?) } pub fn get_tag(&self, tag_id: &String) -> Result { let response = self.request(API::api_url(APIUrl::Tag(tag_id.clone()), &self.config))?; - Ok(response.json()?) + Ok(API::or_err(&response)?) } pub fn get_states(&self, tag_id: &String) -> Result, LibError> { let response = self.request(API::api_url(APIUrl::States(tag_id.clone()), &self.config))?; - Ok(response.json()?) + Ok(API::or_err(&response)?) } pub fn get_current_locations(&self, tag_id: &String) -> Result, LibError> { @@ -66,7 +61,7 @@ impl API { APIUrl::CurrLocations(tag_id.clone()), &self.config, ))?; - Ok(response.json()?) + Ok(API::or_err(&response)?) } pub fn get_locations( @@ -78,7 +73,7 @@ impl API { APIUrl::Locations(tag_id.clone(), state_id.clone()), &self.config, ))?; - Ok(response.json()?) + Ok(API::or_err(&response)?) } pub fn queue_location(&mut self, tag_id: &String, state_id: &String) { @@ -273,6 +268,16 @@ impl API { None } } + + fn or_err<'de, T: Deserialize<'de>>(response: &'de Response) -> Result { + let res = response.json(); + if let Err(_) = res { + let err: ErrorModel = response.json()?; + Err(LibError::from(err)) + } else { + res.map_err(LibError::from) + } + } } pub enum APIUrl { diff --git a/thingy_lib/src/lib.rs b/thingy_lib/src/lib.rs index b2af892..e3b31b8 100644 --- a/thingy_lib/src/lib.rs +++ b/thingy_lib/src/lib.rs @@ -3,7 +3,8 @@ mod config; mod errors; use api::{LocationModel, SharetokenModel, StateModel, TagModel, API}; -use chrono::NaiveDateTime; +use chrono::offset::Local; +use chrono::{NaiveDate, NaiveDateTime, NaiveTime, ParseError}; use errors::LibError; use std::io::prelude::*; use std::path::PathBuf; @@ -194,3 +195,16 @@ fn find_tag(tag_str: String, tags: &Vec, config: &Config) -> Result Result { + match NaiveDateTime::parse_from_str(&parsed, &config.timedate_format) { + Ok(timedate) => Ok(timedate), + Err(_) => match NaiveDate::parse_from_str(&parsed, &config.date_format) { + Ok(date) => Ok(date.and_hms(0, 0, 0)), + Err(_) => match NaiveTime::parse_from_str(&parsed, &config.time_format) { + Ok(time) => Ok(Local::today().naive_local().and_time(time)), + Err(e) => Err(e), + }, + }, + } +}