mirror of
https://github.com/ManiMatter/decluttarr.git
synced 2026-04-24 09:45:45 +02:00
Merge branch 'pr/NaruZosa/252' into decluttarr-v2
This commit is contained in:
@@ -1,16 +1,16 @@
|
||||
import requests
|
||||
from packaging import version
|
||||
|
||||
from src.utils.log_setup import logger
|
||||
from src.settings._config_as_yaml import get_config_as_yaml
|
||||
from src.settings._constants import (
|
||||
ApiEndpoints,
|
||||
MinVersions,
|
||||
FullQueueParameter,
|
||||
DetailItemKey,
|
||||
DetailItemSearchCommand,
|
||||
FullQueueParameter,
|
||||
MinVersions,
|
||||
)
|
||||
from src.settings._config_as_yaml import get_config_as_yaml
|
||||
from src.utils.common import make_request, wait_and_exit
|
||||
from src.utils.log_setup import logger
|
||||
|
||||
|
||||
class Tracker:
|
||||
@@ -63,9 +63,9 @@ class Instances:
|
||||
"""Return a list of arr instances matching the given arr_type."""
|
||||
return [arr for arr in self.arrs if arr.arr_type == arr_type]
|
||||
|
||||
def config_as_yaml(self, hide_internal_attr=True):
|
||||
"""Logs all configured Arr instances while masking sensitive attributes."""
|
||||
internal_attributes={
|
||||
def config_as_yaml(self, *, hide_internal_attr=True):
|
||||
"""Log all configured Arr instances while masking sensitive attributes."""
|
||||
internal_attributes = {
|
||||
"settings",
|
||||
"api_url",
|
||||
"min_version",
|
||||
@@ -92,8 +92,6 @@ class Instances:
|
||||
|
||||
return "\n".join(outputs)
|
||||
|
||||
|
||||
|
||||
def check_any_arrs(self):
|
||||
"""Check if there are any ARR instances."""
|
||||
if not self.arrs:
|
||||
@@ -128,12 +126,11 @@ class ArrInstances(list):
|
||||
arr_type=arr_type,
|
||||
base_url=client_config["base_url"],
|
||||
api_key=client_config["api_key"],
|
||||
)
|
||||
),
|
||||
)
|
||||
except KeyError as e:
|
||||
logger.error(
|
||||
f"Missing required key {e} in {arr_type} client config."
|
||||
)
|
||||
error = f"Missing required key {e} in {arr_type} client config."
|
||||
logger.error(error)
|
||||
|
||||
|
||||
class ArrInstance:
|
||||
@@ -146,11 +143,13 @@ class ArrInstance:
|
||||
def __init__(self, settings, arr_type: str, base_url: str, api_key: str):
|
||||
if not base_url:
|
||||
logger.error(f"Skipping {arr_type} client entry: 'base_url' is required.")
|
||||
raise ValueError(f"{arr_type} client must have a 'base_url'.")
|
||||
error = f"{arr_type} client must have a 'base_url'."
|
||||
raise ValueError(error)
|
||||
|
||||
if not api_key:
|
||||
logger.error(f"Skipping {arr_type} client entry: 'api_key' is required.")
|
||||
raise ValueError(f"{arr_type} client must have an 'api_key'.")
|
||||
error = f"{arr_type} client must have an 'api_key'."
|
||||
raise ValueError(error)
|
||||
|
||||
self.settings = settings
|
||||
self.arr_type = arr_type
|
||||
@@ -164,6 +163,8 @@ class ArrInstance:
|
||||
self.detail_item_ids_key = self.detail_item_key + "Ids"
|
||||
self.detail_item_search_command = getattr(DetailItemSearchCommand, arr_type)
|
||||
|
||||
self.detail_item_search_command = getattr(DetailItemSearchCommand, arr_type)
|
||||
|
||||
async def _check_ui_language(self):
|
||||
"""Check if the UI language is set to English."""
|
||||
endpoint = self.api_url + "/config/ui"
|
||||
@@ -173,25 +174,26 @@ class ArrInstance:
|
||||
if ui_language > 1: # Not English
|
||||
logger.error("!! %s Error: !!", self.name)
|
||||
logger.error(
|
||||
f"> Decluttarr only works correctly if UI language is set to English (under Settings/UI in {self.name})"
|
||||
f"> Decluttarr only works correctly if UI language is set to English (under Settings/UI in {self.name})",
|
||||
)
|
||||
logger.error(
|
||||
"> Details: https://github.com/ManiMatter/decluttarr/issues/132)"
|
||||
"> Details: https://github.com/ManiMatter/decluttarr/issues/132)",
|
||||
)
|
||||
raise ArrError("Not English")
|
||||
error = "Not English"
|
||||
raise ArrError(error)
|
||||
|
||||
def _check_min_version(self, status):
|
||||
"""Check if ARR instance meets minimum version requirements."""
|
||||
self.version = status["version"]
|
||||
min_version = getattr(self.settings.min_versions, self.arr_type)
|
||||
|
||||
if min_version:
|
||||
if version.parse(self.version) < version.parse(min_version):
|
||||
logger.error("!! %s Error: !!", self.name)
|
||||
logger.error(
|
||||
f"> Please update {self.name} ({self.base_url}) to at least version {min_version}. Current version: {self.version}"
|
||||
)
|
||||
raise ArrError("Not meeting minimum version requirements")
|
||||
if min_version and version.parse(self.version) < version.parse(min_version):
|
||||
logger.error("!! %s Error: !!", self.name)
|
||||
logger.error(
|
||||
f"> Please update {self.name} ({self.base_url}) to at least version {min_version}. Current version: {self.version}",
|
||||
)
|
||||
error = f"Not meeting minimum version requirements: {min_version}"
|
||||
logger.error(error)
|
||||
|
||||
def _check_arr_type(self, status):
|
||||
"""Check if the ARR instance is of the correct type."""
|
||||
@@ -199,9 +201,10 @@ class ArrInstance:
|
||||
if actual_arr_type.lower() != self.arr_type:
|
||||
logger.error("!! %s Error: !!", self.name)
|
||||
logger.error(
|
||||
f"> Your {self.name} ({self.base_url}) points to a {actual_arr_type} instance, rather than {self.arr_type}. Did you specify the wrong IP?"
|
||||
f"> Your {self.name} ({self.base_url}) points to a {actual_arr_type} instance, rather than {self.arr_type}. Did you specify the wrong IP?",
|
||||
)
|
||||
raise ArrError("Wrong Arr Type")
|
||||
error = "Wrong Arr Type"
|
||||
logger.error(error)
|
||||
|
||||
async def _check_reachability(self):
|
||||
"""Check if ARR instance is reachable."""
|
||||
@@ -210,14 +213,13 @@ class ArrInstance:
|
||||
endpoint = self.api_url + "/system/status"
|
||||
headers = {"X-Api-Key": self.api_key}
|
||||
response = await make_request(
|
||||
"get", endpoint, self.settings, headers=headers, log_error=False
|
||||
"get", endpoint, self.settings, headers=headers, log_error=False,
|
||||
)
|
||||
status = response.json()
|
||||
return status
|
||||
return response.json()
|
||||
except Exception as e:
|
||||
if isinstance(e, requests.exceptions.HTTPError):
|
||||
response = getattr(e, "response", None)
|
||||
if response is not None and response.status_code == 401:
|
||||
if response is not None and response.status_code == 401: # noqa: PLR2004
|
||||
tip = "💡 Tip: Have you configured the API_KEY correctly?"
|
||||
else:
|
||||
tip = f"💡 Tip: HTTP error occurred. Status: {getattr(response, 'status_code', 'unknown')}"
|
||||
@@ -230,7 +232,7 @@ class ArrInstance:
|
||||
raise ArrError(e) from e
|
||||
|
||||
async def setup(self):
|
||||
"""Checks on specific ARR instance"""
|
||||
"""Check on specific ARR instance."""
|
||||
try:
|
||||
status = await self._check_reachability()
|
||||
self.name = status.get("instanceName", self.arr_type)
|
||||
@@ -242,7 +244,7 @@ class ArrInstance:
|
||||
logger.info(f"OK | {self.name} ({self.base_url})")
|
||||
logger.debug(f"Current version of {self.name}: {self.version}")
|
||||
|
||||
except Exception as e:
|
||||
except Exception as e: # noqa: BLE001
|
||||
if not isinstance(e, ArrError):
|
||||
logger.error(f"Unhandled error: {e}", exc_info=True)
|
||||
wait_and_exit()
|
||||
@@ -266,17 +268,19 @@ class ArrInstance:
|
||||
return client.get("implementation", None)
|
||||
return None
|
||||
|
||||
async def remove_queue_item(self, queue_id, blocklist=False):
|
||||
async def remove_queue_item(self, queue_id, *, blocklist=False):
|
||||
"""
|
||||
Remove a specific queue item from the queue by its qeue id.
|
||||
Remove a specific queue item from the queue by its queue id.
|
||||
|
||||
Sends a delete request to the API to remove the item.
|
||||
|
||||
Args:
|
||||
queue_id (str): The quueue ID of the queue item to be removed.
|
||||
queue_id (str): The queue ID of the queue item to be removed.
|
||||
blocklist (bool): Whether to add the item to the blocklist. Default is False.
|
||||
|
||||
Returns:
|
||||
bool: Returns True if the removal was successful, False otherwise.
|
||||
|
||||
"""
|
||||
logger.debug(f"_instances.py/remove_queue_item: Removing queue item, blocklist: {blocklist}")
|
||||
endpoint = f"{self.api_url}/queue/{queue_id}"
|
||||
@@ -285,14 +289,11 @@ class ArrInstance:
|
||||
|
||||
# Send the request to remove the download from the queue
|
||||
response = await make_request(
|
||||
"delete", endpoint, self.settings, headers=headers, json=json_payload
|
||||
"delete", endpoint, self.settings, headers=headers, json=json_payload,
|
||||
)
|
||||
|
||||
# If the response is successful, return True, else return False
|
||||
if response.status_code == 200:
|
||||
return True
|
||||
else:
|
||||
return False
|
||||
return response.status_code == 200 # noqa: PLR2004
|
||||
|
||||
async def is_monitored(self, detail_id):
|
||||
"""Check if detail item (like a book, series, etc) is monitored."""
|
||||
|
||||
Reference in New Issue
Block a user