Attachment 'RSSReader-2.0.py'
Download 1 # -*- coding: iso-8859-1 -*-
2 u"""
3 MoinMoin - RSSREader macro Version 2.0 Beta
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
15 Examples:
16 * <<RSSReader("http://www.example.dot/feed.rss">>
17 * <<RSSReader("http://www.example.dot/feed.rss", maxEntries=30, allowHtml=False,includeStyle=True)>>
18
19 Description:
20 <<RSSReader(url, maxEntries, allowHtml, includeStyle>>
21 * url is the url of the RSS/ATOM feed to read, it's the only MUST field
22 * maxEntries define how many items the entire feed should display. Default is 30.
23 * allowHtml is an optional argument if you trust the feed to put the HTML
24 directly into the page. CAUTION: this could be an attack vector,
25 although feedparser should strip most "bad" HTML. Default ist False
26 * includeStyle per default True, so a nice css is added before the maco,
27 normaly you may say false and but in your own e.g. common.css some style
28 definition.
29 """
30
31 #do not chache the macro, so you receive updates without clearing the cache of the page
32 Dependencies = ["time"]
33
34
35 class RSStoWiki:
36 def __init__(self, macro, url, maxEntries, allowHtml, includeStyle):
37
38 #initial stuff for the whole class
39 import feedparser
40 self.f = feedparser.parse(url)
41 self.macro = macro
42 self.fmt = macro.formatter
43 self.allowHtml = allowHtml
44 self.includeStyle = includeStyle
45 self.maxEntries = maxEntries
46 self.request = macro.request
47 self._ = self.request.getText
48 self.result = []
49
50 #check if feed exist or display an error message
51 if self.f.feed == {}:
52 self.result.append(self.fmt.div(True, css_class="error rssError") + \
53 self.fmt.icon('info') + \
54 self.fmt.text(" ") + \
55 self.fmt.strong(True) + \
56 self.fmt.text(self._('Unable to retreive feed')) + \
57 self.fmt.strong(False) + \
58 self.fmt.text(' "%s"' % url) + \
59 self.fmt.div(False))
60 self.valid = False
61 else:
62 self.valid = True
63
64 #generate content for the main (header) feed
65 def get_title(self):
66 if 'title' not in self.f.feed:
67 return
68 self.result.append(self.fmt.heading(True, depth=1, css_class="rssTitle") + \
69 self.fmt.text(self.f.feed.title) + \
70 self.fmt.heading(False, depth=1))
71
72 def get_subtitle(self):
73 if 'subtitle' not in self.f.feed:
74 return
75 self.result.append(self.fmt.paragraph(True, css_class="rssSubTitle") + \
76 self.fmt.text(self.f.feed.subtitle) + \
77 self.fmt.paragraph(False))
78
79 def get_description(self):
80 if 'description' not in self.f.feed:
81 return
82 #only desiplay description if its different compare to subtitel, mostly not
83 if ('subtitle' in self.f.feed) and ('description' in self.f.feed):
84 if self.f.feed.subtitle == self.f.feed.description:
85 return
86 self.result.append(self.fmt.paragraph(True, css_class="rssDescription") + \
87 self.fmt.text(self.f.feed.description) + \
88 self.fmt.paragraph(False))
89
90 def get_feedlink(self):
91 if 'link' not in self.f.feed:
92 return
93 self.get_link(self.f.feed.link)
94
95 #generate content for a single feed item (entries)
96 def get_entries(self):
97 entriesCount = 0
98 for entry in self.f.entries:
99 # count and check maxEntries
100 entriesCount = entriesCount + 1
101 if entriesCount > self.maxEntries:
102 break
103 # start with generating the entry (title, link, update, description, ..)
104 self.result.append(self.fmt.div(True, css_class="rssEntry"))
105 if 'title' in entry:
106 if 'link' in entry:
107 self.get_entry_header(entry.title, entry.link)
108 else:
109 self.get_entry_header(entry.title)
110 if 'updated' in entry:
111 self.result.append(self.fmt.paragraph(True, css_class="rssEntryUpdated") + \
112 self.fmt.text(entry.updated) + \
113 self.fmt.paragraph(False))
114 if 'description' in entry:
115 self.get_entry_body(entry.description)
116 if ('link' in entry) and 'title' not in entry:
117 self.get_link(entry.link)
118 self.result.append(self.fmt.div(False))
119
120 #helper functions
121 def get_paragraph(self, text):
122 self.result.append(self.fmt.paragraph(True) + \
123 self.fmt.text(text) + \
124 self.fmt.paragraph(False))
125
126 def get_link(self, link):
127 self.result.append(self.fmt.url(True, href=link) + \
128 self.fmt.text(" ") + \
129 self.fmt.icon('www') + \
130 self.fmt.text(" " + link) + \
131 self.fmt.url(False))
132
133 #helper function for the entry / item
134 def get_entry_header(self, title, link=None):
135 if link: # if link exist, make the entry title with a link
136 self.result.append(self.fmt.paragraph(True, css_class="rssEntryTitle") + \
137 self.fmt.url(True, href=link) + \
138 self.fmt.text(title) + \
139 self.fmt.url(False) + \
140 self.fmt.paragraph(False))
141 else:
142 self.result.append(self.fmt.paragraph(True, css_class="rssEntryTitle") + \
143 self.fmt.text(title) + \
144 self.fmt.heading(False))
145
146 def get_entry_body(self, body):
147 self.result.append(self.fmt.paragraph(True, css_class="rssEntryBody"))
148 if (self.allowHtml): # check if html is allow, for raw html output
149 self.result.append(self.fmt.rawHTML(body))
150 else:
151 self.result.append(self.fmt.text(body))
152 self.result.append(self.fmt.paragraph(False))
153
154 def get_css(self):
155 if not self.includeStyle:
156 return
157 self.result.append(self.fmt.rawHTML("""
158 <style type="text/css" media="all">
159 /* macro RSSReader start*/
160 div.rssReader .rssHeader {
161 margin-top: 1em;
162 margin-bottom: 1em;
163 border-bottom: 1px dotted gray;
164 }
165 div.rssReader .rssSubTitle, div.rssReader .rssDescription {
166 font-size: bold;
167 }
168 div.rssReader div.rssEntries {
169 margin-top: 1em;
170 margin-bottom: 1em;
171 border-bottom: 1px dotted gray;
172 }
173 div.rssReader div.rssEntry {
174 margin-top: 1em;
175 margin-bottom: 1em;
176 }
177 div.rssReader p.rssEntryTitle {
178 font-size: 1.25em;
179 font-weight: bold;
180 margin: 0em;
181 }
182 div.rssReader p.rssEntryUpdated {
183 color: gray;
184 font-size: 0.75em;
185 margin: 0em;
186 }
187 div.rssReader p.rssEntryBody {
188 margin: 0em;
189 padding-top: 1em;
190 }
191 /* macro RSSReader end*/
192 </style>
193 """))
194
195 #output content
196 def get_output(self):
197 if self.valid:
198 #start
199 self.result.append(self.fmt.div(True, css_class="rssReader"))
200 self.get_css()
201 #header
202 self.result.append(self.fmt.div(True, css_class="rssHeader"))
203 self.get_title()
204 self.get_subtitle()
205 self.get_description()
206 self.result.append(self.fmt.linebreak(False))
207 self.get_feedlink()
208 self.result.append(self.fmt.div(False))
209 #entries
210 self.result.append(self.fmt.div(True, css_class="rssEntries"))
211 self.get_entries()
212 self.result.append(self.fmt.div(False))
213 #end
214 self.result.append(self.fmt.div(False))
215 return ''.join(self.result)
216
217
218 def macro_RSSReader(macro, feed, maxEntries=30, allowHtml=False, includeStyle=True):
219 rss = RSStoWiki(macro, feed, maxEntries, allowHtml, includeStyle)
220 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.