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.
  • [get | view] (2006-02-22 00:46:41, 4.1 KB) [[attachment:RSSReader-1.py]]
  • [get | view] (2010-06-03 17:14:44, 8.4 KB) [[attachment:RSSReader-2.0.py]]
  • [get | view] (2010-06-03 17:06:24, 35.2 KB) [[attachment:RSSReader.png]]
  • [get | view] (2012-12-30 22:16:51, 9.5 KB) [[attachment:RSSReader.py]]
 All files | Selected Files: delete move to page copy to page

You are not allowed to attach a file to this page.