diff --git a/config.example.toml b/config.example.toml index 75041a4d..3748e05e 100644 --- a/config.example.toml +++ b/config.example.toml @@ -169,4 +169,5 @@ primary_languages = [""] default_language = "en" [metadata.tvdb] -tvdb_relay_url = "https://metadata-relay.dorninger.co/tvdb" \ No newline at end of file +tvdb_relay_url = "https://metadata-relay.dorninger.co/tvdb" +primary_languages = [""] \ No newline at end of file diff --git a/docs/advanced-features/metadata-provider-configuration.md b/docs/advanced-features/metadata-provider-configuration.md index 2444f037..6daf0bce 100644 --- a/docs/advanced-features/metadata-provider-configuration.md +++ b/docs/advanced-features/metadata-provider-configuration.md @@ -15,7 +15,7 @@ Other software like Jellyfin use TMDB as well, so there won't be any metadata di * `tmdb_relay_url`\ URL of the TMDB relay (MetadataRelay). Default is `https://metadata-relay.dorninger.co/tmdb`. Example: `https://your-own-relay.example.com/tmdb`. * `primary_languages`\ - If the original language of a show/movie is in this list, metadata is fetched in that language. Otherwise, `default_language` is used. Default is `[]`. Example: `["no", "de", "es"]`. Format: ISO 639-1 (2 letters). Full list: https://en.wikipedia.org/wiki/List\_of\_ISO\_639\_language\_codes + If the original language of a show/movie is in this list, metadata is displayed and fetched in that language. Otherwise, `default_language` is used. Default is `[]`. Example: `["no", "de", "es"]`. Format: ISO 639-1 (2 letters). Full list: https://en.wikipedia.org/wiki/List\_of\_ISO\_639\_language\_codes * `default_language`\ TMDB language parameter used when searching and adding. Default is `en`. Format: ISO 639-1 (2 letters). @@ -26,11 +26,13 @@ Other software like Jellyfin use TMDB as well, so there won't be any metadata di ### TVDB Settings (`[metadata.tvdb]`) {% hint style="warning" %} -The TVDB might provide false metadata and doesn't support some features of MediaManager like showing overviews. Therefore, TMDB is the preferred metadata provider. +The TVDB might provide false metadata. Therefore, TMDB is the preferred metadata provider. {% endhint %} * `tvdb_relay_url`\ URL of the TVDB relay (MetadataRelay). Default is `https://metadata-relay.dorninger.co/tvdb`. Example: `https://your-own-relay.example.com/tvdb`. +* `primary_languages`\ + If the original language of a show/movie is in this list, metadata is displayed and fetched in that language. Default is `[]`. Example: `["eng", "deu", "spa"]`. Format: ISO 639-3 (3 letters). Full list: https://en.wikipedia.org/wiki/List\_of\_ISO\_639\_language\_codes ### MetadataRelay @@ -61,10 +63,13 @@ Here's a complete example of the metadata section in your `config.toml`: # TMDB configuration [metadata.tmdb] tmdb_relay_url = "https://metadata-relay.dorninger.co/tmdb" + primary_languages = ["no", "de"] + default_language = "en" # TVDB configuration [metadata.tvdb] tvdb_relay_url = "https://metadata-relay.dorninger.co/tvdb" + primary_languages = ["nor", "deu"] ``` {% endcode %} diff --git a/media_manager/metadataProvider/abstract_metadata_provider.py b/media_manager/metadataProvider/abstract_metadata_provider.py index 28935e53..e51c7fca 100644 --- a/media_manager/metadataProvider/abstract_metadata_provider.py +++ b/media_manager/metadataProvider/abstract_metadata_provider.py @@ -19,13 +19,13 @@ def name(self) -> str: @abstractmethod def get_show_metadata( - self, show_id: int, language: str | None = None + self, show_id: int, original_language: str | None = None ) -> Show: raise NotImplementedError() @abstractmethod def get_movie_metadata( - self, movie_id: int, language: str | None = None + self, movie_id: int, original_language: str | None = None ) -> Movie: raise NotImplementedError() diff --git a/media_manager/metadataProvider/config.py b/media_manager/metadataProvider/config.py index 4f07b469..ca4685c9 100644 --- a/media_manager/metadataProvider/config.py +++ b/media_manager/metadataProvider/config.py @@ -9,6 +9,7 @@ class TmdbConfig(BaseSettings): class TvdbConfig(BaseSettings): tvdb_relay_url: str = "https://metadata-relay.dorninger.co/tvdb" + primary_languages: list[str] = [] # ISO 639-3 language codes class MetadataProviderConfig(BaseSettings): diff --git a/media_manager/metadataProvider/tmdb.py b/media_manager/metadataProvider/tmdb.py index 1acb30fd..ba2b24db 100644 --- a/media_manager/metadataProvider/tmdb.py +++ b/media_manager/metadataProvider/tmdb.py @@ -27,202 +27,159 @@ def __init__(self) -> None: self.primary_languages = config.primary_languages self.default_language = config.default_language - def __get_language_param(self, original_language: str | None) -> str: + def __make_tmdb_request( + self, + endpoint: str, + params: dict | None = None, + original_language: str | None = None, + context: str = "TMDB API request", + ) -> dict: """ - Determine the language parameter to use for TMDB API calls. - Returns the original language if it's in primary_languages, otherwise returns default_language. + Make a TMDB API request with automatic language handling. - :param original_language: The original language code (ISO 639-1) of the media - :return: Language parameter (ISO 639-1 format, e.g., 'en', 'no') + :param endpoint: API endpoint path (e.g., '/tv/shows/12345') + :param params: Query parameters (language will be added automatically) + :param original_language: Original language code to check against primary_languages + :param context: Description for error messages + :return: JSON response as dict """ - if original_language and original_language in self.primary_languages: - return original_language - return self.default_language + if params is None: + params = {} + + # Determine and validate language parameter + selected_language = self.default_language + if original_language: + # Validate it's a 2-letter ISO 639-1 code + if len(original_language) == 2 and original_language in self.primary_languages: + selected_language = original_language + elif len(original_language) != 2: + log.warning( + f"Invalid language code '{original_language}' (must be 2 letters), using default" + ) + + # Always set language parameter + params["language"] = selected_language - def __get_show_metadata(self, show_id: int, language: str | None = None) -> dict: - if language is None: - language = self.default_language try: response = requests.get( - url=f"{self.url}/tv/shows/{show_id}", - params={"language": language}, + url=f"{self.url}{endpoint}", + params=params, timeout=60, ) response.raise_for_status() return response.json() except requests.RequestException as e: - log.error(f"TMDB API error getting show metadata for ID {show_id}: {e}") + log.error(f"TMDB API error for {context}: {e}") if notification_manager.is_configured(): notification_manager.send_notification( title="TMDB API Error", - message=f"Failed to fetch show metadata for ID {show_id} from TMDB. Error: {e}", + message=f"Failed to {context}. Error: {e}", ) raise - def __get_show_external_ids(self, show_id: int) -> dict: - try: - response = requests.get( - url=f"{self.url}/tv/shows/{show_id}/external_ids", - timeout=60, + def __get_show_metadata( + self, show_id: int, original_language: str | None = None + ) -> dict: + # If original_language not provided, fetch once to determine it + if original_language is None: + initial_metadata = self.__make_tmdb_request( + endpoint=f"/tv/shows/{show_id}", + context=f"get show metadata for ID {show_id}", ) - response.raise_for_status() - return response.json() - except requests.RequestException as e: - log.error(f"TMDB API error getting show external IDs for ID {show_id}: {e}") - if notification_manager.is_configured(): - notification_manager.send_notification( - title="TMDB API Error", - message=f"Failed to fetch show external IDs for ID {show_id} from TMDB. Error: {e}", + original_language = initial_metadata.get("original_language") + # If we now have the language, fetch again with proper language parameter + if original_language: + return self.__make_tmdb_request( + endpoint=f"/tv/shows/{show_id}", + original_language=original_language, + context=f"get show metadata for ID {show_id}", ) - raise + return initial_metadata + + return self.__make_tmdb_request( + endpoint=f"/tv/shows/{show_id}", + original_language=original_language, + context=f"get show metadata for ID {show_id}", + ) + + def __get_show_external_ids(self, show_id: int) -> dict: + return self.__make_tmdb_request( + endpoint=f"/tv/shows/{show_id}/external_ids", + context=f"get show external IDs for ID {show_id}", + ) def __get_season_metadata( - self, show_id: int, season_number: int, language: str | None = None + self, show_id: int, season_number: int, original_language: str | None = None ) -> dict: - if language is None: - language = self.default_language - try: - response = requests.get( - url=f"{self.url}/tv/shows/{show_id}/{season_number}", - params={"language": language}, - timeout=60, - ) - response.raise_for_status() - return response.json() - except requests.RequestException as e: - log.error( - f"TMDB API error getting season {season_number} metadata for show ID {show_id}: {e}" - ) - if notification_manager.is_configured(): - notification_manager.send_notification( - title="TMDB API Error", - message=f"Failed to fetch season {season_number} metadata for show ID {show_id} from TMDB. Error: {e}", - ) - raise + return self.__make_tmdb_request( + endpoint=f"/tv/shows/{show_id}/{season_number}", + original_language=original_language, + context=f"get season {season_number} metadata for show ID {show_id}", + ) def __search_tv(self, query: str, page: int) -> dict: - try: - response = requests.get( - url=f"{self.url}/tv/search", - params={ - "query": query, - "page": page, - }, - timeout=60, - ) - response.raise_for_status() - return response.json() - except requests.RequestException as e: - log.error(f"TMDB API error searching TV shows with query '{query}': {e}") - if notification_manager.is_configured(): - notification_manager.send_notification( - title="TMDB API Error", - message=f"Failed to search TV shows with query '{query}' on TMDB. Error: {e}", - ) - raise + return self.__make_tmdb_request( + endpoint="/tv/search", + params={"query": query, "page": page}, + context=f"search TV shows with query '{query}'", + ) def __get_trending_tv(self) -> dict: - try: - response = requests.get( - url=f"{self.url}/tv/trending", - params={"language": self.default_language}, - timeout=60, - ) - response.raise_for_status() - return response.json() - except requests.RequestException as e: - log.error(f"TMDB API error getting trending TV: {e}") - if notification_manager.is_configured(): - notification_manager.send_notification( - title="TMDB API Error", - message=f"Failed to fetch trending TV shows from TMDB. Error: {e}", - ) - raise + return self.__make_tmdb_request( + endpoint="/tv/trending", + context="get trending TV shows", + ) - def __get_movie_metadata(self, movie_id: int, language: str | None = None) -> dict: - if language is None: - language = self.default_language - try: - response = requests.get( - url=f"{self.url}/movies/{movie_id}", - params={"language": language}, - timeout=60, + def __get_movie_metadata( + self, movie_id: int, original_language: str | None = None + ) -> dict: + # If original_language not provided, fetch once to determine it + if original_language is None: + initial_metadata = self.__make_tmdb_request( + endpoint=f"/movies/{movie_id}", + context=f"get movie metadata for ID {movie_id}", ) - response.raise_for_status() - return response.json() - except requests.RequestException as e: - log.error(f"TMDB API error getting movie metadata for ID {movie_id}: {e}") - if notification_manager.is_configured(): - notification_manager.send_notification( - title="TMDB API Error", - message=f"Failed to fetch movie metadata for ID {movie_id} from TMDB. Error: {e}", + original_language = initial_metadata.get("original_language") + # If we now have the language, fetch again with proper language parameter + if original_language: + return self.__make_tmdb_request( + endpoint=f"/movies/{movie_id}", + original_language=original_language, + context=f"get movie metadata for ID {movie_id}", ) - raise + return initial_metadata + + return self.__make_tmdb_request( + endpoint=f"/movies/{movie_id}", + original_language=original_language, + context=f"get movie metadata for ID {movie_id}", + ) def __get_movie_external_ids(self, movie_id: int) -> dict: - try: - response = requests.get( - url=f"{self.url}/movies/{movie_id}/external_ids", timeout=60 - ) - response.raise_for_status() - return response.json() - except requests.RequestException as e: - log.error( - f"TMDB API error getting movie external IDs for ID {movie_id}: {e}" - ) - if notification_manager.is_configured(): - notification_manager.send_notification( - title="TMDB API Error", - message=f"Failed to fetch movie external IDs for ID {movie_id} from TMDB. Error: {e}", - ) - raise + return self.__make_tmdb_request( + endpoint=f"/movies/{movie_id}/external_ids", + context=f"get movie external IDs for ID {movie_id}", + ) def __search_movie(self, query: str, page: int) -> dict: - try: - response = requests.get( - url=f"{self.url}/movies/search", - params={ - "query": query, - "page": page, - }, - timeout=60, - ) - response.raise_for_status() - return response.json() - except requests.RequestException as e: - log.error(f"TMDB API error searching movies with query '{query}': {e}") - if notification_manager.is_configured(): - notification_manager.send_notification( - title="TMDB API Error", - message=f"Failed to search movies with query '{query}' on TMDB. Error: {e}", - ) - raise + return self.__make_tmdb_request( + endpoint="/movies/search", + params={"query": query, "page": page}, + context=f"search movies with query '{query}'", + ) def __get_trending_movies(self) -> dict: - try: - response = requests.get( - url=f"{self.url}/movies/trending", - params={"language": self.default_language}, - timeout=60, - ) - response.raise_for_status() - return response.json() - except requests.RequestException as e: - log.error(f"TMDB API error getting trending movies: {e}") - if notification_manager.is_configured(): - notification_manager.send_notification( - title="TMDB API Error", - message=f"Failed to fetch trending movies from TMDB. Error: {e}", - ) - raise + return self.__make_tmdb_request( + endpoint="/movies/trending", + context="get trending movies", + ) @override def download_show_poster_image(self, show: Show) -> bool: - # Determine which language to use based on show's original_language - language = self.__get_language_param(show.original_language) - # Fetch metadata in the appropriate language to get localized poster - show_metadata = self.__get_show_metadata(show.external_id, language=language) + show_metadata = self.__get_show_metadata( + show.external_id, original_language=show.original_language + ) # downloading the poster # all pictures from TMDB should already be jpeg, so no need to convert @@ -244,27 +201,20 @@ def download_show_poster_image(self, show: Show) -> bool: @override def get_show_metadata( - self, show_id: int, language: str | None = None + self, show_id: int, original_language: str | None = None ) -> Show: """ :param show_id: the external id of the show :type show_id: int - :param language: optional language code (ISO 639-1) to fetch metadata in - :type language: str | None + :param original_language: optional original language code (ISO 639-1) to fetch metadata in + :type original_language: str | None :return: returns a Show object :rtype: Show """ - # If language not provided, fetch once to determine original language - if language is None: - show_metadata = self.__get_show_metadata(show_id) - language = show_metadata.get("original_language") - - # Determine which language to use for metadata - language = self.__get_language_param(language) - - # Fetch show metadata in the appropriate language - show_metadata = self.__get_show_metadata(show_id, language=language) + # Fetch show metadata (language handling is done internally) + show_metadata = self.__get_show_metadata(show_id, original_language=original_language) + original_language = show_metadata.get("original_language") # get imdb id external_ids = self.__get_show_external_ids(show_id=show_id) @@ -276,7 +226,7 @@ def get_show_metadata( season_metadata = self.__get_season_metadata( show_id=show_metadata["id"], season_number=season["season_number"], - language=language, + original_language=original_language, ) episode_list = [ Episode( @@ -309,7 +259,7 @@ def get_show_metadata( seasons=season_list, metadata_provider=self.name, ended=show_metadata["status"] in ENDED_STATUS, - original_language=show_metadata.get("original_language"), + original_language=original_language, imdb_id=imdb_id, ) @@ -374,28 +324,21 @@ def search_show( @override def get_movie_metadata( - self, movie_id: int, language: str | None = None + self, movie_id: int, original_language: str | None = None ) -> Movie: """ Get movie metadata with language-aware fetching. :param movie_id: the external id of the movie :type movie_id: int - :param language: optional language code (ISO 639-1) to fetch metadata in - :type language: str | None + :param original_language: optional original language code (ISO 639-1) to fetch metadata in + :type original_language: str | None :return: returns a Movie object :rtype: Movie """ - # If language not provided, fetch once to determine original language - if language is None: - movie_metadata = self.__get_movie_metadata(movie_id=movie_id) - language = movie_metadata.get("original_language") - - # Determine which language to use for metadata - language = self.__get_language_param(language) - - # Fetch movie metadata in the appropriate language - movie_metadata = self.__get_movie_metadata(movie_id=movie_id, language=language) + # Fetch movie metadata (language handling is done internally) + movie_metadata = self.__get_movie_metadata(movie_id=movie_id, original_language=original_language) + original_language = movie_metadata.get("original_language") # get imdb id external_ids = self.__get_movie_external_ids(movie_id=movie_id) @@ -411,7 +354,7 @@ def get_movie_metadata( overview=movie_metadata["overview"], year=year, metadata_provider=self.name, - original_language=movie_metadata.get("original_language"), + original_language=original_language, imdb_id=imdb_id, ) @@ -476,12 +419,9 @@ def search_movie( @override def download_movie_poster_image(self, movie: Movie) -> bool: - # Determine which language to use based on movie's original_language - language = self.__get_language_param(movie.original_language) - # Fetch metadata in the appropriate language to get localized poster movie_metadata = self.__get_movie_metadata( - movie_id=movie.external_id, language=language + movie_id=movie.external_id, original_language=movie.original_language ) # downloading the poster diff --git a/media_manager/metadataProvider/tvdb.py b/media_manager/metadataProvider/tvdb.py index 616ae746..37059751 100644 --- a/media_manager/metadataProvider/tvdb.py +++ b/media_manager/metadataProvider/tvdb.py @@ -10,6 +10,7 @@ ) from media_manager.metadataProvider.schemas import MetaDataProviderSearchResult from media_manager.movies.schemas import Movie +from media_manager.notification.manager import notification_manager from media_manager.tv.schemas import Episode, Season, SeasonNumber, Show log = logging.getLogger(__name__) @@ -21,31 +22,85 @@ class TvdbMetadataProvider(AbstractMetadataProvider): def __init__(self) -> None: config = MediaManagerConfig().metadata.tvdb self.url = config.tvdb_relay_url + self.primary_languages = config.primary_languages + + def __make_tvdb_request( + self, + endpoint: str, + params: dict | None = None, + context: str = "TVDB API request", + ) -> dict: + """ + Make a TVDB API request with error handling and notifications. + + :param endpoint: API endpoint path (e.g., '/tv/shows/12345') + :param params: Query parameters + :param context: Description for error messages + :return: JSON response as dict + """ + if params is None: + params = {} + + try: + response = requests.get( + url=f"{self.url}{endpoint}", + params=params, + timeout=60, + ) + response.raise_for_status() + return response.json() + except requests.RequestException as e: + log.error(f"TVDB API error for {context}: {e}") + if notification_manager.is_configured(): + notification_manager.send_notification( + title="TVDB API Error", + message=f"Failed to {context}. Error: {e}", + ) + raise def __get_show(self, show_id: int) -> dict: - return requests.get(url=f"{self.url}/tv/shows/{show_id}", timeout=60).json() + return self.__make_tvdb_request( + endpoint=f"/tv/shows/{show_id}", + context=f"get show metadata for ID {show_id}", + ) def __get_season(self, show_id: int) -> dict: - return requests.get(url=f"{self.url}/tv/seasons/{show_id}", timeout=60).json() + return self.__make_tvdb_request( + endpoint=f"/tv/seasons/{show_id}", + context=f"get season metadata for ID {show_id}", + ) def __search_tv(self, query: str) -> dict: - return requests.get( - url=f"{self.url}/tv/search", params={"query": query}, timeout=60 - ).json() + return self.__make_tvdb_request( + endpoint="/tv/search", + params={"query": query}, + context=f"search TV shows with query '{query}'", + ) def __get_trending_tv(self) -> dict: - return requests.get(url=f"{self.url}/tv/trending", timeout=60).json() + return self.__make_tvdb_request( + endpoint="/tv/trending", + context="get trending TV shows", + ) def __get_movie(self, movie_id: int) -> dict: - return requests.get(url=f"{self.url}/movies/{movie_id}", timeout=60).json() + return self.__make_tvdb_request( + endpoint=f"/movies/{movie_id}", + context=f"get movie metadata for ID {movie_id}", + ) def __search_movie(self, query: str) -> dict: - return requests.get( - url=f"{self.url}/movies/search", params={"query": query}, timeout=60 - ).json() + return self.__make_tvdb_request( + endpoint="/movies/search", + params={"query": query}, + context=f"search movies with query '{query}'", + ) def __get_trending_movies(self) -> dict: - return requests.get(url=f"{self.url}/movies/trending", timeout=60).json() + return self.__make_tvdb_request( + endpoint="/movies/trending", + context="get trending movies", + ) @override def download_show_poster_image(self, show: Show) -> bool: @@ -57,21 +112,31 @@ def download_show_poster_image(self, show: Show) -> bool: poster_url=show_metadata["image"], uuid=show.id, ) - log.debug("Successfully downloaded poster image for show " + show.name) + log.info("Successfully downloaded poster image for show " + show.name) return True log.warning(f"image for show {show.name} could not be downloaded") return False @override def get_show_metadata( - self, show_id: int, language: str | None = None + self, show_id: int, original_language: str | None = None ) -> Show: """ + Get show metadata with language-aware fetching. :param show_id: The external id of the show - :param language: does nothing, TVDB does not support multiple languages + :type show_id: int + :param original_language: optional original language code (ISO 639-1) to fetch metadata in + :type original_language: str | None + :return: returns a Show object + :rtype: Show """ series = self.__get_show(show_id) + + # Extract original language from the response if not provided + if original_language is None: + original_language = series.get("original_language") + seasons = [] seasons_ids = [season["id"] for season in series["seasons"]] @@ -120,6 +185,7 @@ def get_show_metadata( metadata_provider=self.name, seasons=seasons, ended=False, + original_language=original_language, imdb_id=imdb_id, ) @@ -148,6 +214,7 @@ def search_show( metadata_provider=self.name, added=False, vote_average=None, + original_language=result.get("primary_language"), ) ) except Exception as e: @@ -176,6 +243,7 @@ def search_show( metadata_provider=self.name, added=False, vote_average=None, + original_language=result.get("primary_language"), ) ) except Exception as e: @@ -192,12 +260,10 @@ def search_movie( log.debug(f"got {len(results)} results from TVDB search") formatted_results = [] for result in results: - if result["type"] != "movie": - continue - - result = self.__get_movie(result["tvdb_id"]) - try: + if result["type"] != "movie": + continue + try: year = result["year"] except KeyError: @@ -213,6 +279,7 @@ def search_movie( metadata_provider=self.name, added=False, vote_average=None, + original_language=result.get("primary_language"), ) ) except Exception as e: @@ -223,7 +290,6 @@ def search_movie( log.debug(f"got {len(results)} results from TVDB search") formatted_results = [] for result in results: - result = self.__get_movie(result["id"]) try: try: year = result["year"] @@ -237,9 +303,7 @@ def search_movie( formatted_results.append( MetaDataProviderSearchResult( - poster_path= poster_path - if result.get("image") - else None, + poster_path=poster_path, overview=result.get("overview"), name=result["name"], external_id=result["id"], @@ -247,6 +311,7 @@ def search_movie( metadata_provider=self.name, added=False, vote_average=None, + original_language=result.get("primary_language"), ) ) except Exception as e: @@ -263,23 +328,30 @@ def download_movie_poster_image(self, movie: Movie) -> bool: poster_url=movie_metadata["image"], uuid=movie.id, ) - log.info("Successfully downloaded poster image for show " + movie.name) + log.info("Successfully downloaded poster image for movie " + movie.name) return True - log.warning(f"image for show {movie.name} could not be downloaded") + log.warning(f"image for movie {movie.name} could not be downloaded") return False @override def get_movie_metadata( - self, movie_id: int, language: str | None = None + self, movie_id: int, original_language: str | None = None ) -> Movie: """ + Get movie metadata with language support. :param movie_id: the external id of the movie - :param language: does nothing, TVDB does not support multiple languages + :type movie_id: int + :param original_language: optional original language code (ISO 639-1) + :type original_language: str | None :return: returns a Movie object """ movie = self.__get_movie(movie_id=movie_id) + # Extract original language from the response if not provided + if original_language is None: + original_language = movie.get("original_language") + # get imdb id from remote ids imdb_id = None remote_ids = movie.get("remoteIds", None) @@ -290,9 +362,10 @@ def get_movie_metadata( return Movie( name=movie["name"], - overview="Overviews are not supported with TVDB", + overview=movie.get("overview", "No overview available"), year=movie.get("year"), external_id=movie["id"], metadata_provider=self.name, imdb_id=imdb_id, + original_language=original_language, ) diff --git a/media_manager/metadataProvider/utils.py b/media_manager/metadataProvider/utils.py index bff3cbd6..483ba1b0 100644 --- a/media_manager/metadataProvider/utils.py +++ b/media_manager/metadataProvider/utils.py @@ -15,7 +15,7 @@ def download_poster_image(storage_path: Path, poster_url: str, uuid: UUID) -> bo res = requests.get(poster_url, stream=True, timeout=60) if res.status_code == 200: - image_file_path = storage_path.joinpath(str(uuid)).with_suffix("jpg") + image_file_path = storage_path.joinpath(str(uuid)).with_suffix(".jpg") image_file_path.write_bytes(res.content) original_image = Image.open(image_file_path) diff --git a/media_manager/movies/router.py b/media_manager/movies/router.py index 4c4ad353..1c919dd4 100644 --- a/media_manager/movies/router.py +++ b/media_manager/movies/router.py @@ -144,7 +144,7 @@ def add_a_movie( movie_service: movie_service_dep, metadata_provider: metadata_provider_dep, movie_id: int, - language: str | None = None, + original_language: str | None = None, ) -> Movie: """ Add a new movie to the library. @@ -153,7 +153,7 @@ def add_a_movie( movie = movie_service.add_movie( external_id=movie_id, metadata_provider=metadata_provider, - language=language, + original_language=original_language, ) except ConflictError: movie = movie_service.get_movie_by_external_id( @@ -256,7 +256,7 @@ def authorize_request( movie_request_id: MovieRequestId, user: Annotated[UserRead, Depends(current_superuser)], authorized_status: bool = False, -) -> MovieRequest: +) -> None: """ Authorize or de-authorize a movie request. """ diff --git a/media_manager/movies/service.py b/media_manager/movies/service.py index 3dd12b68..4a168235 100644 --- a/media_manager/movies/service.py +++ b/media_manager/movies/service.py @@ -70,17 +70,17 @@ def add_movie( self, external_id: int, metadata_provider: AbstractMetadataProvider, - language: str | None = None, + original_language: str | None = None, ) -> Movie: """ Add a new movie to the database. :param external_id: The ID of the movie in the metadata provider's system. :param metadata_provider: The name of the metadata provider. - :param language: Optional language code (ISO 639-1) to fetch metadata in. + :param original_language: Optional original language code (ISO 639-1) to fetch metadata in. """ movie_with_metadata = metadata_provider.get_movie_metadata( - movie_id=external_id, language=language + movie_id=external_id, original_language=original_language ) if not movie_with_metadata: raise NotFoundError @@ -722,7 +722,7 @@ def update_movie_metadata( # Use stored original_language preference for metadata fetching fresh_movie_data = metadata_provider.get_movie_metadata( - movie_id=db_movie.external_id, language=db_movie.original_language + movie_id=db_movie.external_id, original_language=db_movie.original_language ) if not fresh_movie_data: log.warning( diff --git a/media_manager/tv/router.py b/media_manager/tv/router.py index 8f33f756..fa606375 100644 --- a/media_manager/tv/router.py +++ b/media_manager/tv/router.py @@ -139,7 +139,7 @@ def add_a_show( tv_service: tv_service_dep, metadata_provider: metadata_provider_dep, show_id: int, - language: str | None = None, + original_language: str | None = None, ) -> Show: """ Add a new show to the library. @@ -148,7 +148,7 @@ def add_a_show( show = tv_service.add_show( external_id=show_id, metadata_provider=metadata_provider, - language=language, + original_language=original_language, ) except MediaAlreadyExistsError: show = tv_service.get_show_by_external_id( diff --git a/media_manager/tv/service.py b/media_manager/tv/service.py index 9ccc3507..b9e3e8d4 100644 --- a/media_manager/tv/service.py +++ b/media_manager/tv/service.py @@ -78,17 +78,17 @@ def add_show( self, external_id: int, metadata_provider: AbstractMetadataProvider, - language: str | None = None, + original_language: str | None = None, ) -> Show: """ Add a new show to the database. :param external_id: The ID of the show in the metadata provider\'s system. :param metadata_provider: The name of the metadata provider. - :param language: Optional language code (ISO 639-1) to fetch metadata in. + :param original_language: Optional original language code (ISO 639-1) to fetch metadata in. """ show_with_metadata = metadata_provider.get_show_metadata( - show_id=external_id, language=language + show_id=external_id, original_language=original_language ) saved_show = self.tv_repository.save_show(show=show_with_metadata) metadata_provider.download_show_poster_image(show=saved_show) @@ -765,7 +765,7 @@ def update_show_metadata( # Use stored original_language preference for metadata fetching fresh_show_data = metadata_provider.get_show_metadata( - show_id=db_show.external_id, language=db_show.original_language + show_id=db_show.external_id, original_language=db_show.original_language ) if not fresh_show_data: log.warning( diff --git a/web/src/lib/components/add-media-card.svelte b/web/src/lib/components/add-media-card.svelte index 5985b318..a7e3dbf6 100644 --- a/web/src/lib/components/add-media-card.svelte +++ b/web/src/lib/components/add-media-card.svelte @@ -23,7 +23,7 @@ query: { show_id: result.external_id, metadata_provider: result.metadata_provider as 'tmdb' | 'tvdb', - language: result.original_language ?? undefined + original_language: result.original_language ?? undefined } } }); @@ -34,7 +34,7 @@ query: { movie_id: result.external_id, metadata_provider: result.metadata_provider as 'tmdb' | 'tvdb', - language: result.original_language ?? undefined + original_language: result.original_language ?? undefined } } });