Mercurial > libervia-backend
comparison src/plugins/plugin_xep_0277.py @ 1233:0b87d029f0a3
plugin XEP-0277, groupblog: fixes namespace issue of the items that are received from an event + trap some errors
author | souliane <souliane@mailoo.org> |
---|---|
date | Mon, 06 Oct 2014 17:25:41 +0200 |
parents | 301b342c697a |
children | bb30bf3ae932 |
comparison
equal
deleted
inserted
replaced
1232:6b10442e8920 | 1233:0b87d029f0a3 |
---|---|
110 """Convert an XML Item to microblog data used in bridge API | 110 """Convert an XML Item to microblog data used in bridge API |
111 @param item: domish.Element of microblog item | 111 @param item: domish.Element of microblog item |
112 @return: microblog data (dictionary)""" | 112 @return: microblog data (dictionary)""" |
113 | 113 |
114 def xpath(elt, path): | 114 def xpath(elt, path): |
115 """Return the XPATH result of an entry element or its descendance, works with both: | 115 """Return the XPATH result of an entry element or its descendance.""" |
116 - no namespace, that means it is inherited from the parent item node --> NS_PUBSUB | 116 # XXX: use a wildcard to work with all and even undefined namespaces |
117 - empty namespace | 117 return elt.xpath('/'.join(["*[local-name() = '%s']" % tag for tag in path.split('/')])) |
118 XXX: check why the received entries have no namespace when they are retrieved | 118 |
119 from self.host.plugins["XEP-0060"].getItems and they have an empty namespace | 119 def date2float(elt, path): |
120 when they are received with an event. | 120 """Convert a date string to float without dealing with the date format.""" |
121 """ | 121 return unicode(date.rfc3339.tf_from_timestamp(xpath(elt, path)[0].text)) |
122 result = elt.xpath(path) | |
123 if len(result) > 0: | |
124 return result | |
125 return elt.xpath('/'.join(['ns:%s' % tag for tag in path.split('/')]), namespaces={'ns': NS_PUBSUB}) | |
126 | |
127 # convert a date string to float without dealing with the date format | |
128 date2float = lambda elt, path: unicode(date.rfc3339.tf_from_timestamp(xpath(elt, path)[0].text)) | |
129 | 122 |
130 item_elt = etree.fromstring(item.toXml().encode('utf-8')) | 123 item_elt = etree.fromstring(item.toXml().encode('utf-8')) |
124 item_id = item_elt.get('id', '') | |
125 | |
126 # XXX: when you raise an exception from inline callbacks, do defer.returnValue(Exception()) | |
127 # to make it catchable by an eventual errback. If you do raise Exception, raise Exception() | |
128 # or defer.returnValue(Exception), it will explode and then the normal callback is ran. | |
129 | |
130 if item.uri not in (NS_PUBSUB, NS_PUBSUB + "#event"): | |
131 log.error(_("Unsupported namespace {ns} in pubsub item {id}").format(ns=item.uri, id=item_id)) | |
132 defer.returnValue(exceptions.DataError()) | |
133 | |
131 try: | 134 try: |
132 entry_elt = xpath(item_elt, 'entry')[0] | 135 entry_elt = xpath(item_elt, 'entry')[0] |
133 except IndexError: | 136 except IndexError: |
134 raise exceptions.DataError(_('No entry found in the pubsub item %s') % item_elt.get('id', '')) | 137 log.error(_('No atom entry found in the pubsub item %s') % item_id) |
138 defer.returnValue(exceptions.DataError()) | |
135 | 139 |
136 microblog_data = {} | 140 microblog_data = {} |
137 | 141 |
138 for key in ['title', 'content']: # process the textual elements | 142 for key in ['title', 'content']: # process the textual elements |
139 for attr_elt in xpath(entry_elt, key): | 143 for attr_elt in xpath(entry_elt, key): |
152 try: # check for mandatory elements | 156 try: # check for mandatory elements |
153 microblog_data['id'] = xpath(entry_elt, 'id')[0].text | 157 microblog_data['id'] = xpath(entry_elt, 'id')[0].text |
154 microblog_data['updated'] = date2float(entry_elt, 'updated') | 158 microblog_data['updated'] = date2float(entry_elt, 'updated') |
155 assert('title' in microblog_data) # has been processed already | 159 assert('title' in microblog_data) # has been processed already |
156 except IndexError: | 160 except IndexError: |
157 log.error(_("Atom entry %s misses a required element") % item_elt.get('id', '')) | 161 log.error(_("Atom entry of pubsub item %s misses a required element") % item_id) |
158 raise exceptions.DataError | 162 defer.returnValue(exceptions.DataError()) |
159 | 163 |
160 if 'content' not in microblog_data: # use the atom title data as the microblog body content | 164 if 'content' not in microblog_data: # use the atom title data as the microblog body content |
161 microblog_data['content'] = microblog_data['title'] | 165 microblog_data['content'] = microblog_data['title'] |
162 del microblog_data['title'] | 166 del microblog_data['title'] |
163 if 'title_xhtml' in microblog_data: | 167 if 'title_xhtml' in microblog_data: |
178 microblog_data['comments'] = link_elt.attrib['href'] | 182 microblog_data['comments'] = link_elt.attrib['href'] |
179 service, node = self.parseCommentUrl(microblog_data["comments"]) | 183 service, node = self.parseCommentUrl(microblog_data["comments"]) |
180 microblog_data['comments_service'] = service.full() | 184 microblog_data['comments_service'] = service.full() |
181 microblog_data['comments_node'] = node | 185 microblog_data['comments_node'] = node |
182 except (exceptions.DataError, RuntimeError, KeyError): | 186 except (exceptions.DataError, RuntimeError, KeyError): |
183 log.warning(_("Can't parse the link element of pubsub entry %s") % microblog_data['id']) | 187 log.warning(_("Can't parse the link element of atom entry %s") % microblog_data['id']) |
184 except: | 188 except: |
185 pass | 189 pass |
186 try: | 190 try: |
187 microblog_data['author'] = xpath(entry_elt, 'author/name')[0].text | 191 microblog_data['author'] = xpath(entry_elt, 'author/name')[0].text |
188 except IndexError: | 192 except IndexError: |
189 try: # XXX: workaround for Jappix behaviour | 193 try: # XXX: workaround for Jappix behaviour |
190 microblog_data['author'] = xpath(entry_elt, 'author/nick')[0].text | 194 microblog_data['author'] = xpath(entry_elt, 'author/nick')[0].text |
191 except IndexError: | 195 except IndexError: |
192 log.warning(_("Can't find author element in pubsub entry %s") % microblog_data['id']) | 196 log.warning(_("Can't find author element in atom entry %s") % microblog_data['id']) |
193 | 197 |
194 defer.returnValue(microblog_data) | 198 defer.returnValue(microblog_data) |
195 | 199 |
196 def __getLXMLInnerContent(self, elt): | 200 def __getLXMLInnerContent(self, elt): |
197 """Return the inner content of a lxml.etree.Element. It is not | 201 """Return the inner content of a lxml.etree.Element. It is not |
219 if elt.uri != NS_XHTML: | 223 if elt.uri != NS_XHTML: |
220 raise exceptions.DataError(_('Content of type XHTML must declare its namespace!')) | 224 raise exceptions.DataError(_('Content of type XHTML must declare its namespace!')) |
221 return self.__getDomishInnerContent(elt) | 225 return self.__getDomishInnerContent(elt) |
222 | 226 |
223 def microblogCB(self, itemsEvent, profile): | 227 def microblogCB(self, itemsEvent, profile): |
224 d = defer.Deferred() | 228 """Callback to "MICROBLOG" PEP event.""" |
225 | |
226 def manageItem(microblog_data): | 229 def manageItem(microblog_data): |
227 self.host.bridge.personalEvent(itemsEvent.sender.full(), "MICROBLOG", microblog_data, profile) | 230 self.host.bridge.personalEvent(itemsEvent.sender.full(), "MICROBLOG", microblog_data, profile) |
228 | 231 |
229 for item in itemsEvent.items: | 232 for item in itemsEvent.items: |
230 d.addCallback(lambda ignore: self.item2mbdata(item)) | 233 self.item2mbdata(item).addCallbacks(manageItem, lambda failure: None) |
231 d.addCallback(manageItem) | |
232 | |
233 d.callback(None) | |
234 return d | |
235 | 234 |
236 @defer.inlineCallbacks | 235 @defer.inlineCallbacks |
237 def data2entry(self, data, profile): | 236 def data2entry(self, data, profile): |
238 """Convert a data dict to en entry usable to create an item | 237 """Convert a data dict to en entry usable to create an item |
239 @param data: data dict as given by bridge method. | 238 @param data: data dict as given by bridge method. |
315 """Get the last published microblogs | 314 """Get the last published microblogs |
316 @param pub_jid: jid of the publisher | 315 @param pub_jid: jid of the publisher |
317 @param max_items: how many microblogs we want to get | 316 @param max_items: how many microblogs we want to get |
318 @param profile_key: profile key | 317 @param profile_key: profile key |
319 """ | 318 """ |
320 def resultToArray(result): | |
321 ret = [] | |
322 for (success, value) in result: | |
323 if success: | |
324 ret.append(value) | |
325 else: | |
326 log.error('Error while getting last microblog') | |
327 return ret | |
328 | |
329 d = self.host.plugins["XEP-0060"].getItems(jid.JID(pub_jid), NS_MICROBLOG, max_items=max_items, profile_key=profile_key) | 319 d = self.host.plugins["XEP-0060"].getItems(jid.JID(pub_jid), NS_MICROBLOG, max_items=max_items, profile_key=profile_key) |
330 d.addCallback(lambda items: defer.DeferredList(map(self.item2mbdata, items))) | 320 d.addCallback(lambda items: defer.DeferredList(map(self.item2mbdata, items), consumeErrors=True)) |
331 d.addCallback(resultToArray) | 321 d.addCallback(lambda result: [value for (success, value) in result if success]) |
332 return d | 322 return d |
333 | 323 |
334 def setMicroblogAccess(self, access="presence", profile_key=C.PROF_KEY_NONE): | 324 def setMicroblogAccess(self, access="presence", profile_key=C.PROF_KEY_NONE): |
335 """Create a microblog node on PEP with given access | 325 """Create a microblog node on PEP with given access |
336 If the node already exists, it change options | 326 If the node already exists, it change options |