1 # -*- coding: iso-8859-1 -*- 2 """ 3 MoinMoin - SharedContent macro, based on the FeedReader macro 4 5 @copyright: 2008, 2012, 2013, 2014 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 from MoinSupport import parseMacroArguments 11 from MoinShare import getUpdateSources, getUpdates, \ 12 getUpdatesFromPage, getUpdatesFromStore, \ 13 formatUpdate, Update 14 15 Dependencies = ["time"] 16 17 MAX_ENTRIES = 5 18 19 # The macro itself. 20 21 def execute(macro, args): 22 request = macro.request 23 fmt = macro.formatter 24 _ = request.getText 25 26 source_pages = [] 27 show_content = None 28 max_entries = None 29 30 for arg, value in parseMacroArguments(args): 31 if arg == "sources": 32 source_pages.append(value) 33 elif arg == "show": 34 show_content = value.lower() 35 elif arg == "limit": 36 try: 37 max_entries = int(value) 38 except ValueError: 39 return fmt.text(_("SharedContent: limit must be set to the maximum number of entries to be shown")) 40 41 if not source_pages: 42 return fmt.text(_("SharedContent: at least one sources page must be specified")) 43 44 sources = {} 45 46 for source_page in source_pages: 47 sources.update(getUpdateSources(source_page, request)) 48 49 if not sources: 50 return fmt.text(_("SharedContent: at least one update source must be specified")) 51 52 show_content = show_content or False 53 max_entries = max_entries or MAX_ENTRIES 54 55 # Retrieve updates, classifying them as missing or bad and excluding them if 56 # appropriate. 57 58 updates = [] 59 feeds = [] 60 unspecified = [] 61 missing = [] 62 bad_content = [] 63 64 for source_name, source_parameters in sources.items(): 65 location = source_parameters.get("location") 66 if not location: 67 unspecified.append(source_name) 68 continue 69 70 try: 71 max_entries_for_feed = int(source_parameters["limit"]) 72 except (KeyError, ValueError): 73 max_entries_for_feed = None 74 75 # Retrieve updates from feeds. 76 77 if source_parameters.get("type") == "url": 78 try: 79 feed_info, feed_updates = getUpdates(request, location, max_entries_for_feed, show_content) 80 updates += feed_updates 81 feeds.append((location, feed_info)) 82 except FeedMissingError: 83 missing.append(location) 84 except FeedContentTypeError: 85 bad_content.append(location) 86 87 # Retrieve updates from pages. 88 89 elif source_parameters.get("type") == "page": 90 page = Page(request, location) 91 updates += getUpdatesFromPage(page, request) 92 93 # Build feed-equivalent information for the update source. 94 95 feeds.append(( 96 page.url(request, {"action" : "SharedUpdates", "doit" : "1"}), ( 97 "internal", _("Updates from page %s") % location, 98 page.url(request) 99 ) 100 )) 101 102 # Retrieve updates from message stores. 103 104 elif source_parameters.get("type") == "store": 105 page = Page(request, location) 106 updates += getUpdatesFromStore(page, request) 107 108 # Build feed-equivalent information for the update source. 109 110 feeds.append(( 111 page.url(request, {"action" : "SharedUpdates", "store" : "1", "doit" : "1"}), ( 112 "internal", _("Updates from message store on page %s") % location, 113 page.url(request) 114 ) 115 )) 116 117 # Prepare the output. 118 119 output = [] 120 append = output.append 121 122 # Show the updates. 123 124 if not show_content: 125 append(fmt.bullet_list(on=1)) 126 127 # NOTE: Permit configurable sorting. 128 129 updates.sort() 130 updates.reverse() 131 132 # Truncate the number of updates to the maximum number. 133 134 updates = updates[:max_entries] 135 136 for update in updates: 137 138 # Emit content where appropriate. 139 140 if show_content: 141 append(fmt.div(on=1, css_class="moinshare-update")) 142 143 if update.author: 144 append(fmt.div(on=1, css_class="moinshare-author")) 145 append(fmt.text(update.author)) 146 append(fmt.div(on=0)) 147 148 append(formatUpdate(update, request, fmt)) 149 150 append(fmt.div(on=1, css_class="moinshare-date")) 151 append(fmt.text(str(update.updated))) 152 append(fmt.div(on=0)) 153 154 append(fmt.div(on=0)) 155 156 # Or emit title and link information for items. 157 158 elif update.title and update.link: 159 append(fmt.listitem(on=1, css_class="moinshare-update")) 160 append(fmt.url(on=1, href=update.link)) 161 append(fmt.icon('www')) 162 append(fmt.text(" " + update.title)) 163 append(fmt.url(on=0)) 164 append(fmt.listitem(on=0)) 165 166 if not show_content: 167 append(fmt.bullet_list(on=0)) 168 169 # Show the feeds. 170 171 for feed_url, (feed_type, channel_title, channel_link) in feeds: 172 if channel_title and channel_link: 173 append(fmt.paragraph(on=1, css_class="moinshare-feed")) 174 append(fmt.url(on=1, href=channel_link)) 175 append(fmt.text(channel_title)) 176 append(fmt.url(on=0)) 177 append(fmt.text(" ")) 178 append(fmt.url(on=1, href=feed_url)) 179 append(fmt.icon('rss')) 180 append(fmt.url(on=0)) 181 append(fmt.paragraph(on=0)) 182 183 # Show errors. 184 185 for feed_url in missing: 186 append(fmt.paragraph(on=1, css_class="moinshare-missing-feed-error")) 187 append(fmt.text(_("SharedContent: updates could not be retrieved for %s") % feed_url)) 188 append(fmt.paragraph(on=0)) 189 190 for feed_url in bad_content: 191 append(fmt.paragraph(on=1, css_class="moinshare-content-type-feed-error")) 192 return fmt.text(_("SharedContent: updates for %s were not provided in Atom or RSS format") % feed_url) 193 append(fmt.paragraph(on=0)) 194 195 return ''.join(output) 196 197 # vim: tabstop=4 expandtab shiftwidth=4