Add RSS file and RSS generator
This commit is contained in:
108
src/bin/generate_rss.rs
Normal file
108
src/bin/generate_rss.rs
Normal file
@ -0,0 +1,108 @@
|
||||
extern crate regex;
|
||||
extern crate rss;
|
||||
|
||||
use regex::Regex;
|
||||
use rss::{ChannelBuilder, Item};
|
||||
use std::error;
|
||||
use std::fs;
|
||||
use std::fs::File;
|
||||
use std::io::prelude::*;
|
||||
|
||||
fn main() -> Result<(), Box<dyn error::Error>> {
|
||||
// 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()
|
||||
.unwrap();
|
||||
|
||||
// list template directories containing articles for syndication
|
||||
let bacteria = "./templates/bacteria";
|
||||
let computers = "./templates/computers";
|
||||
let fungi = "./templates/fungi";
|
||||
let plants = "./templates/plants";
|
||||
|
||||
// add directories to a vector
|
||||
let mut dirs = Vec::new();
|
||||
dirs.push(bacteria);
|
||||
dirs.push(computers);
|
||||
dirs.push(fungi);
|
||||
dirs.push(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();
|
||||
|
||||
// populate item url vector from article filenames
|
||||
let re_url = Regex::new("./templates/(.*).html.tera")?;
|
||||
let caps_url = re_url.captures(&path.to_str().unwrap());
|
||||
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("<h2>(.*)</h2>")?;
|
||||
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("<i>(.*)</i>")?;
|
||||
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"<article>[\s\S]*</article>")?;
|
||||
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("rss.xml")?;
|
||||
channel.write_to(rss_file)?;
|
||||
|
||||
Ok(())
|
||||
}
|
Reference in New Issue
Block a user