//! # RSS Generator //! //! A custom RSS generator. It crawls the template sub-directories containing //! articles for syndication, extracts relevant information and writes the items //! to `./static/feed.rss`. //! extern crate regex; extern crate rss; use regex::Regex; use rss::{ChannelBuilder, Item}; use std::{error, fs, fs::File, io::prelude::*}; fn main() -> Result<(), Box> { // create rss channel for mycelial.technology let mut channel = ChannelBuilder::default() .title("mycelial technology") .link("https://mycelial.technology") .description( "glyph's RSS feed. Biophilic musings on carbon-based and silicon-based technologies.", ) .build()?; // list template directories containing articles for syndication let bacteria = "./site/bacteria"; let computers = "./site/computers"; let fungi = "./site/fungi"; let plants = "./site/plants"; // add directories to a vector let dirs = vec![bacteria, computers, fungi, plants]; // create vectors for item fields let mut titles = Vec::new(); let mut pub_dates = Vec::new(); let mut urls = Vec::new(); let mut articles = Vec::new(); // loop through template directories and extract item field values for dir in dirs { for entry in fs::read_dir(dir)? { let entry = entry?; let path = entry.path(); if !path.ends_with("index.html") { // populate item url vector from article filenames let re_url = Regex::new("./site/(.*).html")?; let caps_url = re_url.captures( path.to_str() .expect("Failed to convert file path to string slice for regex capture"), ); if let Some(url) = caps_url { let article_url = url[1].replace("_", "-"); let full_url = format!("https://mycelial.technology/{}", article_url); urls.push(full_url); }; // open the file (article) and read it to a string let mut file = File::open(path)?; let mut contents = String::new(); file.read_to_string(&mut contents)?; // populate item title vector from article heading let re_h2 = Regex::new("

(.*)

")?; let caps_h2 = re_h2.captures(&contents); if let Some(title) = caps_h2 { titles.push(title[1].to_string()); }; // populate pub_date vector from first italic element in article let re_i = Regex::new("(.*)")?; let caps_i = re_i.captures(&contents); if let Some(date) = caps_i { pub_dates.push(date[1].to_string()); }; // populate article content vector from article element let re_article = Regex::new(r"
[\s\S]*
")?; let caps_article = re_article.captures(&contents); if let Some(content) = caps_article { articles.push(content[0].to_string()); }; } } } // get length of titles vector (serves as proxy for total number of articles) let library = titles.len(); // create vector for channel items let mut items = Vec::new(); // loop through vectors of item fields and create items accordingly for x in 0..library { let mut item = Item::default(); item.set_title(titles[x].to_string()); item.set_link(urls[x].to_string()); item.set_pub_date(pub_dates[x].to_string()); item.set_description(articles[x].to_string()); items.push(item) } // add the items to the channel channel.set_items(items); // write the channel to file let rss_file = File::create("./static/feed.rss")?; channel.write_to(rss_file)?; Ok(()) }