rmartin16 / qbittorrent-api

Python client implementation for qBittorrent's Web API
https://qbittorrent-api.readthedocs.io/
MIT License
400 stars 66 forks source link

qBittorrent v4.6.0 and `inactive_seeding_time_limit` #364

Closed rmartin16 closed 10 months ago

rmartin16 commented 10 months ago

Describe the bug

From @cascandaliato:

I just upgraded to 4.6.0 and my code crashed when calling this method because I was missing inactive_seeding_time_limit and qBittorrent API doesn't accept an inactive_seeding_time_limit = None. I tested it and this is true for the other two limit parameters so this is not really a breaking change but I was wondering whether the defaulting to None serves a specific purpose.

source: https://github.com/rmartin16/qbittorrent-api/commit/1859017bc7ed4cdb017c23212923f74cf2642a6a#r131152934

Steps to reproduce

  1. Go to '...'
  2. Click on '....'
  3. Scroll down to '....'
  4. See error

Expected behavior

Code doesn't crash.

Screenshots

No response

Environment

Additional context

No response

rmartin16 commented 10 months ago

Hello @cascandaliato, can you please elaborate on what exact API call started crashing? And the exception being raised?

rmartin16 commented 10 months ago

I was wondering whether the defaulting to None serves a specific purpose.

I default all the API method arguments to None for a few reasons. 1) Not all arguments are required by qBittorrent....and some are even conditional on whether other arguments are included 2) I didn't want to try to enforce required arguments in my API wrappers....and instead just let qBittorrent return an error if a required parameter is missing 3) The default of None works nicely because the underlying HTTP library requests doesn't include parameters set to None....because of this, setting an argument to None is the same as not including it at all

rmartin16 commented 10 months ago

I also think I understand now why you started seeing an error when calling client.torrents_set_share_limits().

When qBittorrent added inactive_seeding_time_limit as a argument to this API method, they made it a required argument. So, when you (or anyone else) upgrade to v4.6.0, all existing uses of set_share_limits() will break....until inactive_seeding_time_limit is also included as an argument.

Let me know if this doesn't address your questions....or sparks other ones. Closing.

cascandaliato commented 10 months ago

I get the following error when I call set_share_limits and I don't specify inactive_seeding_time_limit:

