Attachment 'RSSReader.py'
Download 1 # -*- coding: iso-8859-1 -*-
2 u"""
3 MoinMoin - RSSREader macro Version 2.1
4 Output an RSS/ATOM Feed
5 http://moinmo.in/MacroMarket/RSSReader
6
7 @copyright: 2006 by Ian Wienand <ianw@ieee.org>
8 2010 by Marcel Häfner http://moinmo.in/MarcelH%C3%A4fner
9 @license: Public Doman / GNU GPL
10
11 Version:
12 * 1.0 default Version from Ian Wienand
13 * 2.0 first version from Marcel Häfner
14 * 2.1 Bugfix
15 * 2.2 Updates from Matthijs Kooijman
16
17 Examples:
18 * <<RSSReader("http://www.example.dot/feed.rss")>>
19 * <<RSSReader(feed="http://www.example.dot/feed.rss", maxEntries=30, allowHtml=False,includeStyle=True)>>
20
21 Description:
22 <<RSSReader(url, maxEntries, allowHtml, includeStyle, dateFormat, linkEntries>>
23 * url is the url of the RSS/ATOM feed to read, it's the only MUST field
24 * maxEntries define how many items the entire feed should display. Default is 30.
25 * allowHtml is an optional argument if you trust the feed to put the HTML
26 directly into the page. CAUTION: this could be an attack vector,
27 although feedparser should strip most "bad" HTML. Default ist False
28 * includeStyle per default True, so a nice css is added before the maco,
29 normaly you may say false and but in your own e.g. common.css some style
30 definition.
31 * dateFormat is a date format to use for the last updated /
32 published date and time of the entry. This format must be in strftime
33 format (see http://docs.python.org/2/library/time.html#time.strftime).
34 By default, whatever format is used in the feed is displayed as-is.
35 * linkEntries indicates whether the title of a post should be a
36 link to the actual post (as indicated by the "link" field for the
37 entry in the feed). Defaults to True.
38 """
39
40 #do not chache the macro, so you receive updates without clearing the cache of the page.
41 #or if you like caching, add this: Dependencies = []
42 Dependencies = ["time"]
43
44
45 class RSStoWiki:
46 def __init__(self, macro, url, maxEntries, allowHtml, includeStyle, dateFormat, linkEntries):
47
48 #initial stuff for the whole class
49 import feedparser
50 self.f = feedparser.parse(url)
51 self.macro = macro
52 self.fmt = macro.formatter
53 self.allowHtml = allowHtml
54 self.includeStyle = includeStyle
55 self.maxEntries = maxEntries
56 self.dateFormat = dateFormat
57 self.linkEntries = linkEntries
58 self.request = macro.request
59 self._ = self.request.getText
60 self.result = []
61
62 #check if feed exist or display an error message
63 if self.f.feed == {}:
64 self.result.append(self.fmt.div(True, css_class="error rssError") + \
65 self.fmt.icon('info') + \
66 self.fmt.text(" ") + \
67 self.fmt.strong(True) + \
68 self.fmt.text(self._('Unable to retreive feed')) + \
69 self.fmt.strong(False) + \
70 self.fmt.text(' "%s"' % url) + \
71 self.fmt.div(False))
72 self.valid = False
73 else:
74 self.valid = True
75
76 #generate content for the main (header) feed
77 def get_title(self):
78 if 'title' not in self.f.feed:
79 return
80 self.result.append(self.fmt.heading(True, depth=1, css_class="rssTitle") + \
81 self.fmt.text(self.f.feed.title) + \
82 self.fmt.heading(False, depth=1))
83
84 def get_subtitle(self):
85 if 'subtitle' not in self.f.feed:
86 return
87 self.result.append(self.fmt.paragraph(True, css_class="rssSubTitle") + \
88 self.fmt.text(self.f.feed.subtitle) + \
89 self.fmt.paragraph(False))
90
91 def get_description(self):
92 if 'description' not in self.f.feed:
93 return
94 #only desiplay description if its different compare to subtitel, mostly not
95 if ('subtitle' in self.f.feed) and ('description' in self.f.feed):
96 if self.f.feed.subtitle == self.f.feed.description:
97 return
98 self.result.append(self.fmt.paragraph(True, css_class="rssDescription") + \
99 self.fmt.text(self.f.feed.description) + \
100 self.fmt.paragraph(False))
101
102 def get_feedlink(self):
103 if 'link' not in self.f.feed:
104 return
105 self.get_link(self.f.feed.link)
106
107 #generate content for a single feed item (entries)
108 def get_entries(self):
109 import time
110 entriesCount = 0
111 for entry in self.f.entries:
112 # count and check maxEntries
113 entriesCount = entriesCount + 1
114 if entriesCount > self.maxEntries:
115 break
116 # start with generating the entry (title, link, update, description, ..)
117 self.result.append(self.fmt.div(True, css_class="rssEntry"))
118 if 'title' in entry:
119 if self.linkEntries and 'link' in entry:
120 self.get_entry_header(entry.title, entry.link)
121 else:
122 self.get_entry_header(entry.title)
123 if self.dateFormat and 'updated_parsed' in entry:
124 self.result.append(self.fmt.paragraph(True, css_class="rssEntryUpdated") + \
125 self.fmt.text(time.strftime(self.dateFormat, entry.updated_parsed)) + \
126 self.fmt.paragraph(False))
127 elif 'updated' in entry:
128 self.result.append(self.fmt.paragraph(True, css_class="rssEntryUpdated") + \
129 self.fmt.text(entry.updated) + \
130 self.fmt.paragraph(False))
131 if 'description' in entry:
132 self.get_entry_body(entry.description)
133 if ('link' in entry) and 'title' not in entry:
134 self.get_link(entry.link)
135 self.result.append(self.fmt.div(False))
136
137 #helper functions
138 def get_paragraph(self, text):
139 self.result.append(self.fmt.paragraph(True) + \
140 self.fmt.text(text) + \
141 self.fmt.paragraph(False))
142
143 def get_link(self, link):
144 self.result.append(self.fmt.url(True, href=link) + \
145 self.fmt.text(" ") + \
146 self.fmt.icon('www') + \
147 self.fmt.text(" " + link) + \
148 self.fmt.url(False))
149
150 #helper function for the entry / item
151 def get_entry_header(self, title, link=None):
152 if link: # if link exist, make the entry title with a link
153 self.result.append(self.fmt.paragraph(True, css_class="rssEntryTitle") + \
154 self.fmt.url(True, href=link) + \
155 self.fmt.text(title) + \
156 self.fmt.url(False) + \
157 self.fmt.paragraph(False))
158 else:
159 self.result.append(self.fmt.paragraph(True, css_class="rssEntryTitle") + \
160 self.fmt.text(title) + \
161 self.fmt.paragraph(False))
162
163 def get_entry_body(self, body):
164 self.result.append(self.fmt.paragraph(True, css_class="rssEntryBody"))
165 if (self.allowHtml): # check if html is allow, for raw html output
166 self.result.append(self.fmt.rawHTML(body))
167 else:
168 self.result.append(self.fmt.text(body))
169 self.result.append(self.fmt.paragraph(False))
170
171 def get_css(self):
172 if not self.includeStyle:
173 return
174 self.result.append(self.fmt.rawHTML("""
175 <style type="text/css" media="all">
176 /* macro RSSReader start*/
177 div.rssReader .rssHeader {
178 margin-top: 1em;
179 margin-bottom: 1em;
180 border-bottom: 1px dotted gray;
181 }
182 div.rssReader .rssSubTitle, div.rssReader .rssDescription {
183 font-size: bold;
184 }
185 div.rssReader div.rssEntries {
186 margin-top: 1em;
187 margin-bottom: 1em;
188 border-bottom: 1px dotted gray;
189 }
190 div.rssReader div.rssEntry {
191 margin-top: 1em;
192 margin-bottom: 1em;
193 }
194 div.rssReader p.rssEntryTitle {
195 font-weight: bold;
196 margin: 0em;
197 }
198 div.rssReader p.rssEntryUpdated {
199 color: gray;
200 font-size: 0.75em;
201 margin: 0em;
202 }
203 div.rssReader p.rssEntryBody {
204 margin: 0em;
205 padding-top: 1em;
206 }
207 /* macro RSSReader end*/
208 </style>
209 """))
210
211 #output content
212 def get_output(self):
213 if self.valid:
214 #start
215 self.result.append(self.fmt.div(True, css_class="rssReader"))
216 self.get_css()
217 #header
218 self.result.append(self.fmt.div(True, css_class="rssHeader"))
219 self.get_title()
220 self.get_subtitle()
221 self.get_description()
222 self.result.append(self.fmt.linebreak(False))
223 self.get_feedlink()
224 self.result.append(self.fmt.div(False))
225 #entries
226 self.result.append(self.fmt.div(True, css_class="rssEntries"))
227 self.get_entries()
228 self.result.append(self.fmt.div(False))
229 #end
230 self.result.append(self.fmt.div(False))
231 return ''.join(self.result)
232
233
234 def macro_RSSReader(macro, feed, maxEntries=30, allowHtml=False, includeStyle=True, dateFormat=None, linkEntries=True):
235 rss = RSStoWiki(macro, feed, maxEntries, allowHtml, includeStyle, dateFormat, linkEntries)
236 return rss.get_output()
Attached Files
To refer to attachments on a page, use attachment:filename, as shown below in the list of files. Do NOT use the URL of the [get] link, since this is subject to change and can break easily.You are not allowed to attach a file to this page.