Skip to content

Commit

Permalink
Remove dependence on qBittorrent session cookie being named SID
Browse files Browse the repository at this point in the history
  • Loading branch information
rmartin16 committed Jan 15, 2023
1 parent dc90896 commit 89e7cf9
Show file tree
Hide file tree
Showing 4 changed files with 39 additions and 18 deletions.
41 changes: 28 additions & 13 deletions qbittorrentapi/auth.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
from qbittorrentapi.decorators import login_required
from qbittorrentapi.definitions import APINames
from qbittorrentapi.definitions import ClientCache
from qbittorrentapi.exceptions import HTTP403Error
from qbittorrentapi.exceptions import LoginFailed
from qbittorrentapi.exceptions import UnsupportedQbittorrentVersion
from qbittorrentapi.request import Request
Expand Down Expand Up @@ -65,16 +66,19 @@ def auth(self):
@property
def is_logged_in(self):
"""
Returns True/False for whether a log-in attempt was ever successfully
completed.
Returns True if low-overhead API call succeeds; False otherwise.
It isn't possible to know if qBittorrent will accept whatever SID is locally
cached...however, any request that is rejected because of the SID will be
automatically retried after a new SID is requested.
There isn't a reliable way to know if an existing session is still valid
without attempting to use it. qBittorrent invalidates cookies when they expire.
:returns: True/False for whether a log-in attempt was previously completed
:returns: True/False if current auth cookie is accepted by qBittorrent.
"""
return bool(self._SID)
try:
self._post(_name=APINames.Application, _method="version")
except HTTP403Error:
return False
else:
return True

def auth_log_in(self, username=None, password=None, **kwargs):
"""
Expand All @@ -93,13 +97,14 @@ def auth_log_in(self, username=None, password=None, **kwargs):

self._initialize_context()
creds = {"username": self.username, "password": self._password}
self._post(_name=APINames.Authorization, _method="login", data=creds, **kwargs)
auth_response = self._post(
_name=APINames.Authorization, _method="login", data=creds, **kwargs
)

if not self.is_logged_in:
if auth_response.text != "Ok.":
logger.debug("Login failed")
raise LoginFailed()
logger.debug("Login successful")
logger.debug("SID: %s", self._SID)

# check if the connected qBittorrent is fully supported by this Client yet
if self._RAISE_UNSUPPORTEDVERSIONERROR:
Expand All @@ -117,12 +122,22 @@ def auth_log_in(self, username=None, password=None, **kwargs):
@property
def _SID(self):
"""
Authorization cookie from qBittorrent.
Authorization session cookie from qBittorrent using default cookie name
`SID`. Backwards compatible for :meth:`~AuthAPIMixIn._session_cookie`.
:return: SID auth cookie from qBittorrent or None if one isn't already acquired
:return: Auth cookie value from qBittorrent or None if one isn't already acquired
"""
return self._session_cookie()

def _session_cookie(self, cookie_name="SID"):
"""
Authorization session cookie from qBittorrent.
:param cookie_name: Name of the authorization cookie; configurable after v4.5.0.
:return: Auth cookie value from qBittorrent or None if one isn't already acquired
"""
if self._http_session:
return self._http_session.cookies.get("SID", None)
return self._http_session.cookies.get(cookie_name, None)
return None

@login_required
Expand Down
1 change: 1 addition & 0 deletions qbittorrentapi/auth.pyi
Original file line number Diff line number Diff line change
Expand Up @@ -31,4 +31,5 @@ class AuthAPIMixIn(Request):
) -> None: ...
@property
def _SID(self) -> Optional[Text]: ...
def _session_cookie(self, cookie_name: Text = "SID") -> Optional[Text]: ...
def auth_log_out(self, **kwargs: KwargsT) -> None: ...
11 changes: 7 additions & 4 deletions qbittorrentapi/decorators.py
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@ def boring_method():


def login_required(func):
"""Ensure client is logged in before calling API methods."""
"""Ensure client is logged in when calling API methods."""

def get_requests_kwargs(**kwargs):
"""Extract kwargs for performing transparent qBittorrent login."""
Expand All @@ -82,9 +82,12 @@ def get_requests_kwargs(**kwargs):

@wraps(func)
def wrapper(client, *args, **kwargs):
if not client.is_logged_in:
logger.debug("Not logged in...attempting login")
client.auth_log_in(**get_requests_kwargs(**kwargs))
"""
Attempt API call; 403 is returned if the login is expired or the user
is banned.
Attempt a login and if successful try the API call a final time.
"""
try:
return func(client, *args, **kwargs)
except HTTP403Error:
Expand Down
4 changes: 3 additions & 1 deletion qbittorrentapi/request.py
Original file line number Diff line number Diff line change
Expand Up @@ -729,8 +729,10 @@ def _trigger_session_initialization(self):
During the next request, a new session will be created.
"""
if hasattr(self, "_http_session") and isinstance(self._http_session, Session):
try:
self._http_session.close()
except AttributeError:
pass
self._http_session = None

@staticmethod
Expand Down

0 comments on commit 89e7cf9

Please sign in to comment.