diff options
Diffstat (limited to 'src/generate_rss.rs')
| -rw-r--r-- | src/generate_rss.rs | 72 |
1 files changed, 72 insertions, 0 deletions
diff --git a/src/generate_rss.rs b/src/generate_rss.rs new file mode 100644 index 0000000..48a6917 --- /dev/null +++ b/src/generate_rss.rs @@ -0,0 +1,72 @@ +use crate::*; + +use std::collections::VecDeque; + +use chrono::{DateTime, Utc, Local}; + + +pub fn generate_rss(feed: &Feed, website: &Website) -> String { + let path = &feed.source_path; + let content = std::fs::read_to_string(path).unwrap(); + let mut lines: VecDeque<&str> = content.lines().collect(); + let base_url = website.config.get("rss.base_url"); + if base_url.is_empty() { + warn!("No value was given for 'rss.base_url' key in toaster.conf"); + } + let (parent_url, _) = feed.url.split_once('/').unwrap(); + + let channel_title = lines.pop_front().unwrap_or("No title"); + let last_build_date = match feed.last_modified { + Some(system_time) => system_time.into(), + None => Utc::now(), + }.to_rfc2822(); + let mut all_entries = String::new(); + + for line in &lines { + if line.is_empty() { continue } + if let Some((timestamp, name)) = line.split_once("::") { + let mut timestamp = timestamp.to_string(); + let entry_title = name; + if !timestamp.contains('T') { + timestamp.push_str("T00:00:00"); + } + if !timestamp.contains('Z') || timestamp.contains('+') { + let offset = Local::now().offset().to_string(); + timestamp.push_str(&offset); + } + let Ok(entry_time) = DateTime::parse_from_rfc3339(×tamp) else { + warn!("Invalid timestamp in RSS file {path:?}: {timestamp:?}"); + continue; + }; + let entry_link = format!("{base_url}/{parent_url}/{}.html", to_slug(name)); + + // Check that child page exists. + if let None = website.has_page(feed, name, "html") { + warn!("Feed {feed:?} contains link to nonexistent page {name:?}"); + } + + + let entry_string = format!(" + <item> + <title>{entry_title}</title> + <link>{entry_link}</link> + <pubDate>{entry_time}</pubDate> + </item> +"); + all_entries.push_str(&entry_string); + } else { + warn!("Invalid line in RSS file {path:?}: {line:?}"); + } + } + + format!( +r#"<?xml version="1.0" encoding="UTF-8" ?> +<rss version="2.0"> + <channel> + <title>{channel_title}</title> + <link>{base_url}</link> + <lastBuildDate>{last_build_date}</lastBuildDate> +{all_entries} + </channel> +</rss>"#) +} |
