diff libervia/backend/plugins/plugin_xep_0313.py @ 4154:85f5e6225aa1

plugin XEP-0313: better error logging + store last stanza ID when retrieving archives + small improvments
author Goffi <goffi@goffi.org>
date Wed, 22 Nov 2023 14:56:14 +0100
parents 4b842c1fb686
children 1c30d574df2b
line wrap: on
line diff
--- a/libervia/backend/plugins/plugin_xep_0313.py	Wed Nov 22 14:53:07 2023 +0100
+++ b/libervia/backend/plugins/plugin_xep_0313.py	Wed Nov 22 14:56:14 2023 +0100
@@ -18,23 +18,25 @@
 # You should have received a copy of the GNU Affero General Public License
 # along with this program.  If not, see <http://www.gnu.org/licenses/>.
 
+from datetime import datetime
+import uuid
+
+from dateutil import tz
+from twisted.internet import defer
+from twisted.words.protocols.jabber import jid
+from twisted.words.protocols.jabber.error import StanzaError
+from wokkel import disco
+from wokkel import data_form
+from wokkel import rsm
+from wokkel import mam
+from zope.interface import implementer
+
+from libervia.backend.core import exceptions
 from libervia.backend.core.constants import Const as C
 from libervia.backend.core.i18n import _
 from libervia.backend.core.log import getLogger
-from libervia.backend.core import exceptions
+from libervia.backend.tools import xml_tools
 from libervia.backend.tools.common import data_format
-from twisted.words.protocols.jabber import jid
-from twisted.internet import defer
-from zope.interface import implementer
-from datetime import datetime
-from dateutil import tz
-from wokkel import disco
-from wokkel import data_form
-import uuid
-
-# XXX: mam and rsm come from sat_tmp.wokkel
-from wokkel import rsm
-from wokkel import mam
 
 
 log = getLogger(__name__)
@@ -99,8 +101,21 @@
         complete = False
         count = 0
         while not complete:
-            mam_data = await self.get_archives(client, mam_req,
-                                              service=client.jid.userhostJID())
+            try:
+                mam_data = await self.get_archives(client, mam_req,
+                                                  service=client.jid.userhostJID())
+            except StanzaError as e:
+                log.warning(
+                    f"Can't retrieve MAM archives: {e}\n"
+                    f"{xml_tools.pp_elt(mam_req.toElement())}\n"
+                    f"{xml_tools.pp_elt(e.stanza)}"
+                )
+                return
+            except Exception as e:
+                log.exception(
+                    f"Can't retrieve retrieve MAM archive"
+                )
+                return
             elt_list, rsm_response, mam_response = mam_data
             complete = mam_response["complete"]
             # we update MAM request for next iteration
@@ -112,7 +127,7 @@
             else:
                 count += len(elt_list)
 
-            for mess_elt in elt_list:
+            for idx, mess_elt in enumerate(elt_list):
                 try:
                     fwd_message_elt = self.get_message_from_result(
                         client, mess_elt, mam_req)
@@ -152,6 +167,19 @@
                         log.error(
                             "can't add message to history: {e}\n{xml}"
                             .format(e=e, xml=mess_elt.toXml()))
+                    if complete and idx == len(elt_list) - 1:
+                        # We are at the last message from archive, we store the ID to not
+                        # ask again the same messages next time.
+                        try:
+                            stanza_id = mess_elt.result["id"]
+                            await self.host.memory.storage.set_private_value(
+                                namespace=mam.NS_MAM,
+                                key=KEY_LAST_STANZA_ID,
+                                value=stanza_id,
+                                profile=client.profile
+                            )
+                        except Exception:
+                            log.exception("Can't store last stanza ID")
 
         if not count:
             log.info(_("We have received no message while offline"))
@@ -163,7 +191,7 @@
         defer.ensureDeferred(self.resume(client))
 
     def get_handler(self, client):
-        mam_client = client._mam = SatMAMClient(self)
+        mam_client = client._mam = LiberviaMAMClient(self)
         return mam_client
 
     def parse_extra(self, extra, with_rsm=True):
@@ -240,7 +268,7 @@
                 xml=mess_elt.toXml()))
             raise exceptions.DataError("Invalid element")
         service_jid = client.jid.userhostJID() if service is None else service
-        mess_from = mess_elt["from"]
+        mess_from = mess_elt.getAttribute("from") or client.jid.userhostJID()
         # 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
@@ -420,6 +448,9 @@
         to retrieve missing history on next connection
         @param message_elt(domish.Element): <message> with a stanza-id
         """
+        if message_elt.getAttribute("type") == C.MESS_TYPE_GROUPCHAT:
+            # groupchat message MAM is handled by XEP-0045
+            return
         service_jid = client.jid.userhostJID()
         stanza_id = self._sid.get_stanza_id(message_elt, service_jid)
         if stanza_id is None:
@@ -436,7 +467,7 @@
 
 
 @implementer(disco.IDisco)
-class SatMAMClient(mam.MAMClient):
+class LiberviaMAMClient(mam.MAMClient):
 
     def __init__(self, plugin_parent):
         self.plugin_parent = plugin_parent