use std::path::Path;
use std::path::PathBuf;
use std::fs;
use std::fs::File;
use std::io::Read;
use serde_json;
use super::export;
use super::feed::Feed;
use super::import;
use super::settings::Settings;
#[derive(Debug, Deserialize, Serialize)]
pub struct Store {
pub settings: Settings,
pub feeds: Vec<Feed>,
#[serde(skip)]
pub dirty:bool
}
const STORE: &str = "config.json";
impl Store {
pub fn load() -> Store {
let path = Path::new(STORE);
if path.exists() {
let mut file =
File::open(STORE).unwrap_or_else(|_| panic!("Unable to open file {}", STORE));
let mut contents = String::new();
file.read_to_string(&mut contents)
.unwrap_or_else(|_| panic!("Unable to read file {}", STORE));
let store: Store =
serde_json::from_str(&contents).expect("Can't deserialize Store from JSON");
store
} else {
Store {
settings: Settings::default(),
feeds: vec![],
dirty: false
}
}
}
fn save(&self) {
let serialized = serde_json::to_string_pretty(self).expect("Can't serialize Store to JSON");
fs::write(STORE, serialized).unwrap_or_else(|_| panic!("Unable to write file {}", STORE));
}
pub fn set_email(&mut self, email: String) {
self.settings.config.email = Some(email);
self.dirty = true;
self.save();
}
pub fn export(&self, file: Option<PathBuf>) {
let path_to_write = file.expect("Can't expport file if no file is given");
warn!("exporting content to {:?}", path_to_write);
export::export(&path_to_write, self);
warn!("exported feeds to {:?}", path_to_write);
}
pub fn import(&mut self, file: Option<PathBuf>) {
let path_to_read = file.expect("Can't import file if no file is given");
warn!("importing content from {:?}", path_to_read);
let count = self.feeds.len();
import::import(&path_to_read, self);
self.dirty = true;
warn!(
"imported {} feeds from {:?}",
self.feeds.len() - count,
path_to_read
);
}
pub fn add(&mut self, parameters: Vec<String>) {
info!("adding \"{:?}\"", parameters);
let to_add = Feed::from(parameters);
self.add_feed(to_add);
self.dirty = true;
}
pub fn delete(&mut self, feed: u32) {
let f = self.feeds.remove(feed as usize);
self.dirty = true;
info!("Removed {:?}", f);
}
pub fn reset(&mut self) {
self.feeds.clear();
self.settings.config.clear();
self.dirty = true;
info!("store have been cleared to contain only {:?}", self);
}
pub fn run(&mut self) {
self.feeds = self
.feeds
.iter()
.map(|f| f.read(&self.settings))
.collect::<Vec<Feed>>();
self.dirty = true;
}
pub fn list(&self) {
let lines: Vec<String> = self
.feeds
.iter()
.enumerate()
.map(|(i, f)| format!("{} : {}", i, f.to_string(&self.settings.config)))
.collect();
println!("{}", &lines.join("\n"));
}
pub fn add_feed(&mut self, to_add: Feed) {
let tested = self.feeds.clone();
let already_existing: Vec<&Feed> = tested.iter().filter(|f| f.url == to_add.url).collect();
if already_existing.is_empty() {
self.feeds.push(to_add);
} else {
error!(
"We already read this feed with the following configuration {:?}",
already_existing
);
}
}
}
impl Drop for Store {
fn drop(&mut self) {
if self.dirty {
info!("store has been modified. Saving !");
self.save();
}
}
}