plugin XEP-0277, groupblog: fixes namespace issue of the items that are received from an event + trap some errors
This commit is contained in:
parent
be4fda30dd
commit
97630ccab9
2 changed files with 48 additions and 54 deletions
|
|
@ -212,25 +212,27 @@ class GroupBlog(object):
|
|||
return False
|
||||
return True
|
||||
|
||||
@defer.inlineCallbacks
|
||||
def _handleCommentsItems(self, items, service, node_identifier):
|
||||
""" Convert comments items to groupblog data, and send them as signals
|
||||
@param items: comments items
|
||||
@param service: jid of the PubSub service used
|
||||
@param node_identifier: comments node
|
||||
@return: list of group blog data
|
||||
@return: deferred list of group blog data
|
||||
"""
|
||||
ret = []
|
||||
for item in items:
|
||||
d_list = []
|
||||
|
||||
def cb(microblog_data):
|
||||
publisher = "" # FIXME: publisher attribute for item in SàT pubsub is not managed yet, so
|
||||
# publisher is not checked and can be easily spoofed. This need to be fixed
|
||||
# quickly.
|
||||
microblog_data = yield self.item2gbdata(item, "comment")
|
||||
microblog_data["service"] = service.userhost()
|
||||
microblog_data["node"] = node_identifier
|
||||
microblog_data["verified_publisher"] = "true" if publisher else "false"
|
||||
ret.append(microblog_data)
|
||||
defer.returnValue(ret)
|
||||
return microblog_data
|
||||
|
||||
for item in items:
|
||||
d_list.append(self.item2gbdata(item, "comment").addCallback(cb))
|
||||
return defer.DeferredList(d_list, consumeErrors=True).addCallback(lambda result: [value for (success, value) in result if success])
|
||||
|
||||
def _parseAccessData(self, microblog_data, item):
|
||||
P = self.host.plugins["XEP-0060"]
|
||||
|
|
@ -477,8 +479,6 @@ class GroupBlog(object):
|
|||
|
||||
return self._initialise(profile_key).addCallback(initialised)
|
||||
|
||||
|
||||
@defer.inlineCallbacks
|
||||
def _itemsConstruction(self, items, pub_jid, client):
|
||||
""" Transforms items to group blog data and manage comments node
|
||||
|
||||
|
|
@ -487,29 +487,33 @@ class GroupBlog(object):
|
|||
@param client: SatXMPPClient instance
|
||||
@return: deferred which fire list of group blog data """
|
||||
# TODO: use items data when pub_jid is None
|
||||
ret = []
|
||||
for item in items:
|
||||
gbdata = yield self.item2gbdata(item)
|
||||
d_list = []
|
||||
|
||||
@defer.inlineCallbacks
|
||||
def cb(gbdata):
|
||||
try:
|
||||
gbdata['service'] = client.item_access_pubsub.full()
|
||||
except AttributeError:
|
||||
pass
|
||||
ret.append(gbdata)
|
||||
log.warning(_("Pubsub service is unknown for blog entry %s") % gbdata['id'])
|
||||
# every comments node must be subscribed, except if we are the publisher (we are already subscribed in this case)
|
||||
if "comments_node" in gbdata and pub_jid.userhostJID() != client.jid.userhostJID():
|
||||
try:
|
||||
service = jid.JID(gbdata["comments_service"])
|
||||
node = gbdata["comments_node"]
|
||||
except KeyError:
|
||||
log.warning("Missing key for comments")
|
||||
continue
|
||||
log.error(_("Missing key for blog comment %s") % gbdata['id'])
|
||||
defer.returnValue(gbdata)
|
||||
# TODO: see if it is really needed to check for not subscribing twice to the node
|
||||
# It previously worked without this check, but the pubsub service logs were polluted
|
||||
# or, if in debug mode, it made sat-pubsub very difficult to debug.
|
||||
subscribed_nodes = yield self.host.plugins['XEP-0060'].listSubscribedNodes(service, profile=client.profile)
|
||||
if node not in subscribed_nodes: # avoid sat-pubsub "SubscriptionExists" error
|
||||
self.host.plugins["XEP-0060"].subscribe(service, node, profile_key=client.profile)
|
||||
defer.returnValue(ret)
|
||||
defer.returnValue(gbdata)
|
||||
|
||||
for item in items:
|
||||
d_list.append(self.item2gbdata(item).addCallback(cb))
|
||||
return defer.DeferredList(d_list, consumeErrors=True).addCallback(lambda result: [value for (success, value) in result if success])
|
||||
|
||||
def __getGroupBlogs(self, pub_jid_s, max_items=10, item_ids=None, profile_key=C.PROF_KEY_NONE):
|
||||
"""Retrieve previously published items from a publish subscribe node.
|
||||
|
|
|
|||
|
|
@ -112,26 +112,30 @@ class XEP_0277(object):
|
|||
@return: microblog data (dictionary)"""
|
||||
|
||||
def xpath(elt, path):
|
||||
"""Return the XPATH result of an entry element or its descendance, works with both:
|
||||
- no namespace, that means it is inherited from the parent item node --> NS_PUBSUB
|
||||
- empty namespace
|
||||
XXX: check why the received entries have no namespace when they are retrieved
|
||||
from self.host.plugins["XEP-0060"].getItems and they have an empty namespace
|
||||
when they are received with an event.
|
||||
"""
|
||||
result = elt.xpath(path)
|
||||
if len(result) > 0:
|
||||
return result
|
||||
return elt.xpath('/'.join(['ns:%s' % tag for tag in path.split('/')]), namespaces={'ns': NS_PUBSUB})
|
||||
"""Return the XPATH result of an entry element or its descendance."""
|
||||
# XXX: use a wildcard to work with all and even undefined namespaces
|
||||
return elt.xpath('/'.join(["*[local-name() = '%s']" % tag for tag in path.split('/')]))
|
||||
|
||||
# convert a date string to float without dealing with the date format
|
||||
date2float = lambda elt, path: unicode(date.rfc3339.tf_from_timestamp(xpath(elt, path)[0].text))
|
||||
def date2float(elt, path):
|
||||
"""Convert a date string to float without dealing with the date format."""
|
||||
return unicode(date.rfc3339.tf_from_timestamp(xpath(elt, path)[0].text))
|
||||
|
||||
item_elt = etree.fromstring(item.toXml().encode('utf-8'))
|
||||
item_id = item_elt.get('id', '')
|
||||
|
||||
# XXX: when you raise an exception from inline callbacks, do defer.returnValue(Exception())
|
||||
# to make it catchable by an eventual errback. If you do raise Exception, raise Exception()
|
||||
# or defer.returnValue(Exception), it will explode and then the normal callback is ran.
|
||||
|
||||
if item.uri not in (NS_PUBSUB, NS_PUBSUB + "#event"):
|
||||
log.error(_("Unsupported namespace {ns} in pubsub item {id}").format(ns=item.uri, id=item_id))
|
||||
defer.returnValue(exceptions.DataError())
|
||||
|
||||
try:
|
||||
entry_elt = xpath(item_elt, 'entry')[0]
|
||||
except IndexError:
|
||||
raise exceptions.DataError(_('No entry found in the pubsub item %s') % item_elt.get('id', ''))
|
||||
log.error(_('No atom entry found in the pubsub item %s') % item_id)
|
||||
defer.returnValue(exceptions.DataError())
|
||||
|
||||
microblog_data = {}
|
||||
|
||||
|
|
@ -154,8 +158,8 @@ class XEP_0277(object):
|
|||
microblog_data['updated'] = date2float(entry_elt, 'updated')
|
||||
assert('title' in microblog_data) # has been processed already
|
||||
except IndexError:
|
||||
log.error(_("Atom entry %s misses a required element") % item_elt.get('id', ''))
|
||||
raise exceptions.DataError
|
||||
log.error(_("Atom entry of pubsub item %s misses a required element") % item_id)
|
||||
defer.returnValue(exceptions.DataError())
|
||||
|
||||
if 'content' not in microblog_data: # use the atom title data as the microblog body content
|
||||
microblog_data['content'] = microblog_data['title']
|
||||
|
|
@ -180,7 +184,7 @@ class XEP_0277(object):
|
|||
microblog_data['comments_service'] = service.full()
|
||||
microblog_data['comments_node'] = node
|
||||
except (exceptions.DataError, RuntimeError, KeyError):
|
||||
log.warning(_("Can't parse the link element of pubsub entry %s") % microblog_data['id'])
|
||||
log.warning(_("Can't parse the link element of atom entry %s") % microblog_data['id'])
|
||||
except:
|
||||
pass
|
||||
try:
|
||||
|
|
@ -189,7 +193,7 @@ class XEP_0277(object):
|
|||
try: # XXX: workaround for Jappix behaviour
|
||||
microblog_data['author'] = xpath(entry_elt, 'author/nick')[0].text
|
||||
except IndexError:
|
||||
log.warning(_("Can't find author element in pubsub entry %s") % microblog_data['id'])
|
||||
log.warning(_("Can't find author element in atom entry %s") % microblog_data['id'])
|
||||
|
||||
defer.returnValue(microblog_data)
|
||||
|
||||
|
|
@ -221,17 +225,12 @@ class XEP_0277(object):
|
|||
return self.__getDomishInnerContent(elt)
|
||||
|
||||
def microblogCB(self, itemsEvent, profile):
|
||||
d = defer.Deferred()
|
||||
|
||||
"""Callback to "MICROBLOG" PEP event."""
|
||||
def manageItem(microblog_data):
|
||||
self.host.bridge.personalEvent(itemsEvent.sender.full(), "MICROBLOG", microblog_data, profile)
|
||||
|
||||
for item in itemsEvent.items:
|
||||
d.addCallback(lambda ignore: self.item2mbdata(item))
|
||||
d.addCallback(manageItem)
|
||||
|
||||
d.callback(None)
|
||||
return d
|
||||
self.item2mbdata(item).addCallbacks(manageItem, lambda failure: None)
|
||||
|
||||
@defer.inlineCallbacks
|
||||
def data2entry(self, data, profile):
|
||||
|
|
@ -317,18 +316,9 @@ class XEP_0277(object):
|
|||
@param max_items: how many microblogs we want to get
|
||||
@param profile_key: profile key
|
||||
"""
|
||||
def resultToArray(result):
|
||||
ret = []
|
||||
for (success, value) in result:
|
||||
if success:
|
||||
ret.append(value)
|
||||
else:
|
||||
log.error('Error while getting last microblog')
|
||||
return ret
|
||||
|
||||
d = self.host.plugins["XEP-0060"].getItems(jid.JID(pub_jid), NS_MICROBLOG, max_items=max_items, profile_key=profile_key)
|
||||
d.addCallback(lambda items: defer.DeferredList(map(self.item2mbdata, items)))
|
||||
d.addCallback(resultToArray)
|
||||
d.addCallback(lambda items: defer.DeferredList(map(self.item2mbdata, items), consumeErrors=True))
|
||||
d.addCallback(lambda result: [value for (success, value) in result if success])
|
||||
return d
|
||||
|
||||
def setMicroblogAccess(self, access="presence", profile_key=C.PROF_KEY_NONE):
|
||||
|
|
|
|||
Loading…
Reference in a new issue