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

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

#from io import StringIO
from StringIO 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')