109 lines
3.6 KiB
Rust
109 lines
3.6 KiB
Rust
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("static/feed.rss")?;
|
|
channel.write_to(rss_file)?;
|
|
|
|
Ok(())
|
|
}
|