From acf281a46ae1f6f91bd648aceac99ef8dd1bf6b3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mike=20F=C3=A4hrmann?= Date: Thu, 27 Nov 2025 19:19:29 +0100 Subject: [PATCH] [twitter] implement 'retries-api' option (#8317) retry API requests when encountering server-related errors --- docs/configuration.rst | 12 ++++++++++++ docs/gallery-dl.conf | 1 + gallery_dl/extractor/twitter.py | 26 +++++++++++++++++++++++--- 3 files changed, 36 insertions(+), 3 deletions(-) diff --git a/docs/configuration.rst b/docs/configuration.rst index 873c5fe6..2dd79b09 100644 --- a/docs/configuration.rst +++ b/docs/configuration.rst @@ -6294,6 +6294,18 @@ Note `__. +extractor.twitter.retries-api +----------------------------- +Type + ``integer`` +Default + ``4`` +Description + Maximum number of retries + for API requests when encountering server ``errors``, + or ``-1`` for infinite retries. + + extractor.twitter.retweets -------------------------- Type diff --git a/docs/gallery-dl.conf b/docs/gallery-dl.conf index 561f7963..263ed1df 100644 --- a/docs/gallery-dl.conf +++ b/docs/gallery-dl.conf @@ -877,6 +877,7 @@ "quoted" : false, "ratelimit" : "wait", "replies" : true, + "retries-api" : 4, "retweets" : false, "search-limit": 20, "search-pagination": "cursor", diff --git a/gallery_dl/extractor/twitter.py b/gallery_dl/extractor/twitter.py index b091d188..b76a49c9 100644 --- a/gallery_dl/extractor/twitter.py +++ b/gallery_dl/extractor/twitter.py @@ -1902,14 +1902,14 @@ class TwitterAPI(): while True: params["variables"] = self._json_dumps(variables) - data = self._call(endpoint, params)["data"] + data = self._call(endpoint, params) try: if path is None: - instructions = (data["user"]["result"]["timeline"] + instructions = (data["data"]["user"]["result"]["timeline"] ["timeline"]["instructions"]) else: - instructions = data + instructions = data["data"] for key in path: instructions = instructions[key] instructions = instructions["instructions"] @@ -1940,6 +1940,26 @@ class TwitterAPI(): except LookupError: extr.log.debug(data) + if errors := data.get("errors"): + if "api_retries" not in locals(): + api_tries = 1 + api_retries = extr.config("retries-api", 4) + if api_retries < 0: + api_retries = float("inf") + + err = [] + srv = False + for e in errors: + err.append(f"- '{e.get('message') or e.get('name')}'") + if e.get("source") == "Server": + srv = True + + self.log.warning("API errors (%s/%s):\n%s", + api_tries, api_retries+1, "\n".join(err)) + if srv and api_tries <= api_retries: + api_tries += 1 + continue + if user := extr._user_obj: user = user["legacy"] if user.get("blocked_by"):