~glyph/website

website/src/bin/generate_rss.rs -rw-r--r-- 3.7 KiB View raw
02cdf4ddglyph Add Extrasolar poster and parka drawing 23 hours ago
                                                                                
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
extern crate regex;
extern crate rss;

use std::error;
use std::fs;
use std::fs::File;
use std::io::prelude::*;
use regex::Regex;
use rss::{ChannelBuilder, Item};

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()?;

    // 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()
                    .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("<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(())
}