Skip to content

Commit

Permalink
[twitter] implement 'relogin' option (#5445)
Browse files Browse the repository at this point in the history
  • Loading branch information
mikf committed Apr 12, 2024
1 parent e02d2ff commit 85bbb59
Show file tree
Hide file tree
Showing 2 changed files with 62 additions and 36 deletions.
13 changes: 13 additions & 0 deletions docs/configuration.rst
Original file line number Diff line number Diff line change
Expand Up @@ -3916,6 +3916,19 @@ Description
* ``"wait"``: Wait until rate limit reset


extractor.twitter.relogin
-------------------------
Type
``bool``
Default
``true``
Description
| When receiving a "Could not authenticate you" error while logged in with
`username & passeword <extractor.*.username & .password_>`__,
| refresh the current login session and
try to continue from where it left off.

extractor.twitter.locked
------------------------
Type
Expand Down
85 changes: 49 additions & 36 deletions gallery_dl/extractor/twitter.py
Original file line number Diff line number Diff line change
Expand Up @@ -1294,42 +1294,62 @@ def _call(self, endpoint, params, method="GET", auth=True, root=None):
if csrf_token:
self.headers["x-csrf-token"] = csrf_token

if response.status_code < 400:
try:
data = response.json()
except ValueError:
data = {"errors": ({"message": response.text},)}

errors = data.get("errors")
if not errors:
return data

retry = False
for error in errors:
msg = error.get("message") or "Unspecified"
self.log.debug("API error: '%s'", msg)

if "this account is temporarily locked" in msg:
msg = "Account temporarily locked"
if self.extractor.config("locked") != "wait":
raise exception.AuthorizationError(msg)
self.log.warning("%s. Press ENTER to retry.", msg)
try:
input()
except (EOFError, OSError):
pass
retry = True

errors = data.get("errors")
if not errors:
return data
elif "Could not authenticate you" in msg:
if not self.extractor.config("relogin", True):
continue

retry = False
for error in errors:
msg = error.get("message") or "Unspecified"
self.log.debug("API error: '%s'", msg)
username, password = self.extractor._get_auth_info()
if not username:
continue

if "this account is temporarily locked" in msg:
msg = "Account temporarily locked"
if self.extractor.config("locked") != "wait":
raise exception.AuthorizationError(msg)
self.log.warning("%s. Press ENTER to retry.", msg)
try:
input()
except (EOFError, OSError):
pass
retry = True
_login_impl.invalidate(username)
self.extractor.cookies_update(
_login_impl(self.extractor, username, password))
self.__init__(self.extractor)
retry = True

elif msg.lower().startswith("timeout"):
retry = True
elif msg.lower().startswith("timeout"):
retry = True

if not retry:
return data
elif self.headers["x-twitter-auth-type"]:
if retry:
if self.headers["x-twitter-auth-type"]:
self.log.debug("Retrying API request")
continue
else:
# fall through to "Login Required"
response.status_code = 404

# fall through to "Login Required"
response.status_code = 404

if response.status_code == 429:
if response.status_code < 400:
return data
elif response.status_code in (403, 404) and \
not self.headers["x-twitter-auth-type"]:
raise exception.AuthorizationError("Login required")
elif response.status_code == 429:
# rate limit exceeded
if self.extractor.config("ratelimit") == "abort":
raise exception.StopExtraction("Rate limit exceeded")
Expand All @@ -1339,18 +1359,11 @@ def _call(self, endpoint, params, method="GET", auth=True, root=None):
self.extractor.wait(until=until, seconds=seconds)
continue

if response.status_code in (403, 404) and \
not self.headers["x-twitter-auth-type"]:
raise exception.AuthorizationError("Login required")

# error
try:
data = response.json()
errors = ", ".join(e["message"] for e in data["errors"])
except ValueError:
errors = response.text
errors = ", ".join(e["message"] for e in errors)
except Exception:
errors = data.get("errors", "")
pass

raise exception.StopExtraction(
"%s %s (%s)", response.status_code, response.reason, errors)
Expand Down

0 comments on commit 85bbb59

Please sign in to comment.