Skip to content

Commit

Permalink
feat: enhance downloader with improved filesize validation and logging
Browse files Browse the repository at this point in the history
- Introduced `InvalidFileSizeException` for better error handling.
- Added `DownloadCachedStreamResult` class to encapsulate download results.
- Refactored `validate_filesize` to raise exceptions and log invalid file sizes.
- Enhanced logging with `get_invalid_filesize_log_string` for clearer messages.
- Improved structure and readability of the downloader service.
  • Loading branch information
iPromKnight committed Nov 7, 2024
1 parent a882ab2 commit 2d3200e
Show file tree
Hide file tree
Showing 2 changed files with 34 additions and 33 deletions.
55 changes: 27 additions & 28 deletions src/program/services/downloaders/__init__.py
Original file line number Diff line number Diff line change
@@ -1,18 +1,24 @@
from loguru import logger

from program.media.item import MediaItem
from program.media.item import MediaItem, MovieMediaType, ShowMediaType
from program.media.state import States
from program.media.stream import Stream
from program.settings.manager import settings_manager
from program.services.downloaders.shared import filesize_is_acceptable
from program.services.downloaders.shared import filesize_is_acceptable, get_invalid_filesize_log_string

from .alldebrid import AllDebridDownloader
from .realdebrid import RealDebridDownloader
from ...media import MovieMediaType, ShowMediaType


# from .torbox import TorBoxDownloader

class InvalidFileSizeException(Exception):
pass

class DownloadCachedStreamResult:
def __init__(self, container=None, torrent_id=None, info=None, info_hash=None):
self.container = container
self.torrent_id = torrent_id
self.info = info
self.info_hash = info_hash

class Downloader:
def __init__(self):
Expand Down Expand Up @@ -42,22 +48,22 @@ def validate(self):

def run(self, item: MediaItem):
logger.debug(f"Running downloader for {item.log_string}")

for stream in item.streams:
torrent_id = None
download_result = None
try:
torrent_id = self.download_cached_stream(item, stream)
if torrent_id:
download_result = self.download_cached_stream(item, stream)
if download_result:
self.validate_filesize(item, download_result)
break
except Exception as e:
if torrent_id:
self.service.delete_torrent(torrent_id)
logger.debug(f"Blacklisting {stream.raw_title} for {item.log_string}, reason: {e}")
if download_result and download_result.torrent_id:
self.service.delete_torrent(download_result.torrent_id)
logger.debug(f"Invalid stream: {stream.infohash} - reason: {e}")
item.blacklist_stream(stream)
yield item

def download_cached_stream(self, item: MediaItem, stream: Stream) -> bool:
torrent_id = None

def download_cached_stream(self, item: MediaItem, stream: Stream) -> DownloadCachedStreamResult:
cached_containers = self.get_instant_availability([stream.infohash]).get(stream.infohash, None)
if not cached_containers:
raise Exception("Not cached!")
Expand All @@ -68,7 +74,7 @@ def download_cached_stream(self, item: MediaItem, stream: Stream) -> bool:
if not self.update_item_attributes(item, info, the_container):
raise Exception("No matching files found!")
logger.log("DEBRID", f"Downloaded {item.log_string} from '{stream.raw_title}' [{stream.infohash}]")
return torrent_id
return DownloadCachedStreamResult(the_container, torrent_id, info, stream.infohash)

def get_instant_availability(self, infohashes: list[str]) -> dict[str, list[dict]]:
return self.service.get_instant_availability(infohashes)
Expand All @@ -91,8 +97,6 @@ def update_item_attributes(self, item: MediaItem, info, container) -> bool:
item = item
container = container
for file in container.values():
if not self.validate_filesize(item, info, file):
continue
if item.type == MovieMediaType.Movie.value and self.service.file_finder.container_file_matches_movie(file):
item.file = file[self.service.file_finder.filename_attr]
item.folder = info["filename"]
Expand Down Expand Up @@ -121,17 +125,12 @@ def update_item_attributes(self, item: MediaItem, info, container) -> bool:
found = True
return found

def validate_filesize(self, item, info, file) -> bool:
item_media_type = self._get_item_media_type(item)
if filesize_is_acceptable(file[self.service.file_finder.filesize_attr], item_media_type):
return True
torrent_id = info.get("id", None)
if not torrent_id:
logger.warning(f"Couldn't find torrent id to delete")
return False
logger.debug(f"Deleting {torrent_id} because it doesn't match the item type or size")
self.service.delete_torrent(torrent_id)
return False
def validate_filesize(self, item: MediaItem, download_result: DownloadCachedStreamResult):
for file in download_result.container.values():
item_media_type = self._get_item_media_type(item)
if not filesize_is_acceptable(file[self.service.file_finder.filesize_attr], item_media_type):
raise InvalidFileSizeException(f"File '{file[self.service.file_finder.filename_attr]}' is invalid: {get_invalid_filesize_log_string(file[self.service.file_finder.filesize_attr], item_media_type)}")
logger.debug(f"All files for {download_result.info_hash} are of an acceptable size")

@staticmethod
def _get_item_media_type(item):
Expand Down
12 changes: 7 additions & 5 deletions src/program/services/downloaders/shared.py
Original file line number Diff line number Diff line change
Expand Up @@ -179,11 +179,13 @@ def _validate_filesize(filesize: int, media_type: str) -> bool:
min_size = 0 if min_mb == -1 else _convert_to_bytes(min_mb)
max_size = float("inf") if max_mb == -1 else _convert_to_bytes(max_mb)

is_acceptable = min_size <= filesize <= max_size
if not is_acceptable:
logger.debug(f"{media_type} filesize {filesize} bytes is not within acceptable range {min_size} - {max_size} bytes")
return is_acceptable
return min_size <= filesize <= max_size


def filesize_is_acceptable(filesize: int, media_type: str) -> bool:
return _validate_filesize(filesize, media_type)
return _validate_filesize(filesize, media_type)

def get_invalid_filesize_log_string(filesize: int, media_type: str) -> str:
min_mb, max_mb = _get_size_limits(media_type)
friendly_filesize = round(filesize / BYTES_PER_MB, 2)
return f"{friendly_filesize} MB is not within acceptable range of [{min_mb}MB] to [{max_mb}MB]"

0 comments on commit 2d3200e

Please sign in to comment.