newsletter-to-web/src/feed.rs

138 lines
3.8 KiB
Rust

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<W: std::io::Write>(
feed: Feed,
mut out: W,
) -> Result<W, atom_syndication::Error> {
let _ = writeln!(out, r#"<?xml version="1.0"?>"#);
let _ = writeln!(out, r#"<?xml-stylesheet href="feed.xsl" type="text/xsl"?>"#);
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<String>,
author: Person,
published: DateTime<Utc>,
}
impl From<Newsletter> 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()
}
}