changeset 3592:ef144aaea2bb

plugin XEP-0059: new `getNextRequest` method to generate request to retrieve next page
author Goffi <goffi@goffi.org>
date Thu, 29 Jul 2021 21:30:32 +0200
parents d830c11eeef3
children cb8d0e8b917f
files sat/plugins/plugin_xep_0059.py
diffstat 1 files changed, 53 insertions(+), 9 deletions(-) [+]
line wrap: on
line diff
--- a/sat/plugins/plugin_xep_0059.py	Thu Jul 29 21:28:48 2021 +0200
+++ b/sat/plugins/plugin_xep_0059.py	Thu Jul 29 21:30:32 2021 +0200
@@ -1,7 +1,6 @@
 #!/usr/bin/env python3
 
-
-# SAT plugin for Result Set Management (XEP-0059)
+# Result Set Management (XEP-0059)
 # Copyright (C) 2009-2021 Jérôme Poisson (goffi@goffi.org)
 # Copyright (C) 2013-2016 Adrien Cossa (souliane@mailoo.org)
 
@@ -18,19 +17,19 @@
 # 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 typing import Optional
+from zope.interface import implementer
+from twisted.words.protocols.jabber import xmlstream
+from wokkel import disco
+from wokkel import iwokkel
+from wokkel import rsm
 from sat.core.i18n import _
 from sat.core.constants import Const as C
 from sat.core.log import getLogger
 
+
 log = getLogger(__name__)
 
-from wokkel import disco
-from wokkel import iwokkel
-from wokkel import rsm
-
-from twisted.words.protocols.jabber import xmlstream
-from zope.interface import implementer
-
 
 PLUGIN_INFO = {
     C.PI_NAME: "Result Set Management",
@@ -102,6 +101,51 @@
             data["index"] = rsm_response.index
         return data
 
+    def getNextRequest(
+        self,
+        rsm_request: rsm.RSMRequest,
+        rsm_response: rsm.RSMResponse,
+        log_progress: bool = True,
+    ) -> Optional[rsm.RSMRequest]:
+        """Generate next request to paginate through all items
+
+        Page will be retrieved forward
+        @param rsm_request: last request used
+        @param rsm_response: response from the last request
+        @return: request to retrive next page, or None if we are at the end
+            or if pagination is not possible
+        """
+        if rsm_request.max == 0:
+            log.warning("Can't do pagination if max is 0")
+            return None
+        if rsm_response is None:
+            # may happen if result set it empty, or we are at the end
+            return None
+        if (
+            rsm_response.count is not None
+            and rsm_response.index is not None
+        ):
+            next_index = rsm_response.index + rsm_request.max
+            if next_index >= rsm_response.count:
+                # we have reached the last page
+                return None
+
+            if log_progress:
+                log.debug(
+                    f"retrieving items {next_index} to "
+                    f"{min(next_index+rsm_request.max, rsm_response.count)} on "
+                    f"{rsm_response.count} ({next_index/rsm_response.count*100:.2f}%)"
+                )
+
+        if rsm_response.last is None:
+            log.warning("Can't do pagination, no \"last\" received")
+            return None
+
+        return rsm.RSMRequest(
+            max_=rsm_request.max,
+            after=rsm_response.last
+        )
+
 
 @implementer(iwokkel.IDisco)
 class XEP_0059_handler(xmlstream.XMPPHandler):