From 802b2a81b889930976fa293119b785c853bf89af Mon Sep 17 00:00:00 2001 From: Jacob Kiers Date: Sun, 7 Aug 2022 23:17:41 +0200 Subject: [PATCH] Add missing options to build-feed Signed-off-by: Jacob Kiers --- bin/src/cli.rs | 5 +++++ bin/src/feed.rs | 42 ++++++++++++++++++++++++++++-------------- bin/src/main.rs | 32 +++++++++++++++++++++----------- 3 files changed, 54 insertions(+), 25 deletions(-) diff --git a/bin/src/cli.rs b/bin/src/cli.rs index a566c9d..5c69ea4 100644 --- a/bin/src/cli.rs +++ b/bin/src/cli.rs @@ -29,9 +29,14 @@ pub(crate) enum Command { }, /// Build an ATOM feed containing the full contents of the email BuildFeed { + /// Host name hosting the feed + hostname: String, /// Feed file #[clap(value_parser, default_value = "output/feed.atom")] filename: PathBuf, + /// Create an HTML file for each message + #[clap(short, long, value_parser, default_value_t = false)] + include_html: bool, }, /// Exports the emails as HTML files ExportHtml { diff --git a/bin/src/feed.rs b/bin/src/feed.rs index ad8681b..3b517ab 100644 --- a/bin/src/feed.rs +++ b/bin/src/feed.rs @@ -3,11 +3,17 @@ use crate::Message; use atom_syndication::{ ContentBuilder, Entry, EntryBuilder, Feed, FeedBuilder, Generator, LinkBuilder, Person, }; -use chrono::{DateTime, Utc, TimeZone}; +use chrono::{DateTime, TimeZone, Utc}; use mail_parser::HeaderValue; -pub(crate) fn add_entry_to_feed(feed: &mut Feed, message: &Message, processed_html: &String) { +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.get_date().expect("Could not extract date"); let from = match parsed.get_from() { @@ -17,7 +23,7 @@ pub(crate) fn add_entry_to_feed(feed: &mut Feed, message: &Message, processed_ht let path = crate::get_path(&parsed, message); - let url = format!("https://newsletters.kiers.eu/{}", &path); + let url = format!("https://{}/{}", hostname, &path); let mut entry: Entry = Newsletter { author: Person { @@ -41,26 +47,29 @@ pub(crate) fn add_entry_to_feed(feed: &mut Feed, message: &Message, processed_ht content: Some(processed_html.clone()), id: url.clone(), published: Utc.timestamp(date.to_timestamp(), 0), //(format!("{}{}", &date.to_iso8601(), "+00:00").as_str()).`unwrap(), - url: url, + url: match include_html { + true => url, + false => "".to_string(), + }, } .into(); entry.set_updated(Utc.timestamp(date.to_timestamp(), 0)); feed.entries.push(entry); } -pub(crate) fn build_atom_feed() -> Feed { +pub(crate) fn build_atom_feed(hostname: &String) -> Feed { FeedBuilder::default() .title("JJKiers Newsletters") - .id("https://newsletters.kiers.eu/feed.atom") + .id(format!("https://{}/feed.atom", hostname)) .link( LinkBuilder::default() - .href("https://newsletters.kiers.eu/") + .href(format!("https://{}/", hostname)) .rel("alternate") .build(), ) .link( LinkBuilder::default() - .href("https://newsletters.kiers.eu/feed.atom") + .href(format!("https://{}/feed.atom", hostname)) .rel("self") .build(), ) @@ -91,18 +100,23 @@ impl From for Entry { .build() }); - EntryBuilder::default() - .title(post.title) + let mut eb = EntryBuilder::default(); + + eb.title(post.title) .id(post.id) .published(Some(post.published.clone().into())) .author(post.author.into()) - .content(content) - .link( + .content(content); + + if post.url.len() > 1 { + eb.link( LinkBuilder::default() .href(post.url) .rel("alternate") .build(), - ) - .build() + ); + } + + eb.build() } } diff --git a/bin/src/main.rs b/bin/src/main.rs index 21a5edf..a47d049 100644 --- a/bin/src/main.rs +++ b/bin/src/main.rs @@ -35,7 +35,7 @@ fn main() -> Result<(), Box> { username.to_owned(), password.to_owned(), ), - cli::Command::BuildFeed { filename } => build_feed(&filename), + cli::Command::BuildFeed { filename , hostname, include_html } => build_feed(&filename, hostname.to_owned(), *include_html), _ => unimplemented!("This method is not yet implemented."), }; @@ -50,7 +50,7 @@ fn create_directory>(dir: P) -> Result<(), std::io::Error> { Ok(()) } -fn build_feed(filename: &PathBuf) -> Result<(), Box> { +fn build_feed(filename: &PathBuf, hostname: String, include_html: bool) -> Result<(), Box> { let dir = filename.parent().ok_or(format!( "Could not get parent directory of {}", filename.display() @@ -64,7 +64,7 @@ fn build_feed(filename: &PathBuf) -> Result<(), Box> { create_directory(dir)?; - let mut feed = feed::build_atom_feed(); + let mut feed = feed::build_atom_feed(&hostname); let mut reader = DataDirectoryMessageReader::new((&Path::new("data")).to_path_buf()); @@ -91,7 +91,12 @@ fn build_feed(filename: &PathBuf) -> Result<(), Box> { let html_body = parsed.get_html_body(0).expect("Could not read html body"); let processed_html = process_html(&html_body).expect("Could not process the HTML"); - feed::add_entry_to_feed(&mut feed, &msg, &processed_html); + if include_html { + let path : PathBuf = [dir, Path::new(&get_path(&parsed, &msg))].iter().collect(); + write_file(&path, processed_html.as_bytes())?; + } + + feed::add_entry_to_feed(&mut feed, &msg, &processed_html, &hostname, include_html); } if feed.entries.len() > 0 { @@ -156,18 +161,14 @@ fn fetch_from_imap( println!("Storing to {}", &html_path.display()); - OpenOptions::new() - .write(true) - .create(true) - .open(&html_path) - .expect(format!("Could not open file '{}' for writing", &html_path.display()).as_str()) - .write_all(msg.get_data()) - .expect(format!("Could not write html to file '{}'.", &html_path.display()).as_str()); + write_file(&html_path, msg.get_data())?; } Ok(()) } + + fn get_path(parsed: &ParsedMessage, msg: &Message) -> String { let date = parsed.get_date().expect("Could not extract date"); let date_str = format!( @@ -189,3 +190,12 @@ fn get_path(parsed: &ParsedMessage, msg: &Message) -> String { fn process_html(input: &str) -> Result { Ok(input.replace("src", "data-source")) } + +fn write_file(html_path: &PathBuf, data: &[u8]) -> Result<(), std::io::Error> { + OpenOptions::new() + .write(true) + .create(true) + .open(&html_path) + .expect(format!("Could not open file '{}' for writing", &html_path.display()).as_str()) + .write_all(data) +} \ No newline at end of file