Changes per review of Dark3clipse

This commit is contained in:
Benjamin Harder
2025-06-03 00:52:26 +02:00
parent 5ec2a62e86
commit 6d14d29abc
8 changed files with 38 additions and 26 deletions

View File

@@ -121,7 +121,7 @@ jobs:
fi
docker buildx build \
--platform linux/amd64,linux/arm64 -f docker/dockerfile . \
--platform linux/amd64,linux/arm64 -f docker/Dockerfile . \
--progress plain \
-t $IMAGE_NAME:$IMAGE_TAG \
$TAG_LATEST \

View File

@@ -98,7 +98,7 @@ How to run this:
## Getting started
You can run decluttarr either as local python script, or inside docker.
You can run decluttarr either as local python script, or as a docker container.
### Running locally
@@ -117,7 +117,7 @@ jobs:
remove_bad_files: # This is turned on
# remove_bad_files: # This is turned off
## Note that this is different from docker-compose (where both exsmples above would be turned off; in docker, "true" or additional options are required as value next to the key)
## Note that this is different from docker-compose (where both examples above would be turned off; in docker, "true" or additional options are required as value next to the key)
```

View File

@@ -1,7 +1,7 @@
#FROM python:3.9-slim-buster
# For debugging:
# First build:
# sudo docker build --no-cache --progress=plain -f ./docker/dockerfile -t decluttarr .
# sudo docker build --no-cache --progress=plain -f ./docker/Dockerfile -t decluttarr .
# Entering image (and printing env variables):
# sudo docker run --rm -it -w /app --entrypoint sh decluttarr -c "printenv; exec sh"

View File

@@ -54,8 +54,10 @@ class RemovalHandler:
if affected_download['protocol'] != 'torrent':
return "remove" # handling is only implemented for torrent
client_implementation = await self.arr.get_download_client_implementation(affected_download['downloadClient'])
if client_implementation != "QBittorrent":
download_client_name = affected_download["downloadClient"]
_, download_client_type = self.settings.download_clients.get_download_client_by_name(download_client_name)
if download_client_type != "qbittorrent":
return "remove" # handling is only implemented for qbit
if len(self.settings.download_clients.qbittorrent) == 0:

View File

@@ -9,7 +9,7 @@ STANDARD_EXTENSIONS = [
# Movies, TV Shows (Radarr, Sonarr, Whisparr)
".webm", ".m4v", ".3gp", ".nsv", ".ty", ".strm", ".rm", ".rmvb", ".m3u", ".ifo", ".mov", ".qt", ".divx", ".xvid", ".bivx", ".nrg", ".pva", ".wmv", ".asf", ".asx", ".ogm", ".ogv", ".m2v", ".avi", ".bin", ".dat", ".dvr-ms", ".mpg", ".mpeg", ".mp4", ".avc", ".vp3", ".svq3", ".nuv", ".viv", ".dv", ".fli", ".flv", ".wpl", ".img", ".iso", ".vob", ".mkv", ".mk3d", ".ts", ".wtv", ".m2ts",
# Subs (Radarr, Sonarr, Whisparr)
".sub", ".srt", ".idx",
".sub", ".srt", ".idx", "vtt",
# Audio (Lidarr, Readarr)
".aac", ".aif", ".aiff", ".aifc", ".ape", ".flac", ".mp2", ".mp3", ".m4a", ".m4b", ".m4p", ".mp4a", ".oga", ".ogg", ".opus", ".vorbis", ".wma", ".wav", ".wv", "wavepack",
# Text (Readarr)

View File

@@ -9,7 +9,7 @@ class RemoveMissingFiles(RemovalJob):
affected_items = []
for item in self.queue:
if self._is_failed_torrent(item) or self._no_elibible_import(item):
if self._is_failed_torrent(item) or self._no_eligible_import(item):
affected_items.append(item)
return affected_items
@@ -19,7 +19,8 @@ class RemoveMissingFiles(RemovalJob):
"status" in item
and item["status"] == "warning"
and "errorMessage" in item
and item["errorMessage"] in [
and item["errorMessage"]
in [
"DownloadClientQbittorrentTorrentStateMissingFiles",
"The download is missing files",
"qBittorrent is reporting missing files",
@@ -27,11 +28,17 @@ class RemoveMissingFiles(RemovalJob):
)
@staticmethod
def _no_elibible_import(item) -> bool:
if "status" in item and item["status"] == "completed" and "statusMessages" in item:
def _no_eligible_import(item) -> bool:
if (
"status" in item
and item["status"] == "completed"
and "statusMessages" in item
):
for status_message in item["statusMessages"]:
if "messages" in status_message:
for message in status_message["messages"]:
if message.startswith("No files found are eligible for import in"):
if message.startswith(
"No files found are eligible for import in"
):
return True
return False

View File

@@ -66,8 +66,8 @@ class DownloadClients:
download_clients = getattr(self, download_client_type, [])
# Check each client in the list
for client in download_clients:
if client.name.lower() == name_lower:
return client, download_client_type
for download_client in download_clients:
if download_client.name.lower() == name_lower:
return download_client, download_client_type
return None, None

View File

@@ -5,32 +5,35 @@ from src.jobs.removal_handler import RemovalHandler
@pytest.mark.parametrize(
"qbittorrent_configured, is_private, client_impl, protocol, expected",
"qbittorrent_configured, is_private, client_type, protocol, expected",
[
(True, True, "QBittorrent", "torrent", "private_handling"),
(True, False, "QBittorrent", "torrent", "public_handling"),
(False, True, "QBittorrent", "torrent", "remove"),
(False, False, "QBittorrent", "torrent", "remove"),
(True, False, "Transmission", "torrent", "remove"), # unsupported client
(True, False, "MyUseNetClient", "usenet", "remove"), # unsupported protocol
(True, True, "qbittorrent", "torrent", "private_handling"),
(True, False, "qbittorrent", "torrent", "public_handling"),
(False, True, "qbittorrent", "torrent", "remove"),
(False, False, "qbittorrent", "torrent", "remove"),
(True, False, "transmission", "torrent", "remove"), # unsupported client
(True, False, "myusenetclient", "usenet", "remove"), # unsupported protocol
],
)
@pytest.mark.asyncio
async def test_get_handling_method(
qbittorrent_configured,
is_private,
client_impl,
client_type,
protocol,
expected,
):
# Mock arr
arr = AsyncMock()
arr.tracker.private = ["A"] if is_private else []
arr.get_download_client_implementation.return_value = client_impl
# Mock settings
# Mock settings and get_download_client_by_name
settings = MagicMock()
settings.download_clients.qbittorrent = ["dummy"] if qbittorrent_configured else []
# Simulate (client_name, client_type) return
settings.download_clients.get_download_client_by_name.return_value = ("client_name", client_type)
settings.general.private_tracker_handling = "private_handling"
settings.general.public_tracker_handling = "public_handling"
@@ -44,4 +47,4 @@ async def test_get_handling_method(
result = await handler._get_handling_method( # pylint: disable=W0212
"A", affected_download
)
assert result == expected
assert result == expected