2023-10-28 19:54:46,448 - urllib3.connectionpool - DEBUG - http://REDACTED:8080 "POST /api/v2/torrents/setShareLimits HTTP/1.1" 400 11
2023-10-28 19:54:46,448 - qbittorrentapi.request - DEBUG - Request URL: (POST) http://REDACTED:8080/api/v2/torrents/setShareLimits
2023-10-28 19:54:46,448 - qbittorrentapi.request - DEBUG - Request Headers: {'User-Agent': 'python-requests/2.31.0', 'Accept-Encoding': 'gzip, deflate', 'Accept': '*/*', 'Connection': 'keep-alive', 'Cookie': 'SID=REDACTED', 'Content-Length': '81', 'Content-Type': 'application/x-www-form-urlencoded'}
2023-10-28 19:54:46,448 - qbittorrentapi.request - DEBUG - Request HTTP Data: {'data': {'hashes': 'REDACTED', 'ratioLimit': -2, 'seedingTimeLimit': -2, 'inactiveSeedingTimeLimit': None}, 'params': {}}
2023-10-28 19:54:46,448 - qbittorrentapi.request - DEBUG - Requests Config: {}
2023-10-28 19:54:46,448 - qbittorrentapi.request - DEBUG - Request body: hashes=REDACTED&ratioLimit=-2&seedingTimeLimit=-2
2023-10-28 19:54:46,448 - qbittorrentapi.request - DEBUG - Response status: 400 (Bad Request)
2023-10-28 19:54:46,448 - qbittorrentapi.request - DEBUG - Response text: Bad Request
Traceback (most recent call last):
  File "/usr/src/app/./main.py", line 125, in <module>
    action.update(torrent)
  File "/usr/src/app/seeding_limits.py", line 31, in update
    self.qbt_set_share_limits(
  File "/usr/src/app/slower.py", line 22, in wrapper
    return fn(*args, **kwargs)
           ^^^^^^^^^^^^^^^^^^^
  File "/usr/local/lib/python3.12/site-packages/qbittorrentapi/torrents.py", line 1095, in torrents_set_share_limits
    self._post(
  File "/usr/local/lib/python3.12/site-packages/qbittorrentapi/request.py", line 514, in _post
    return self._auth_request(
           ^^^^^^^^^^^^^^^^^^^
  File "/usr/local/lib/python3.12/site-packages/qbittorrentapi/request.py", line 591, in _auth_request
    return self._request_manager(
           ^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/local/lib/python3.12/site-packages/qbittorrentapi/request.py", line 664, in _request_manager
    return self._request(
           ^^^^^^^^^^^^^^
  File "/usr/local/lib/python3.12/site-packages/qbittorrentapi/request.py", line 811, in _request
    self._handle_error_responses(final_data, final_params, response)
  File "/usr/local/lib/python3.12/site-packages/qbittorrentapi/request.py", line 964, in _handle_error_responses
    raise MissingRequiredParameters400Error(
qbittorrentapi.exceptions.MissingRequiredParameters400Error

The same happens if I don't pass ratio_limit or seeding_time_limit except I never noticed it before because my code specifies both values:

2023-10-28 19:57:42,067 - urllib3.connectionpool - DEBUG - http://REDACTED:8080 "POST /api/v2/torrents/setShareLimits HTTP/1.1" 400 11
2023-10-28 19:57:42,067 - qbittorrentapi.request - DEBUG - Request URL: (POST) http://REDACTED:8080/api/v2/torrents/setShareLimits
2023-10-28 19:57:42,067 - qbittorrentapi.request - DEBUG - Request Headers: {'User-Agent': 'python-requests/2.31.0', 'Accept-Encoding': 'gzip, deflate', 'Accept': '*/*', 'Connection': 'keep-alive', 'Cookie': 'SID=REDACTED', 'Content-Length': '75', 'Content-Type': 'application/x-www-form-urlencoded'}
2023-10-28 19:57:42,067 - qbittorrentapi.request - DEBUG - Request HTTP Data: {'data': {'hashes': 'REDACTED', 'ratioLimit': None, 'seedingTimeLimit': None, 'inactiveSeedingTimeLimit': -1}, 'params': {}}
2023-10-28 19:57:42,067 - qbittorrentapi.request - DEBUG - Requests Config: {}
2023-10-28 19:57:42,067 - qbittorrentapi.request - DEBUG - Request body: hashes=REDACTED&inactiveSeedingTimeLimit=-1
2023-10-28 19:57:42,067 - qbittorrentapi.request - DEBUG - Response status: 400 (Bad Request)
2023-10-28 19:57:42,067 - qbittorrentapi.request - DEBUG - Response text: Bad Request
Traceback (most recent call last):
  File "/usr/src/app/./main.py", line 96, in <module>
    action.update(cache[hash])
  File "/usr/src/app/seeding_limits.py", line 31, in update
    self.qbt_set_share_limits(
  File "/usr/src/app/slower.py", line 22, in wrapper
    return fn(*args, **kwargs)
           ^^^^^^^^^^^^^^^^^^^
  File "/usr/local/lib/python3.12/site-packages/qbittorrentapi/torrents.py", line 1095, in torrents_set_share_limits
    self._post(
  File "/usr/local/lib/python3.12/site-packages/qbittorrentapi/request.py", line 514, in _post
    return self._auth_request(
           ^^^^^^^^^^^^^^^^^^^
  File "/usr/local/lib/python3.12/site-packages/qbittorrentapi/request.py", line 591, in _auth_request
    return self._request_manager(
           ^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/local/lib/python3.12/site-packages/qbittorrentapi/request.py", line 664, in _request_manager
    return self._request(
           ^^^^^^^^^^^^^^
  File "/usr/local/lib/python3.12/site-packages/qbittorrentapi/request.py", line 811, in _request
    self._handle_error_responses(final_data, final_params, response)
  File "/usr/local/lib/python3.12/site-packages/qbittorrentapi/request.py", line 964, in _handle_error_responses
    raise MissingRequiredParameters400Error(
qbittorrentapi.exceptions.MissingRequiredParameters400Error

As you said, requests is not sending the None parameters

body: hashes=REDACTED&inactiveSeedingTimeLimit=-1

so it might be the case that all these parameters are required for the specific endpoint.

rmartin16 commented 10 months ago

so it might be the case that all these parameters are required for the specific endpoint.

Indeed, they are all required. For better or worse, the qBittorrent team doesn't seem to concern themselves too much with backwards (or forwards) compatibility for the API :/

cascandaliato commented 10 months ago

Perfect, that explains it. Thank you for taking the time to look at my comments.