Separate cmd.rs, and make errorparsing generic
This commit is contained in:
parent
b1b8ac417b
commit
64742a0e21
100
src/cmd.rs
Normal file
100
src/cmd.rs
Normal file
@ -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::<Vec<NaiveDateTime>>(),
|
||||||
|
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(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
116
src/main.rs
116
src/main.rs
@ -1,127 +1,19 @@
|
|||||||
#![windows_subsystem = "windows"]
|
#![windows_subsystem = "windows"]
|
||||||
|
|
||||||
mod args;
|
mod args;
|
||||||
|
mod cmd;
|
||||||
mod errors;
|
mod errors;
|
||||||
mod gpx;
|
mod gpx;
|
||||||
|
|
||||||
use args::*;
|
use args::*;
|
||||||
use errors::GenericError;
|
use errors::GenericError;
|
||||||
use thingy_lib::api::{LocationModel, TagModel, API};
|
use thingy_lib::api::{LocationModel, TagModel};
|
||||||
use thingy_lib::chrono::offset::Local;
|
use thingy_lib::Config;
|
||||||
use thingy_lib::chrono::{NaiveDate, NaiveDateTime, NaiveTime, ParseError};
|
|
||||||
use thingy_lib::{Config, MessagedError};
|
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
let env: EnvOpt = argh::from_env();
|
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);
|
eprintln!("Critical Error: {}", e);
|
||||||
std::process::exit(1);
|
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::<Vec<NaiveDateTime>>(),
|
|
||||||
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<NaiveDateTime, ParseError> {
|
|
||||||
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),
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
@ -5,6 +5,7 @@ use super::LibError;
|
|||||||
use chrono::format::ParseError;
|
use chrono::format::ParseError;
|
||||||
use chrono::NaiveDateTime;
|
use chrono::NaiveDateTime;
|
||||||
use minreq::Response;
|
use minreq::Response;
|
||||||
|
use serde::Deserialize;
|
||||||
use std::fmt::Display;
|
use std::fmt::Display;
|
||||||
use std::sync::mpsc;
|
use std::sync::mpsc;
|
||||||
use std::sync::mpsc::Receiver;
|
use std::sync::mpsc::Receiver;
|
||||||
@ -37,28 +38,22 @@ impl API {
|
|||||||
APIUrl::Sharetoken(tag_id.clone()),
|
APIUrl::Sharetoken(tag_id.clone()),
|
||||||
&self.config,
|
&self.config,
|
||||||
))?;
|
))?;
|
||||||
Ok(response.json()?)
|
Ok(API::or_err(&response)?)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_tags(&self) -> Result<Vec<TagModel>, LibError> {
|
pub fn get_tags(&self) -> Result<Vec<TagModel>, LibError> {
|
||||||
let response = self.request(API::api_url(APIUrl::Tags, &self.config))?;
|
let response = self.request(API::api_url(APIUrl::Tags, &self.config))?;
|
||||||
let tags = response.json();
|
Ok(API::or_err(&response)?)
|
||||||
if let Err(_) = tags {
|
|
||||||
let err: ErrorModel = response.json()?;
|
|
||||||
Err(LibError::from(err))
|
|
||||||
} else {
|
|
||||||
tags.map_err(LibError::from)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_tag(&self, tag_id: &String) -> Result<TagModel, LibError> {
|
pub fn get_tag(&self, tag_id: &String) -> Result<TagModel, LibError> {
|
||||||
let response = self.request(API::api_url(APIUrl::Tag(tag_id.clone()), &self.config))?;
|
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<Vec<StateModel>, LibError> {
|
pub fn get_states(&self, tag_id: &String) -> Result<Vec<StateModel>, LibError> {
|
||||||
let response = self.request(API::api_url(APIUrl::States(tag_id.clone()), &self.config))?;
|
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<Vec<LocationModel>, LibError> {
|
pub fn get_current_locations(&self, tag_id: &String) -> Result<Vec<LocationModel>, LibError> {
|
||||||
@ -66,7 +61,7 @@ impl API {
|
|||||||
APIUrl::CurrLocations(tag_id.clone()),
|
APIUrl::CurrLocations(tag_id.clone()),
|
||||||
&self.config,
|
&self.config,
|
||||||
))?;
|
))?;
|
||||||
Ok(response.json()?)
|
Ok(API::or_err(&response)?)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_locations(
|
pub fn get_locations(
|
||||||
@ -78,7 +73,7 @@ impl API {
|
|||||||
APIUrl::Locations(tag_id.clone(), state_id.clone()),
|
APIUrl::Locations(tag_id.clone(), state_id.clone()),
|
||||||
&self.config,
|
&self.config,
|
||||||
))?;
|
))?;
|
||||||
Ok(response.json()?)
|
Ok(API::or_err(&response)?)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn queue_location(&mut self, tag_id: &String, state_id: &String) {
|
pub fn queue_location(&mut self, tag_id: &String, state_id: &String) {
|
||||||
@ -273,6 +268,16 @@ impl API {
|
|||||||
None
|
None
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn or_err<'de, T: Deserialize<'de>>(response: &'de Response) -> Result<T, LibError> {
|
||||||
|
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 {
|
pub enum APIUrl {
|
||||||
|
@ -3,7 +3,8 @@ mod config;
|
|||||||
mod errors;
|
mod errors;
|
||||||
|
|
||||||
use api::{LocationModel, SharetokenModel, StateModel, TagModel, API};
|
use api::{LocationModel, SharetokenModel, StateModel, TagModel, API};
|
||||||
use chrono::NaiveDateTime;
|
use chrono::offset::Local;
|
||||||
|
use chrono::{NaiveDate, NaiveDateTime, NaiveTime, ParseError};
|
||||||
use errors::LibError;
|
use errors::LibError;
|
||||||
use std::io::prelude::*;
|
use std::io::prelude::*;
|
||||||
use std::path::PathBuf;
|
use std::path::PathBuf;
|
||||||
@ -194,3 +195,16 @@ fn find_tag(tag_str: String, tags: &Vec<TagModel>, config: &Config) -> Result<Ta
|
|||||||
)),
|
)),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn try_get_datetime(parsed: String, config: &Config) -> Result<NaiveDateTime, ParseError> {
|
||||||
|
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),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user