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