diff --git a/src/config/mod.rs b/src/config/mod.rs index 92b79e9..2480674 100644 --- a/src/config/mod.rs +++ b/src/config/mod.rs @@ -19,6 +19,7 @@ use std::fs::File; use std::io::prelude::*; +use elefren::Data; use serde_derive::Deserialize; use serde_derive::Serialize; @@ -31,49 +32,83 @@ pub struct JoplinConfig { pub token: String, } +#[derive(Serialize, Deserialize, Debug)] +pub struct Favourite { + pub last: String, +} + +impl Favourite { + pub fn new() -> Self { + Self { last: "".into() } + } + + pub fn new_with_value(new_last: &str) -> Self { + Self { + last: new_last.into(), + } + } +} + #[derive(Serialize, Deserialize, Debug)] pub struct Config { - pub last_favorite: String, + pub favourite: Favourite, + pub mastodon: Data, pub joplin: Option, } +/// Errors while loading the configuration file +#[derive(Debug)] +pub enum ConfigError { + /// There is no configuration file + NoConfig, + /// The configuration file format is invalid + InvalidConfig, +} + +impl From for ConfigError { + fn from(_: toml::de::Error) -> Self { + // Since we only have one single error so far... + ConfigError::InvalidConfig + } +} + +impl From for ConfigError { + fn from(_: std::io::Error) -> Self { + // This is not optimal: Some IO errors we can't recover (like + // PermissionDenied) + ConfigError::NoConfig + } +} + impl Config { - pub fn get() -> Config { - if let Ok(mut fp) = File::open("downfav.toml") { - let mut contents = String::new(); - fp.read_to_string(&mut contents).unwrap(); - - let config: Config = toml::from_str(&contents).unwrap_or(Config { - last_favorite: "".to_string(), - joplin: None, - }); - config - } else { - Config { - last_favorite: "".to_string(), - joplin: None, - } + pub fn get() -> Result { + let mut fp = File::open("downfav.toml")?; + let mut contents = String::new(); + fp.read_to_string(&mut contents).unwrap(); + + Ok(toml::from_str(&contents)?) + } + + pub fn save(self, most_recent_favourite: &str) -> Self { + let new_configuration = Self { + favourite: Favourite::new_with_value(most_recent_favourite), + ..self + }; + let content = toml::to_string(&new_configuration).unwrap(); + + if let Ok(mut fp) = File::create("downfav.toml") { + fp.write_all(content.as_bytes()).unwrap(); } + new_configuration } +} - pub fn save(&self, most_recent_favourite: Option) -> () { - if let Some(id) = most_recent_favourite { - let new_configuration = Config { - last_favorite: id, - joplin: match &self.joplin { - None => None, - Some(x) => Some(JoplinConfig { - folder: x.folder.to_string(), - token: x.token.to_string(), - port: x.port, - }), - }, - }; - let content = toml::to_string(&new_configuration).unwrap(); - - if let Ok(mut fp) = File::create("downfav.toml") { - fp.write_all(content.as_bytes()).unwrap(); - } +impl From for Config { + fn from(data: elefren::data::Data) -> Self { + Config { + favourite: Favourite::new(), + mastodon: data, + joplin: None, // at least, not yet } } } diff --git a/src/main.rs b/src/main.rs index 05a5367..560d826 100644 --- a/src/main.rs +++ b/src/main.rs @@ -19,7 +19,6 @@ use std::io; use elefren::helpers::cli; -use elefren::helpers::toml as elefren_toml; use elefren::prelude::*; use crate::storage::data::Data; @@ -31,14 +30,21 @@ mod config; mod storage; fn main() { - let config = dbg!(config::Config::get()); - let client = dbg!(get_mastodon_connection()); - let top = dbg!(config.last_favorite.to_string()); + let config = match config::Config::get() { + Ok(config) => config, + Err(_) => { + let data = connect_to_mastodon(); + config::Config::from(data) + } + }; + + let top = dbg!(config.favourite.last.to_string()); let storage: Box = match &config.joplin { Some(joplin) => Box::new(Joplin::new_from_config(&joplin)), None => Box::new(Filesystem::new()), }; + let client = Mastodon::from(config.mastodon.clone()); let most_recent_favourite = client .favourites() .unwrap() @@ -59,28 +65,22 @@ fn main() { } }); - config.save(most_recent_favourite); + if let Some(new_favourite) = most_recent_favourite { + config.save(&new_favourite); + } } -/// Get a connection with Mastodon; if there is no set up with any account yet, -/// requests one. -fn get_mastodon_connection() -> Mastodon { - match elefren_toml::from_file("mastodon.toml") { - Ok(data) => Mastodon::from(data), - Err(_) => { - println!("Your server URL: "); - let mut server = String::new(); - io::stdin() - .read_line(&mut server) - .expect("You need to enter yoru server URL"); +/// Create a connection to a mastodon server. +fn connect_to_mastodon() -> elefren::data::Data { + println!("Your server URL: "); + let mut server = String::new(); + io::stdin() + .read_line(&mut server) + .expect("You need to enter yoru server URL"); - let registration = Registration::new(server.trim()) - .client_name("downfav") - .build() - .unwrap(); - let mastodon = cli::authenticate(registration).unwrap(); - elefren_toml::to_file(&*mastodon, "mastodon.toml").unwrap(); - mastodon - } - } + let registration = Registration::new(server.trim()) + .client_name("downfav") + .build() + .unwrap(); + cli::authenticate(registration).unwrap().data }