1 # -*- coding: iso-8859-1 -*- 2 """ 3 MoinMoin - SharedContent macro, based on the FeedReader macro 4 5 @copyright: 2008, 2012 by Paul Boddie <paul@boddie.org.uk> 6 @license: GNU GPL (v2 or later), see COPYING.txt for details. 7 """ 8 9 from MoinMoin.Page import Page 10 import urllib 11 import xml.dom.pulldom 12 13 Dependencies = ["time"] 14 15 MAX_ENTRIES = 5 16 ATOM_NS = "http://www.w3.org/2005/Atom" 17 18 def text(element): 19 nodes = [] 20 for node in element.childNodes: 21 if node.nodeType == node.TEXT_NODE: 22 nodes.append(node.nodeValue) 23 return "".join(nodes) 24 25 def linktext(element, feed_type): 26 if feed_type == "rss": 27 return text(element) 28 else: 29 return element.getAttribute("href") 30 31 def execute(macro, args): 32 request = macro.request 33 fmt = macro.formatter 34 35 max_entries = MAX_ENTRIES 36 args = args.split(",") 37 if args: 38 try: 39 feed_url = args[0] 40 max_entries = int(args[1]) 41 except IndexError: 42 pass 43 44 # Obtain the feed. 45 46 feed = urllib.urlopen(feed_url) 47 48 try: 49 # Parse each node from the feed. 50 51 title = link = None 52 channel_title = channel_link = None 53 54 output = [] 55 append = output.append 56 append(fmt.bullet_list(on=1)) 57 58 feed_type = None 59 in_item = False 60 nentries = 0 61 62 events = xml.dom.pulldom.parse(feed) 63 64 for event, value in events: 65 66 if event == xml.dom.pulldom.START_ELEMENT: 67 tagname = value.localName 68 69 # Detect the feed type and items. 70 71 if tagname == "feed" and value.namespaceURI == ATOM_NS: 72 feed_type = "atom" 73 74 elif tagname == "rss": 75 feed_type = "rss" 76 77 # Detect items. 78 79 elif feed_type == "rss" and tagname == "item" or \ 80 feed_type == "atom" and tagname == "entry": 81 82 in_item = True 83 84 elif tagname == "title": 85 events.expandNode(value) 86 if in_item: 87 title = value 88 else: 89 channel_title = value 90 91 elif tagname == "link": 92 events.expandNode(value) 93 if in_item: 94 link = value 95 else: 96 channel_link = value 97 98 elif event == xml.dom.pulldom.END_ELEMENT: 99 tagname = value.localName 100 101 if feed_type == "rss" and tagname == "item" or \ 102 feed_type == "atom" and tagname == "entry": 103 104 in_item = False 105 106 # Emit title and link information for items. 107 108 if title and link and nentries < max_entries: 109 link_text = linktext(link, feed_type) 110 111 append(fmt.listitem(on=1)) 112 append(fmt.url(on=1, href=link_text)) 113 append(fmt.icon('www')) 114 append(fmt.text(" " + text(title))) 115 append(fmt.url(on=0)) 116 append(fmt.listitem(on=0)) 117 118 title = link = None 119 nentries += 1 120 121 append(fmt.bullet_list(on=0)) 122 123 if channel_title and channel_link: 124 channel_link_text = linktext(channel_link, feed_type) 125 126 append(fmt.paragraph(on=1)) 127 append(fmt.url(on=1, href=channel_link_text)) 128 append(fmt.text(text(channel_title))) 129 append(fmt.url(on=0)) 130 append(fmt.text(" ")) 131 append(fmt.url(on=1, href=feed_url)) 132 append(fmt.icon('rss')) 133 append(fmt.url(on=0)) 134 append(fmt.paragraph(on=0)) 135 136 finally: 137 feed.close() 138 139 return ''.join(output) 140 141 # vim: tabstop=4 expandtab shiftwidth=4