From d2f8374ae95fc763842750a67d1d9b9f3c545a8d Mon Sep 17 00:00:00 2001 From: davidemarcoli Date: Sat, 26 Oct 2024 21:29:14 +0200 Subject: [PATCH] feat: filesize filter --- src/program/downloaders/realdebrid.py | 22 ++++++------ src/program/downloaders/shared.py | 49 +++++++++++++++++++++++++-- src/program/settings/models.py | 8 ++--- 3 files changed, 62 insertions(+), 17 deletions(-) diff --git a/src/program/downloaders/realdebrid.py b/src/program/downloaders/realdebrid.py index 46d19ea9..74c743a5 100644 --- a/src/program/downloaders/realdebrid.py +++ b/src/program/downloaders/realdebrid.py @@ -3,7 +3,7 @@ from typing import Optional, Union from loguru import logger -from program.settings.manager import settings_manager as settings +from program.settings.manager import settings_manager from pydantic import BaseModel, TypeAdapter from requests import ConnectTimeout from utils import request @@ -52,7 +52,7 @@ class RDTorrent(BaseModel): class RealDebridDownloader(DownloaderBase): def __init__(self): self.key = "realdebrid" - self.settings = settings.settings.downloaders.real_debrid + self.settings = settings_manager.settings.downloaders.real_debrid self.initialized = self.validate() if self.initialized: self.existing_hashes = [torrent.hash for torrent in get_torrents(1000)] @@ -176,14 +176,14 @@ def get(url): return request.get( url=f"{BASE_URL}/{url}", additional_headers={ - "Authorization": f"Bearer {settings.settings.downloaders.real_debrid.api_key}" + "Authorization": f"Bearer {settings_manager.settings.downloaders.real_debrid.api_key}" }, response_type=dict, specific_rate_limiter=torrent_limiter, overall_rate_limiter=overall_limiter, proxies=( - settings.settings.downloaders.real_debrid.proxy_url - if settings.settings.downloaders.real_debrid.proxy_enabled + settings_manager.settings.downloaders.real_debrid.proxy_url + if settings_manager.settings.downloaders.real_debrid.proxy_enabled else None ), ).data @@ -195,13 +195,13 @@ def post(url, data): data=data, response_type=dict, additional_headers={ - "Authorization": f"Bearer {settings.settings.downloaders.real_debrid.api_key}" + "Authorization": f"Bearer {settings_manager.settings.downloaders.real_debrid.api_key}" }, specific_rate_limiter=torrent_limiter, overall_rate_limiter=overall_limiter, proxies=( - settings.settings.downloaders.real_debrid.proxy_url - if settings.settings.downloaders.real_debrid.proxy_enabled + settings_manager.settings.downloaders.real_debrid.proxy_url + if settings_manager.settings.downloaders.real_debrid.proxy_enabled else None ), ).data @@ -211,14 +211,14 @@ def delete(url): return request.delete( url=f"{BASE_URL}/{url}", additional_headers={ - "Authorization": f"Bearer {settings.settings.downloaders.real_debrid.api_key}" + "Authorization": f"Bearer {settings_manager.settings.downloaders.real_debrid.api_key}" }, response_type=dict, specific_rate_limiter=torrent_limiter, overall_rate_limiter=overall_limiter, proxies=( - settings.settings.downloaders.real_debrid.proxy_url - if settings.settings.downloaders.real_debrid.proxy_enabled + settings_manager.settings.downloaders.real_debrid.proxy_url + if settings_manager.settings.downloaders.real_debrid.proxy_enabled else None ), ).data diff --git a/src/program/downloaders/shared.py b/src/program/downloaders/shared.py index 9b5f66b5..442cf563 100644 --- a/src/program/downloaders/shared.py +++ b/src/program/downloaders/shared.py @@ -1,6 +1,7 @@ from RTN import parse from abc import ABC, abstractmethod +from loguru import logger from program.media.item import MediaItem from program.media.state import States from program.settings.manager import settings_manager @@ -129,9 +130,31 @@ class FileFinder: filename_attr (str): The name of the file attribute. """ + min_movie_filesize = settings_manager.settings.downloaders.movie_filesize_mb_min + max_movie_filesize = settings_manager.settings.downloaders.movie_filesize_mb_max + min_episode_filesize = settings_manager.settings.downloaders.episode_filesize_mb_min + max_episode_filesize = settings_manager.settings.downloaders.episode_filesize_mb_max + are_filesizes_valid = False + def __init__(self, name, size): self.filename_attr = name self.filesize_attr = size + self.are_filesizes_valid = self._validate_filesizes() + + def _validate_filesizes(self) -> bool: + if not isinstance(settings_manager.settings.downloaders.movie_filesize_mb_min, int) or settings_manager.settings.downloaders.movie_filesize_mb_min < -1: + logger.error("Movie filesize min is not set or invalid.") + return False + if not isinstance(settings_manager.settings.downloaders.movie_filesize_mb_max, int) or settings_manager.settings.downloaders.movie_filesize_mb_max < -1: + logger.error("Movie filesize max is not set or invalid.") + return False + if not isinstance(settings_manager.settings.downloaders.episode_filesize_mb_min, int) or settings_manager.settings.downloaders.episode_filesize_mb_min < -1: + logger.error("Episode filesize min is not set or invalid.") + return False + if not isinstance(settings_manager.settings.downloaders.episode_filesize_mb_max, int) or settings_manager.settings.downloaders.episode_filesize_mb_max < -1: + logger.error("Episode filesize max is not set or invalid.") + return False + return True def get_cached_container( self, @@ -160,6 +183,28 @@ def filename_matches_movie(self, filename): return parsed_data.type == "movie" except Exception: return None + + def filesize_is_acceptable_movie(self, filesize): + if not self.are_filesizes_valid: + logger.error("Filesize settings are invalid, movie file sizes will not be checked.") + return True + min_size = settings_manager.settings.downloaders.movie_filesize_mb_min * 1_000_000 + max_size = settings_manager.settings.downloaders.movie_filesize_mb_max * 1_000_000 if settings_manager.settings.downloaders.movie_filesize_mb_max != -1 else float("inf") + is_acceptable = min_size <= filesize <= max_size + if not is_acceptable: + logger.debug(f"Filesize {filesize} is not within acceptable range {min_size} - {max_size}") + return is_acceptable + + def filesize_is_acceptable_show(self, filesize): + if not self.are_filesizes_valid: + logger.error("Filesize settings are invalid, episode file sizes will not be checked.") + return True + min_size = settings_manager.settings.downloaders.episode_filesize_mb_min * 1_000_000 + max_size = settings_manager.settings.downloaders.episode_filesize_mb_max * 1_000_000 if settings_manager.settings.downloaders.episode_filesize_mb_max != -1 else float("inf") + is_acceptable = min_size <= filesize <= max_size + if not is_acceptable: + logger.debug(f"Filesize {filesize} is not within acceptable range {min_size} - {max_size}") + return is_acceptable def cache_matches( self, @@ -184,7 +229,7 @@ def cache_matches( ) if matched_season and matched_episodes: for episode in matched_episodes: - if (matched_season, episode) in needed_episodes: + if (matched_season, episode) in needed_episodes and self.filesize_is_acceptable_show(file[self.filesize_attr]): if matched_season not in matches_dict: matches_dict[matched_season] = {} matches_dict[matched_season][episode] = file @@ -198,7 +243,7 @@ def cache_matches( ) if biggest_file and self.filename_matches_movie( biggest_file[self.filename_attr] - ): + ) and self.filesize_is_acceptable_movie(biggest_file[self.filesize_attr]): return {1: {1: biggest_file}} diff --git a/src/program/settings/models.py b/src/program/settings/models.py index d70da153..94e611e7 100644 --- a/src/program/settings/models.py +++ b/src/program/settings/models.py @@ -63,10 +63,10 @@ class TorboxModel(Observable): class DownloadersModel(Observable): video_extensions: List[str] = ["mp4", "mkv", "avi"] prefer_speed_over_quality: bool = True - # movie_filesize_min: int = 200 # MB - # movie_filesize_max: int = -1 # MB (-1 is no limit) - # episode_filesize_min: int = 40 # MB - # episode_filesize_max: int = -1 # MB (-1 is no limit) + movie_filesize_mb_min: int = -1 # MB + movie_filesize_mb_max: int = -1 # MB (-1 is no limit) + episode_filesize_mb_min: int = -1 # MB + episode_filesize_mb_max: int = -1 # MB (-1 is no limit) real_debrid: RealDebridModel = RealDebridModel() all_debrid: AllDebridModel = AllDebridModel() torbox: TorboxModel = TorboxModel()