summaryrefslogtreecommitdiff
path: root/site_builder/feeds.py
blob: dd343b5acf61c07f8b928d2516294d9c5e74d4e7 (plain)
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
# vim: set filencoding=utf8
"""
Atom Feed Writer

@author: Mike Crute (mike@crute.us)
@date: June 04, 2010
"""

from io import StringIO
from xml.sax.saxutils import XMLGenerator


class SimpleXMLGenerator(XMLGenerator):

    def __init__(self, encoding="utf-8"):
        self.output = StringIO()
        XMLGenerator.__init__(self, out=self.output, encoding=encoding)

    def get_contents(self):
        return self.output.getvalue()

    def startElement(self, tag, attrs=None):
        attrs = attrs if attrs else {}
        return XMLGenerator.startElement(self, tag, attrs)

    def addElement(self, tag, contents=None, attrs=None):
        attrs = attrs if attrs else {}
        self.startElement(tag, attrs)
        if contents:
            self.characters(contents)
        self.endElement(tag)


class Atom1Feed(object):

    def __init__(self, posts, title, feed_url, updated, blog_url,
                    post_filter=None):
        self.posts = posts
        self.title = title
        self.feed_url = feed_url
        self.updated = updated
        self.blog_url = blog_url
        self.handler = SimpleXMLGenerator()

        if not post_filter:
            post_filter = lambda post: True

        self.post_filter = post_filter

    def _format_time(self, timeobj):
        return timeobj.strftime("%Y-%m-%dT%H:%M:%SZ")

    def get_feed(self):
        self.handler.startDocument()
        self.handler.startElement("feed", {
            "xmlns": "http://www.w3.org/2005/Atom" })

        self.add_root_elements()

        for post in self.posts:
            if not self.post_filter(post):
                continue

            self.add_post(post)

        self.handler.endElement("feed")

        return self.handler.get_contents()

    def add_root_elements(self):
        self.handler.addElement("title", self.title)
        self.handler.addElement("updated", self._format_time(self.updated))
        self.handler.addElement("id", self.feed_url)
        self.handler.addElement("link", attrs={
            "rel": "alternate",
            "type": "text/html",
            "href": self.blog_url })
        self.handler.addElement("link", attrs={
            "rel": "self",
            "type": "application/atom+xml",
            "href": self.feed_url })

    def add_post(self, post):
        handler = self.handler

        handler.startElement("entry")

        handler.startElement("author")
        handler.addElement("name", post.author.name)
        handler.addElement("email", post.author.email)
        handler.endElement("author")

        post_href = "{0}/{1}".format(self.blog_url, post.filename)

        handler.addElement("title", post.title)
        handler.addElement("link", attrs={
            "rel": "alternate",
            "type": "text/html",
            "href": post_href })
        handler.addElement("id", post_href)
        handler.addElement("updated", self._format_time(post.post_date))
        handler.addElement("published", self._format_time(post.post_date))

        for tag in post.tags:
            handler.addElement("category", attrs={ "term": tag })

        handler.addElement("content", post.contents, attrs={ "type": "html" })

        handler.endElement("entry")