use chrono::{NaiveDateTime};
use super::config::*;
use super::feed_reader::*;
use super::settings::*;
use super::syndication;
use reqwest::blocking::Client;
#[derive(Clone, Debug, Deserialize, Serialize)]
pub struct Feed {
pub url: String,
#[serde(skip_serializing_if = "Config::is_none", default = "Config::new")]
pub config: Config,
#[serde(default = "Feed::at_epoch")]
pub last_updated: NaiveDateTime,
#[serde(skip_serializing_if = "Option::is_none")]
pub last_message: Option<String>
}
impl Feed {
pub fn at_epoch() -> NaiveDateTime {
NaiveDateTime::from_timestamp(0, 0)
}
pub fn from_vec(parameters: Vec<String>) -> Feed {
let mut consumed = parameters;
let url: String = consumed
.pop()
.expect("You must at least define an url to add.");
let mut email: Option<String> = None;
let mut folder: Option<String> = None;
if !consumed.is_empty() {
let second = consumed.pop().unwrap();
if second.contains('@') {
debug!(
"Second add parameter {} is considered an email address",
second
);
email = Some(second)
} else {
warn!("Second add parameter {} is NOT considered an email address, but a folder. NO MORE ARGUMENTS WILL BE PROCESSED", second);
folder = Some(second)
}
}
if !consumed.is_empty() && folder == None {
folder = Some(consumed.pop().unwrap());
}
Feed {
url,
config: Config {
email,
folder,
from: None,
inline_image_as_data: false,
},
last_updated: Feed::at_epoch(),
last_message: None
}
}
pub fn from_all(url:Option<String>, email:Option<String>, destination:Option<String>, inline:bool) -> Feed {
Feed {
url: url.unwrap(),
config: Config {
email,
folder: destination,
from: None,
inline_image_as_data: inline,
},
last_updated: Feed::at_epoch(),
last_message: None
}
}
pub fn to_string(&self, config: &Config) -> String {
return format!("{} {}", self.url, self.config.clone().to_string(config));
}
pub async fn read(&self, index:usize, count:&usize, client:&Client, settings: &Settings) -> Feed {
info!("Reading feed {}/{} from {}", index+1, count, self.url);
match client.get(&self.url).send() {
Ok(response) => match response.text() {
Ok(text) => match text.parse::<syndication::Feed>() {
Ok(parsed) => {
return match parsed {
syndication::Feed::Atom(atom_feed) => {
AtomReader {}.read(self, &atom_feed, settings)
}
syndication::Feed::RSS(rss_feed) => {
RssReader {}.read(self, &rss_feed, settings)
}
}
}
Err(e) => error!("Content ar {} is neither Atom, nor RSS {}.\nTODO check real content type to help user.", &self.url, e),
},
Err(e) => error!("There is no text at {} due to error {}", &self.url, e),
},
Err(e) => error!("Unable to get {} due to {}.\nTODO Add better http response analysis !", &self.url, e),
}
self.clone()
}
}