plugin XEP-0313: improvments to prepare MUC MAM:

- discard groupchat message when retrieving last stanza_id on connection
- service can be specified in getMessageFromResult
- service is also used when using getArchives from bridge
This commit is contained in:
Goffi 2018-12-07 17:43:43 +01:00
commit 6bb1b599ab

View file

@ -71,18 +71,17 @@ class XEP_0313(object):
@defer.inlineCallbacks
def profileConnected(self, client):
last_mess = yield self.host.memory.historyGet(
None, None, limit=1, filters={u'last_stanza_id': True},
None, None, limit=1, filters={u'not_types': C.MESS_TYPE_GROUPCHAT,
u'last_stanza_id': True},
profile=client.profile)
if not last_mess:
log.info(_(u"It seems that we have no MAM history yet"))
return
stanza_id = last_mess[0][-1][u'stanza_id']
# XXX: test
# stanza_id = "IIheJOfiIhkPYkw6"
rsm_req = rsm.RSMRequest(after=stanza_id)
mam_req = mam.MAMRequest(rsm_=rsm_req)
mam_data = yield self.getArchives(client, mam_req,
service=client.jid.userhostJID())
service=client.jid.userhostJID())
elt_list, rsm_response = mam_data
if not elt_list:
log.info(_(u"We have received no message while offline"))
@ -154,21 +153,28 @@ class XEP_0313(object):
return mam.MAMRequest(**mam_args) if mam_args else None
def getMessageFromResult(self, client, mess_elt, mam_req):
def getMessageFromResult(self, client, mess_elt, mam_req, service=None):
"""Extract usable <message/> from MAM query result
The message will be validated, and stanza-id/delay will be added if necessary.
@param mess_elt(domish.Element): result <message/> element wrapping the message
to retrieve
@param mam_req(mam.MAMRequest): request used
@param service(jid.JID, None): MAM service where the request has been sent
None if it's user server
@return (domish.Element): <message/> that can be used directly with onMessage
"""
if mess_elt.name != u"message":
log.warning(u"unexpected stanza in archive: {xml}".format(
xml=mess_elt.toXml()))
raise exceptions.DataError(u"Invalid element")
service_jid = client.jid.userhostJID() if service is None else service
mess_from = mess_elt[u"from"]
if mess_from != client.jid.host and mess_from != client.jid.userhost():
# we check that the message has been sent by the right service
# if service is None (i.e. message expected from our own server)
# from can be server jid or user's bare jid
if (mess_from != service_jid.full()
and not (service is None and mess_from == client.jid.host)):
log.error(u"Message is not from our server, something went wrong: "
u"{xml}".format(xml=mess_elt.toXml()))
raise exceptions.DataError(u"Invalid element")
@ -191,7 +197,7 @@ class XEP_0313(object):
.format(query_id=mam.query_id, xml=mess_elt.toXml()))
raise exceptions.DataError(u"Invalid element")
stanza_id = self._sid.getStanzaId(fwd_message_elt,
client.jid.userhostJID())
service_jid)
if stanza_id is None:
# not stanza-id element is present, we add one so message
# will be archived with it, and we won't request several times
@ -202,7 +208,7 @@ class XEP_0313(object):
log.warning(u'Invalid MAM result: missing "id" attribute: {xml}'
.format(xml=result_elt.toXml()))
raise exceptions.DataError(u"Invalid element")
self._sid.addStanzaId(client, fwd_message_elt, stanza_id)
self._sid.addStanzaId(client, fwd_message_elt, stanza_id, by=service_jid)
if delay_elt is not None:
fwd_message_elt.addChild(delay_elt)
@ -247,11 +253,12 @@ class XEP_0313(object):
return (elt_list, rsm_response)
def serializeArchiveResult(self, data, client, mam_req):
def serializeArchiveResult(self, data, client, mam_req, service):
elt_list, rsm_response = data
mess_list = []
for elt in elt_list:
fwd_message_elt = self.getMessageFromResult(client, elt, mam_req)
fwd_message_elt = self.getMessageFromResult(client, elt, mam_req,
service=service)
mess_data = client.messageProt.parseMessage(fwd_message_elt)
mess_list.append(client.messageGetBridgeArgs(mess_data))
return mess_list, client.profile
@ -263,7 +270,7 @@ class XEP_0313(object):
mam_req = self.parseExtra(extra)
d = self.getArchives(client, mam_req, service=service)
d.addCallback(self.serializeArchiveResult, client, mam_req)
d.addCallback(self.serializeArchiveResult, client, mam_req, service)
return d
def getArchives(self, client, query, service=None, message_cb=None):