diff --git a/src/api/mod.rs b/src/api/mod.rs index 2b4bc95..e047098 100644 --- a/src/api/mod.rs +++ b/src/api/mod.rs @@ -33,6 +33,14 @@ impl API { .to_owned()) } + pub fn get_sharetoken(&self, tag_id: &String) -> Result { + let response = self.request(API::api_url( + APIUrl::Sharetoken(tag_id.clone()), + &self.config, + ))?; + Ok(response.json()?) + } + pub fn get_tags(&self) -> Result, GenericError> { let response = self.request(API::api_url(APIUrl::Tags, &self.config))?; let tags = response.json(); @@ -220,6 +228,7 @@ impl API { } APIUrl::States(tag) => str::replace(&config.states_url, "{tag}", &tag), APIUrl::Tags => config.tags_url.clone(), + APIUrl::Sharetoken(tag) => str::replace(&config.sharetoken_url, "{tag}", &tag), } } @@ -268,4 +277,5 @@ pub enum APIUrl { Locations(String, String), States(String), Tags, + Sharetoken(String), } diff --git a/src/api/structs.rs b/src/api/structs.rs index ea6983c..b7a5f7b 100644 --- a/src/api/structs.rs +++ b/src/api/structs.rs @@ -12,6 +12,39 @@ pub struct ErrorModel { pub message: Option, } +#[derive(Deserialize, Debug)] +#[serde(deny_unknown_fields)] +pub struct SharetokenModel { + token: Option, + url: Option, + expires: Option, +} + +impl Timestamped for SharetokenModel { + fn timestamp(&self) -> Option { + self.expires.clone() + } +} + +impl Display for SharetokenModel { + fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), std::fmt::Error> { + let mut text = String::new(); + text += &format!( + " token = {}", + self.token.as_ref().unwrap_or(&"unknown".to_owned()) + ); + text += &format!( + "\n url = {}", + self.url.as_ref().unwrap_or(&"unknown".to_owned()) + ); + text += &format!( + "\n expiry time = {}", + &self.expires.as_ref().unwrap_or(&"unknown".to_owned()) + ); + write!(f, "{}", text) + } +} + #[derive(Deserialize, Debug, Clone)] #[serde(deny_unknown_fields)] #[serde(rename_all = "camelCase")] diff --git a/src/args.rs b/src/args.rs index edc5673..ff8c4a1 100644 --- a/src/args.rs +++ b/src/args.rs @@ -21,6 +21,7 @@ pub enum Subcommand { Between(BetweenOpt), Init(InitOpt), Api(ApiOpt), + ShareToken(ShareTokenOpt), Nick(NickOpt), #[cfg(debug_assertions)] Get(GetOpt), @@ -68,6 +69,17 @@ pub struct InitOpt { )] pub struct ApiOpt {} +#[derive(FromArgs)] +#[argh( + subcommand, + name = "sharetoken", + description = "retrieve share token for given device." +)] +pub struct ShareTokenOpt { + #[argh(positional, description = "the device index or nickname")] + pub device: String, +} + #[derive(FromArgs)] #[argh( subcommand, diff --git a/src/commands.rs b/src/commands.rs index 9fa1a9a..f292383 100644 --- a/src/commands.rs +++ b/src/commands.rs @@ -1,4 +1,4 @@ -use super::api::{LocationModel, StateModel, TagModel, API}; +use super::api::{LocationModel, SharetokenModel, StateModel, TagModel, API}; use super::config::Config; use super::errors::GenericError; use super::gpx; @@ -84,6 +84,7 @@ pub fn check_api(api: &API) -> Result<(), GenericError> { let tag_id = tag.get_id()?; api.get_current_locations(&tag_id)?; + api.get_sharetoken(&tag_id)?; if let Some(state) = api.get_states(&tag_id)?.get(0) { let state_id = state.get_id()?; @@ -100,6 +101,12 @@ pub fn check_api(api: &API) -> Result<(), GenericError> { } } +pub fn sharetoken(api: &API, tag: String) -> Result { + let tags = api.get_tags()?; + let tag = find_tag(tag, &tags, &api.config)?; + Ok(api.get_sharetoken(&tag.get_id()?)?) +} + pub fn nick_list(api: &API) -> Result, GenericError> { let mut tags = api.get_tags()?; tags.sort_by(|tag1, tag2| tag1.id.cmp(&tag2.id)); diff --git a/src/config.rs b/src/config.rs index 0d3989c..503989e 100644 --- a/src/config.rs +++ b/src/config.rs @@ -13,6 +13,7 @@ pub struct Config { pub states_url: String, pub locations_url: String, pub current_locations_url: String, + pub sharetoken_url: String, pub timestamp_format: String, pub timedate_format: String, @@ -52,6 +53,7 @@ impl Default for Config { states_url: "https://platform.yepzon.com/tags/{tag}/states".to_owned(), locations_url: "https://platform.yepzon.com/tags/{tag}/locations/{state}".to_owned(), current_locations_url: "https://platform.yepzon.com/tags/{tag}/locations".to_owned(), + sharetoken_url: "https://platform.yepzon.com/tags/{tag}/sharetoken".to_owned(), timestamp_format: "%Y-%m-%dT%H:%M:%S%.fZ".to_owned(), diff --git a/src/main.rs b/src/main.rs index fcc093d..be628b7 100644 --- a/src/main.rs +++ b/src/main.rs @@ -61,6 +61,12 @@ fn from_env(env: EnvOpt) -> Result<(), GenericError> { )), } } + Subcommand::ShareToken(opt) => { + let config = Config::from_path(&env.config)?; + let api = API::new(config.clone()); + println!("{}", commands::sharetoken(&api, opt.device)?); + Ok(()) + } Subcommand::Nick(opt) => { let config = Config::from_path(&env.config)?; let mut api = API::new(config.clone());