From 6fe5bb763f0c5cc0cafe4e04dc8e37771074c710 Mon Sep 17 00:00:00 2001 From: Benjamin Harder Date: Thu, 29 May 2025 16:38:24 +0200 Subject: [PATCH] test_run --- src/jobs/removal_handler.py | 6 +-- src/jobs/remove_bad_files.py | 3 +- src/jobs/search_handler.py | 5 +-- src/settings/_download_clients_qBit.py | 55 ++++++++++++-------------- src/utils/common.py | 26 +++++++++++- 5 files changed, 56 insertions(+), 39 deletions(-) diff --git a/src/jobs/removal_handler.py b/src/jobs/removal_handler.py index 4b97b19..079b67c 100644 --- a/src/jobs/removal_handler.py +++ b/src/jobs/removal_handler.py @@ -41,13 +41,11 @@ class RemovalHandler: async def _remove_download(self, queue_item, blocklist): queue_id = queue_item["id"] logger.info(f">>> Job '{self.job_name}' triggered removal: {queue_item['title']}") - if not self.settings.general.test_run: - await self.arr.remove_queue_item(queue_id=queue_id, blocklist=blocklist) + await self.arr.remove_queue_item(queue_id=queue_id, blocklist=blocklist) async def _tag_as_obsolete(self, queue_item, download_id): logger.info(f">>> Job'{self.job_name}' triggered obsolete-tagging: {queue_item['title']}") - if not self.settings.general.test_run: - for qbit in self.settings.download_clients.qbittorrent: + for qbit in self.settings.download_clients.qbittorrent: await qbit.set_tag(tags=[self.settings.general.obsolete_tag], hashes=[download_id]) diff --git a/src/jobs/remove_bad_files.py b/src/jobs/remove_bad_files.py index 5d5ca5c..e3facbd 100644 --- a/src/jobs/remove_bad_files.py +++ b/src/jobs/remove_bad_files.py @@ -201,8 +201,7 @@ class RemoveBadFiles(RemovalJob): async def _mark_files_as_stopped(self, qbit_client, torrent_hash, stoppable_files): """Mark specific files as 'Do Not Download' in qBittorrent.""" for file, _ in stoppable_files: - if not self.settings.general.test_run: - await qbit_client.set_torrent_file_priority(torrent_hash, file['index'], 0) + await qbit_client.set_torrent_file_priority(torrent_hash, file['index'], 0) def _all_files_stopped(self, torrent_files, stoppable_files): """Check if all files are either stopped (priority 0) or in the stoppable files list.""" diff --git a/src/jobs/search_handler.py b/src/jobs/search_handler.py index 45ef4c1..5f0dd87 100644 --- a/src/jobs/search_handler.py +++ b/src/jobs/search_handler.py @@ -68,9 +68,8 @@ class SearchHandler: return [item for item in wanted_items if item["id"] not in queue_ids] async def _trigger_search(self, items): - if not self.settings.general.test_run: - ids = [item["id"] for item in items] - await self.wanted_manager.search_items(ids) + ids = [item["id"] for item in items] + await self.wanted_manager.search_items(ids) def _filter_recent_searches(self, items): now = datetime.now(timezone.utc) diff --git a/src/settings/_download_clients_qBit.py b/src/settings/_download_clients_qBit.py index 2c1b2c1..c337ccc 100644 --- a/src/settings/_download_clients_qBit.py +++ b/src/settings/_download_clients_qBit.py @@ -76,7 +76,7 @@ class QbitClient: data = {"username": getattr(self, 'username', ''), "password": getattr(self, 'password', '')} headers = {"content-type": "application/x-www-form-urlencoded"} response = await make_request( - "post", endpoint, self.settings, data=data, headers=headers + "post", endpoint, self.settings, data=data, headers=headers, ignore_test_run=True ) if response.text == "Fails.": @@ -124,15 +124,14 @@ class QbitClient: current_tags = response.json() if self.settings.general.protected_tag not in current_tags: logger.verbose(f"Creating protection tag: {self.settings.general.protected_tag}") - if not self.settings.general.test_run: - data = {"tags": self.settings.general.protected_tag} - await make_request( - "post", - self.api_url + "/torrents/createTags", - self.settings, - data=data, - cookies=self.cookie, - ) + data = {"tags": self.settings.general.protected_tag} + await make_request( + "post", + self.api_url + "/torrents/createTags", + self.settings, + data=data, + cookies=self.cookie, + ) if ( self.settings.general.public_tracker_handling == "tag_as_obsolete" @@ -140,15 +139,14 @@ class QbitClient: ): if self.settings.general.obsolete_tag not in current_tags: logger.verbose(f"Creating obsolete tag: {self.settings.general.obsolete_tag}") - if not self.settings.general.test_run: - data = {"tags": self.settings.general.obsolete_tag} - await make_request( - "post", - self.api_url + "/torrents/createTags", - self.settings, - data=data, - cookies=self.cookie, - ) + data = {"tags": self.settings.general.obsolete_tag} + await make_request( + "post", + self.api_url + "/torrents/createTags", + self.settings, + data=data, + cookies=self.cookie, + ) async def set_unwanted_folder(self): """Set the 'unwanted folder' setting in qBittorrent if needed.""" @@ -163,15 +161,14 @@ class QbitClient: logger.info( "Enabling 'Keep unselected files in .unwanted folder' in qBittorrent." ) - if not self.settings.general.test_run: - data = {"json": '{"use_unwanted_folder": true}'} - await make_request( - "post", - self.api_url + "/app/setPreferences", - self.settings, - data=data, - cookies=self.cookie, - ) + data = {"json": '{"use_unwanted_folder": true}'} + await make_request( + "post", + self.api_url + "/app/setPreferences", + self.settings, + data=data, + cookies=self.cookie, + ) async def check_qbit_reachability(self): @@ -181,7 +178,7 @@ class QbitClient: data = {"username": getattr(self, 'username', ''), "password": getattr(self, 'password', '')} headers = {"content-type": "application/x-www-form-urlencoded"} await make_request( - "post", endpoint, self.settings, data=data, headers=headers, log_error=False + "post", endpoint, self.settings, data=data, headers=headers, log_error=False, ignore_test_run=True ) except Exception as e: diff --git a/src/utils/common.py b/src/utils/common.py index cf08fd9..831f465 100644 --- a/src/utils/common.py +++ b/src/utils/common.py @@ -6,6 +6,17 @@ import copy import requests from src.utils.log_setup import logger + +class DummyResponse: + def __init__(self, text="", status_code=200): + self.text = text + self.status_code = status_code + + def raise_for_status(self): + if self.status_code >= 400: + raise requests.HTTPError(f"Status code: {self.status_code}") + + def sanitize_kwargs(data): """Recursively redact sensitive values in kwargs for safe logging.""" if isinstance(data, dict): @@ -20,19 +31,32 @@ def sanitize_kwargs(data): return [sanitize_kwargs(item) for item in data] return data + async def make_request( method: str, endpoint: str, settings, timeout: int = 15, log_error = True, **kwargs ) -> requests.Response: """ A utility function to make HTTP requests (GET, POST, DELETE, PUT). """ + ignore_test_run = kwargs.pop("ignore_test_run", False) + + if settings.general.test_run and not ignore_test_run: + if method.lower() in ("put", "post","delete"): + if logger.isEnabledFor(logging.DEBUG): + sanitized_kwargs = sanitize_kwargs(copy.deepcopy(kwargs)) + logger.debug( + f"common.py/make_request: [Test Run] Simulating {method.upper()} request to {endpoint} with kwargs={sanitized_kwargs}" + ) + return DummyResponse(text="Test run - no actual call made", status_code=200) + + try: if logger.isEnabledFor(logging.DEBUG): sanitized_kwargs = sanitize_kwargs(copy.deepcopy(kwargs)) logger.debug( f"common.py/make_request: Making {method.upper()} request to {endpoint} with kwargs={sanitized_kwargs}" ) - + # Make the request using the method passed (get, post, etc.) response = await asyncio.to_thread( getattr(requests, method.lower()),