all repos — site @ c390f021aae70ae94d58cea3e99332ab6aa9468c

source for my site, found at icyphox.sh

bin/rss.py (view raw)

 1#!/usr/bin/env python3
 2# generate an rss item
 3
 4import html
 5from markdown2 import markdown
 6import sys
 7import os
 8from collections import namedtuple
 9import re
10import arrow
11import operator
12import warnings
13
14# warnings.simplefilter("ignore", arrow.factory.ArrowParseWarning)
15items_raw = []
16from lxml import etree as ET
17
18
19def convert_date(d):
20    return arrow.get(d, "YYYY-MM-DD").format("ddd, DD MMM YYYY HH:mm:ss Z")
21
22
23PREFIX_URL = "https://icyphox.sh/blog/"
24link_extractor = re.compile("\/([^\/]*)\.md$")
25
26
27def generate_node(rendered, path):
28
29    item = ET.Element("item")
30    title = ET.SubElement(item, "title")
31    title.text = rendered.metadata["title"]
32    description = ET.SubElement(item, "description")
33    description.text = ET.CDATA(str(rendered))
34    link = ET.SubElement(item, "link")
35    link.text = PREFIX_URL + link_extractor.search(path).group(1)
36    pubData = ET.SubElement(item, "pubDate")
37    pubData.text = convert_date(rendered.metadata["date"])
38    guid = ET.SubElement(item, "guid")
39    guid.text = PREFIX_URL + link_extractor.search(path).group(1)
40
41    return item
42
43
44def parse_article(path):
45    with open(path) as f:
46        rendered = markdown(
47            f.read(),
48            extras=[
49                "metadata",
50                "fenced-code-blocks",
51                "header-ids",
52                "footnotes",
53                "smarty-pants",
54                "link-patterns",
55            ],
56            link_patterns=[
57                (
58                    re.compile(
59                        r"((([A-Za-z]{3,9}:(?:\/\/)?)(?:[\-;:&=\+\$,\w]+@)?[A-Za-z0-9\.\-]+(:[0-9]+)?|(?:www\.|[\-;:&=\+\$,\w]+@)[A-Za-z0-9\.\-]+)((?:\/[\+~%\/\.\w\-_]*)?\??(?:[\-\+=&;%@\.\w_]*)#?(?:[\.\!\/\\\w]*))?)"
60                    ),
61                    r"\1",
62                )
63            ],
64        )
65        return (arrow.get(rendered.metadata["date"]), rendered, path)
66
67
68tree = ET.parse(os.path.join("templates", "feed.xml"))
69articles = []
70
71for f in os.listdir("pages/blog/"):
72    if f not in ["_index.md", "feed.xml"]:
73        articles.append(parse_article(os.path.join("pages/blog", f)))
74
75articles.sort(key=operator.itemgetter(0), reverse=True)
76chan = tree.find("channel")
77
78for article in articles:
79    chan.append(generate_node(article[1], article[2]))
80
81out = ET.tostring(tree, encoding="unicode")
82with open("pages/blog/feed.xml", "w") as f:
83    f.write(out)