-
Notifications
You must be signed in to change notification settings - Fork 3
/
Copy pathfeeds.py
115 lines (95 loc) · 3.49 KB
/
feeds.py
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
112
113
114
115
from feedgen.feed import FeedGenerator
import main as contents
from dateutil import parser
import markdown
import pytz
from datetime import datetime
def convert_dtstr_to_dt(date_str):
"""
Convert a naive or non-naive date/datetime string to a datetime object.
Naive datetime strings are assumed to be in GMT (UTC) timezone.
Args:
date_str (str): The date or datetime string to convert.
Returns:
datetime: The corresponding datetime object.
"""
try:
dt = parser.parse(date_str)
if dt.tzinfo is None:
# If the datetime object is naive, set it to GMT (UTC)
dt = dt.replace(tzinfo=pytz.UTC)
return dt
except (ValueError, TypeError) as e:
print(f"Error parsing date string: {e}")
return None
def filter_posts_by_tag(posts: list[dict], tag: str):
"""
Generator function that filters posts by a single tag.
"""
for post in posts:
post_tags = [x.lower() for x in post.get('tags', [])]
if tag in post_tags:
yield post
def github_markdown_to_html(markdown_str):
"""
Convert a GitHub-flavored Markdown string to HTML.
Args:
markdown_str (str): The GitHub-flavored Markdown string to convert.
Returns:
str: The resulting HTML string.
"""
html = markdown.markdown(
markdown_str,
extensions=['extra', 'codehilite', 'toc', 'tables']
)
return html
def add_entry(fg, raw):
content, metadata = contents.get_post(raw['slug'])
fe = fg.add_entry()
linker = f'https://daniel.feldroy.com/posts/{raw["slug"]}'
fe.id(linker)
fe.link(href=linker)
fe.title(metadata['title'])
fe.summary(metadata.get('description'))
try:
fe.content(github_markdown_to_html(content),type='html')
# fe.content(src=linker)
except TypeError:
# Probably a Jupyter notebook, so it won't render easily. Just pass it by.
pass
fe.contributor([{'name': 'Daniel Roy Greenfeld', 'email': '[email protected]'}])
fe.author([{'name': 'Daniel Roy Greenfeld', 'email': '[email protected]'}])
fe.pubDate(convert_dtstr_to_dt(metadata['date']))
# Add tags to the entry
for tag in metadata.get('tags', []):
fe.category(term=tag)
def build_feed(content_tag: str | None = None):
fg = FeedGenerator()
fg.id('https://daniel.feldroy.com/')
fg.author({'name': 'Daniel Roy Greenfeld', 'email': '[email protected]', 'uri':'https://daniel.feldroy.com'})
fg.link(href='https://daniel.feldroy.com', rel='alternate')
fg.logo('https://daniel.feldroy.com/images/pydanny-cartwheel.png')
fg.rights(f'All rights reserved {datetime.now().year}, Daniel Roy Greenfeld')
fg.language('en')
posts = contents.list_posts(published=True)
if content_tag is None:
fg.title('Inside the head of Daniel Roy Greenfeld')
else:
fg.title(f'{content_tag.capitalize()} posts by Daniel Roy Greenfeld')
posts = list(filter_posts_by_tag(posts, content_tag))
for raw in posts[:1]:
add_entry(fg, raw)
if content_tag is not None:
fg.atom_file(f'feeds/{content_tag}.atom.xml', pretty=True)
else:
fg.atom_file('feeds/atom.xml', pretty=True)
if __name__ == '__main__':
import sys
if len(sys.argv) == 1:
build_feed(None)
build_feed('django')
build_feed('python')
build_feed('til')
else:
content_tag = sys.argv[1]
build_feed(sys.argv[1])