diff --git a/Cargo.lock b/Cargo.lock index 0eb2d76..ecf074f 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -303,8 +303,9 @@ checksum = "923dea538cea0aa3025e8685b20d6ee21ef99c4f77e954a30febbaac5ec73a97" [[package]] name = "downfav" -version = "0.3.2" +version = "0.4.0" dependencies = [ + "chrono", "elefren", "env_logger", "html2md", diff --git a/Cargo.toml b/Cargo.toml index 3870387..f1fc4c6 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "downfav" -version = "0.3.3" +version = "0.4.0" authors = ["Julio Biason "] edition = "2018" @@ -13,3 +13,4 @@ serde_derive = "*" toml = "0.5" log = "0.4" env_logger = "0.8" +chrono = "0.4" \ No newline at end of file diff --git a/src/config/mod.rs b/src/config/mod.rs index 2480674..fe6962e 100644 --- a/src/config/mod.rs +++ b/src/config/mod.rs @@ -32,6 +32,11 @@ pub struct JoplinConfig { pub token: String, } +#[derive(Serialize, Deserialize, Debug)] +pub struct OrgConfig { + pub location: String, +} + #[derive(Serialize, Deserialize, Debug)] pub struct Favourite { pub last: String, @@ -54,6 +59,7 @@ pub struct Config { pub favourite: Favourite, pub mastodon: Data, pub joplin: Option, + pub org: Option, } /// Errors while loading the configuration file @@ -66,8 +72,9 @@ pub enum ConfigError { } impl From for ConfigError { - fn from(_: toml::de::Error) -> Self { + fn from(e: toml::de::Error) -> Self { // Since we only have one single error so far... + log::debug!("Toml error: {:?}", e); ConfigError::InvalidConfig } } @@ -85,7 +92,6 @@ impl Config { let mut fp = File::open("downfav.toml")?; let mut contents = String::new(); fp.read_to_string(&mut contents).unwrap(); - Ok(toml::from_str(&contents)?) } @@ -108,7 +114,8 @@ impl From for Config { Config { favourite: Favourite::new(), mastodon: data, - joplin: None, // at least, not yet + joplin: None, + org: None, } } } diff --git a/src/main.rs b/src/main.rs index f718250..0e03797 100644 --- a/src/main.rs +++ b/src/main.rs @@ -24,6 +24,7 @@ use elefren::prelude::*; use crate::storage::data::Data; use crate::storage::filesystem::Filesystem; use crate::storage::joplin::Joplin; +use crate::storage::org::Org; use crate::storage::storage::Storage; mod config; @@ -34,7 +35,8 @@ fn main() { let config = match config::Config::get() { Ok(config) => config, - Err(_) => { + Err(e) => { + log::debug!("Configuration error: {:?}", e); let data = connect_to_mastodon(); config::Config::from(data) } @@ -42,9 +44,10 @@ fn main() { let top = config.favourite.last.to_string(); log::debug!("Last favourite seen: {}", top); - let storage: Box = match &config.joplin { - Some(joplin) => Box::new(Joplin::new_from_config(&joplin)), - None => Box::new(Filesystem::new()), + let storage: Box = match (&config.joplin, &config.org) { + (Some(joplin), _) => Box::new(Joplin::new_from_config(&joplin)), + (None, Some(org)) => Box::new(Org::new_from_config(&org)), + (None, None) => Box::new(Filesystem::new()), }; let client = Mastodon::from(config.mastodon.clone()); diff --git a/src/storage/mod.rs b/src/storage/mod.rs index 155570d..f7ee662 100644 --- a/src/storage/mod.rs +++ b/src/storage/mod.rs @@ -20,4 +20,5 @@ pub mod attachment; pub mod data; pub mod filesystem; pub mod joplin; +pub mod org; pub mod storage; diff --git a/src/storage/org.rs b/src/storage/org.rs new file mode 100644 index 0000000..8d0677b --- /dev/null +++ b/src/storage/org.rs @@ -0,0 +1,84 @@ +/* + DOWNFAV - Download Favourites + Copyright (C) 2020 Julio Biason + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Affero General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Affero General Public License for more details. + + You should have received a copy of the GNU Affero General Public License + along with this program. If not, see . +*/ + +use chrono::prelude::*; +use std::fs::OpenOptions; +use std::io::prelude::*; +use std::path::Path; +use std::path::PathBuf; + +use crate::config::OrgConfig; +use crate::storage::data::Data; +use crate::storage::storage::Storage; + +pub struct Org { + file: PathBuf, + date: String, +} + +impl Org { + pub(crate) fn new_from_config(config: &OrgConfig) -> Org { + let now = Utc::now(); + let filename = format!("{}{}{}.org", now.year(), now.month(), now.day()); + let date = format!("{}-{}-{}", now.year(), now.month(), now.day()); + let full_path = Path::new(&config.location).join(&filename); + log::debug!("Org file: {}", full_path.to_string_lossy()); + + Org { + file: full_path, + date, + } + } +} + +impl Storage for Org { + fn save(&self, record: &Data) { + let mut fp = OpenOptions::new() + .write(true) + .append(true) + .open(&self.file) + .map_err(|_| { + // Let's assume here that the problem is that the file doesn't exist. + log::debug!( + "Creating {filename}", + filename = &self.file.to_string_lossy() + ); + OpenOptions::new() + .write(true) + .create(true) + .open(&self.file) + .map(|mut fp| { + let text = + format!("#+title: Favourites from {date}\n\n", date = &self.date); + fp.write_all(text.as_bytes()).unwrap(); + fp + }) + }) + .unwrap(); + fp.write_all( + format!( + "* {user}/{id}\n {message}\n", + user = record.account, + id = record.id, + message = record.text, + ) + .as_bytes(), + ) + .unwrap(); + } +} diff --git a/src/storage/storage.rs b/src/storage/storage.rs index 9551eeb..67e4b4d 100644 --- a/src/storage/storage.rs +++ b/src/storage/storage.rs @@ -20,6 +20,12 @@ use crate::storage::data::Data; /// Trait for storing favorites on a storage. pub trait Storage { + /// Storage initialization + fn init(&self) {} + /// Save the favourite in the storage. fn save(&self, record: &Data); + + /// Storage finalization + fn close(&self) {} }