use crate::OkOrStringError;
use chrono_tz::{ParseError, Tz, UTC};
use serde::{Deserialize, Serialize};
use std::{env, fmt};
#[derive(Debug, Serialize, Deserialize, Default)]
pub struct MyConfig {
pub default_timezone: Option<String>,
pub custom_parsing_tokens: Option<Vec<String>>,
}
impl fmt::Display for MyConfig {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "Timezone: {:?}", self.default_timezone)
}
}
pub fn load_config() -> MyConfig {
confy::load("rti").expect("Unable to load config.")
}
pub fn set_tz_config(tz_input: Option<String>) -> OkOrStringError {
let timezone: Tz = match tz_input {
Some(val) => match val.parse() {
Ok(v) => v,
Err(_) => return Err("Invalid timezone provided.".to_string()),
},
None => return Err("Must provide timezone argument.".to_string()),
};
let existing_config = load_config();
let new_config = MyConfig {
default_timezone: Some(timezone.to_string()),
..existing_config
};
match confy::store("rti", new_config) {
Ok(_) => Ok(Some(format!("Timezone updated to {}", timezone))),
Err(e) => Err(format!("Error storing timezone: {}", e)),
}
}
pub fn clear_tz_config() -> OkOrStringError {
let existing_config = load_config();
let new_config = MyConfig {
default_timezone: None,
..existing_config
};
match confy::store("rti", new_config) {
Ok(_) => Ok(Some("Timezone cleared.".to_string())),
Err(e) => Err(format!("Error storing timezone: {}", e)),
}
}
fn get_env_timezone() -> Option<Tz> {
let env_timezone = env::var("TIMEZONE");
if let Ok(env_tz) = env_timezone {
let parsed_env_tz: Result<Tz, ParseError> = env_tz.parse();
match parsed_env_tz {
Ok(tz) => return Some(tz),
_ => panic!("Unable to parse TIMEZONE env variable."),
}
};
None
}
pub fn get_timezone() -> Tz {
let env_timezone = get_env_timezone();
if let Some(tz) = env_timezone {
return tz;
}
let existing_config = load_config();
if let Some(val) = existing_config.default_timezone {
let tz: Tz = val.parse().unwrap();
tz
} else {
UTC
}
}
pub fn get_custom_tokens() -> Vec<String> {
let existing_config = load_config();
match existing_config.custom_parsing_tokens {
Some(tokens) => tokens,
None => Vec::new(),
}
}
pub fn add_custom_token(new_token: Option<String>) -> OkOrStringError {
let token: String = match new_token {
Some(val) => val,
None => return Err("Must provide timezone argument.".to_string()),
};
let mut existing_tokens = match load_config().custom_parsing_tokens {
Some(tokens) => tokens,
None => Vec::new(),
};
existing_tokens.push(token);
let existing_config = load_config();
let new_config = MyConfig {
custom_parsing_tokens: Some(existing_tokens),
..existing_config
};
match confy::store("rti", new_config) {
Ok(_) => Ok(Some("Custom Token successfully added.".to_string())),
Err(e) => Err(format!("Error storing custom token: {}", e)),
}
}
pub fn remove_custom_token(to_remove: Option<String>) -> OkOrStringError {
let token: String = match to_remove {
Some(val) => val,
None => return Err("Must provide token to remove.".to_string()),
};
let existing_tokens: Vec<String> = match load_config().custom_parsing_tokens {
Some(tokens) => tokens,
None => {
return Ok(Some("No tokens to remove.".to_string()));
}
};
let filtered_tokens: Vec<String> = existing_tokens
.into_iter()
.filter(|val| val != &token)
.collect();
if filtered_tokens.is_empty() {
return Ok(Some("No matching token found.".to_string()));
}
let tokens_to_store = match filtered_tokens.len() {
0 => None,
_ => Some(filtered_tokens),
};
let new_config = MyConfig {
custom_parsing_tokens: tokens_to_store,
..load_config()
};
match confy::store("rti", new_config) {
Ok(_) => Ok(Some("Custom token removed.".to_string())),
Err(e) => Err(format!("Error removing custom token: {}", e)),
}
}
pub fn view_tokens() -> OkOrStringError {
let mut existing_tokens: Vec<String> = vec!["Custom datetime tokens:".to_string()];
match load_config().custom_parsing_tokens {
Some(mut tokens) => existing_tokens.append(&mut tokens),
None => return Err("No custom tokens exist!".to_string()),
};
Ok(Some(existing_tokens.join("\n")))
}