mod link; use chrono::{DateTime, Utc}; use link::Link; use url::Url; /// Export crawl index to the RSS file pub struct Feed { buffer: String, canonical: Link, } impl Feed { pub fn new( title: &str, description: Option<&str>, canonical: Option, capacity: usize, ) -> Self { let t = chrono::Utc::now().to_rfc2822(); let mut buffer = String::with_capacity(capacity); buffer.push_str(""); buffer.push_str(""); buffer.push_str(&t); buffer.push_str(""); buffer.push_str(""); buffer.push_str(&t); buffer.push_str(""); buffer.push_str(""); buffer.push_str(title); buffer.push_str(""); if let Some(d) = description { buffer.push_str(""); buffer.push_str(d); buffer.push_str("") } if let Some(ref c) = canonical { // @TODO required the RSS specification! buffer.push_str(""); buffer.push_str(c.as_str()); buffer.push_str("") } Self { buffer, canonical: Link::from_url(canonical), } } /// Append `item` to the feed `channel` pub fn push(&mut self, guid: i64, time: DateTime, title: String, message: &str) { self.buffer.push_str(&format!( "{guid}{title}{}", self.canonical.link(guid) )); self.buffer.push_str(""); self.buffer.push_str(&escape(message)); self.buffer.push_str(""); self.buffer.push_str(""); self.buffer.push_str(&time.to_rfc2822()); self.buffer.push_str(""); self.buffer.push_str("") } /// Write final bytes pub fn commit(mut self) -> String { self.buffer.push_str(""); self.buffer } } fn escape(value: &str) -> String { value .replace('&', "&") .replace('<', "<") .replace('>', ">") .replace('"', """) .replace("'", "'") }