use crate::Message; use atom_syndication::{ ContentBuilder, Entry, EntryBuilder, Feed, FeedBuilder, Generator, LinkBuilder, Person, WriteConfig, }; use chrono::{DateTime, TimeZone, Utc}; use mail_parser::HeaderValue; pub(crate) fn add_entry_to_feed( feed: &mut Feed, message: &Message, processed_html: &String, hostname: &String, include_html: bool, ) { let parsed = message.get_parsed().unwrap(); let date = parsed.date().expect("Could not extract date"); let from = match parsed.from() { HeaderValue::Address(e) => e, _ => return, }; let path = crate::get_path(&parsed, message); let url = format!("https://{}/{}", hostname, &path); let mut entry: Entry = Newsletter { author: Person { name: match &from.name { Some(n) => n.to_string(), _ => match &from.address { Some(e) => e.to_string(), _ => "".to_string(), }, }, email: match &from.address { Some(e) => Some(e.to_string()), _ => None, }, uri: None, }, title: parsed .subject() .expect("Expected a subject") .to_string(), content: Some(processed_html.clone()), id: url.clone(), published: Utc.timestamp_opt(date.to_timestamp(), 0).unwrap(), //(format!("{}{}", &date.to_iso8601(), "+00:00").as_str()).`unwrap(), url: match include_html { true => url, false => "".to_string(), }, } .into(); entry.set_updated(Utc.timestamp_opt(date.to_timestamp(), 0).unwrap()); feed.entries.push(entry); } pub(crate) fn build_atom_feed(hostname: &String, feed_file: &str) -> Feed { let feed_url = format!("https://{}/{}", hostname, feed_file); FeedBuilder::default() .title("JJKiers Newsletters") .id(&feed_url) .link( LinkBuilder::default() .href(format!("https://{}/", hostname)) .rel("alternate".to_string()) .build(), ) .link( LinkBuilder::default() .href(&feed_url) .rel("self".to_string()) .build(), ) .generator(Generator { value: String::from("newsletter-to-web"), uri: None, version: Some(String::from("0.0.1")), }) .build() } pub(crate) fn write_feed( feed: Feed, mut out: W, ) -> Result { let _ = writeln!(out, r#""#); let _ = writeln!(out, r#""#); let config = WriteConfig { write_document_declaration: false, ..Default::default() }; feed.write(out, config) } //#[derive(Serialize, Deserialize, Debug)] pub(crate) struct Newsletter { id: String, url: String, title: String, content: Option, author: Person, published: DateTime, } impl From for Entry { fn from(post: Newsletter) -> Self { let content = post.content.map(|v| { ContentBuilder::default() .value(v) .content_type(Some("html".to_string())) .build() }); let mut eb = EntryBuilder::default(); eb.title(post.title) .id(post.id) .published(Some(post.published.clone().into())) .author(post.author.into()) .content(content); if post.url.len() > 1 { eb.link( LinkBuilder::default() .href(post.url) .rel("alternate".to_string()) .build(), ); } eb.build() } }