From af7185164756b3d232787897ef78a6917789eb59 Mon Sep 17 00:00:00 2001 From: meisnate12 Date: Tue, 8 Aug 2023 15:52:29 -0400 Subject: [PATCH] [81] all mass image operations to skip seasons and episodes --- VERSION | 2 +- docs/config/operations.md | 50 +++++++++++++++++++++++--------- modules/config.py | 61 ++++++++++++++++++++++----------------- modules/operations.py | 61 +++++++++++++++++++++------------------ modules/plex.py | 2 +- 5 files changed, 106 insertions(+), 70 deletions(-) diff --git a/VERSION b/VERSION index 92d799e6..2f20c50f 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -1.19.0-develop80 +1.19.0-develop81 diff --git a/docs/config/operations.md b/docs/config/operations.md index 2dbba167..25617326 100644 --- a/docs/config/operations.md +++ b/docs/config/operations.md @@ -240,14 +240,25 @@ Updates every item's poster to the chosen sites poster. Will fallback to `plex` **Attribute:** `mass_poster_update` -**Values:** +**Values:** There are a few different options to determine how the `mass_poster_update` works. + +| Attribute | Description | +|:--------------------|:----------------------------------------------------------------------------------------------------| +| `source` | Source of the poster update
**Values:** `tmdb`, `plex`, `lock`, or `unlock` | +| `seasons` | Update season posters while updating shows
**Default:** `true`
**Values:** `true` or `false` | +| `episodes` | Update episode posters while updating shows
**Default:** `true`
**Values:** `true` or `false` | + +**Example:** -| Value | Description | -|:---------|:----------------| -| `tmdb` | Use TMDb Poster | -| `plex` | Use Plex Poster | -| `lock` | Lock Poster | -| `unlock` | Unlock Poster | +```yaml +library: + TV Shows: + operations: + mass_poster_update: + source: tmdb + seasons: false + episodes: false +``` ## Mass Background Update @@ -255,14 +266,25 @@ Updates every item's background to the chosen sites background. Will fallback to **Attribute:** `mass_background_update` -**Values:** +**Values:** There are a few different options to determine how the `mass_background_update` works. + +| Attribute | Description | +|:--------------------|:--------------------------------------------------------------------------------------------------------| +| `source` | Source of the background update
**Values:** `tmdb`, `plex`, `lock`, or `unlock` | +| `seasons` | Update season backgrounds while updating shows
**Default:** `true`
**Values:** `true` or `false` | +| `episodes` | Update episode backgrounds while updating shows
**Default:** `true`
**Values:** `true` or `false` | + +**Example:** -| Value | Description | -|:---------|:--------------------| -| `tmdb` | Use TMDb Background | -| `plex` | Use Plex Background | -| `lock` | Lock Background | -| `unlock` | Unlock Background | +```yaml +library: + TV Shows: + operations: + mass_background_update: + source: tmdb + seasons: false + episodes: false +``` ## Mass IMDb Parental Labels diff --git a/modules/config.py b/modules/config.py index 7085f3d9..46ce11b4 100644 --- a/modules/config.py +++ b/modules/config.py @@ -41,34 +41,34 @@ imdb_label_options = { "severe": "Add IMDb Parental Labels for Severe" } mass_genre_options = { - "lock": "Unlock Genre", "unlock": "Unlock Genre", "remove": "Remove and Lock Genre", "reset": "Remove and Unlock Genre", + "lock": "Lock Genre", "unlock": "Unlock Genre", "remove": "Remove and Lock Genre", "reset": "Remove and Unlock Genre", "tmdb": "Use TMDb Genres", "imdb": "Use IMDb Genres", "omdb": "Use IMDb Genres through OMDb", "tvdb": "Use TVDb Genres", "anidb": "Use AniDB Main Tags", "anidb_all": "Use All AniDB Tags", "mal": "Use MyAnimeList Genres" } mass_content_options = { - "lock": "Unlock Rating", "unlock": "Unlock Rating", "remove": "Remove and Lock Rating", "reset": "Remove and Unlock Rating", + "lock": "Lock Rating", "unlock": "Unlock Rating", "remove": "Remove and Lock Rating", "reset": "Remove and Unlock Rating", "omdb": "Use IMDb Rating through OMDb", "mdb": "Use MdbList Rating", "mdb_commonsense": "Use Commonsense Rating through MDbList", "mdb_commonsense0": "Use Commonsense Rating with Zero Padding through MDbList", "mal": "Use MyAnimeList Rating" } mass_studio_options = { - "lock": "Unlock Rating", "unlock": "Unlock Rating", "remove": "Remove and Lock Rating", "reset": "Remove and Unlock Rating", + "lock": "Lock Rating", "unlock": "Unlock Rating", "remove": "Remove and Lock Rating", "reset": "Remove and Unlock Rating", "tmdb": "Use TMDb Studio", "anidb": "Use AniDB Animation Work", "mal": "Use MyAnimeList Studio" } mass_original_title_options = { - "lock": "Unlock Original Title", "unlock": "Unlock Original Title", "remove": "Remove and Lock Original Title", "reset": "Remove and Unlock Original Title", + "lock": "Lock Original Title", "unlock": "Unlock Original Title", "remove": "Remove and Lock Original Title", "reset": "Remove and Unlock Original Title", "anidb": "Use AniDB Main Title", "anidb_official": "Use AniDB Official Title based on the language attribute in the config file", "mal": "Use MyAnimeList Main Title", "mal_english": "Use MyAnimeList English Title", "mal_japanese": "Use MyAnimeList Japanese Title", } mass_available_options = { - "lock": "Unlock Originally Available", "unlock": "Unlock Originally Available", "remove": "Remove and Lock Originally Available", "reset": "Remove and Unlock Originally Available", + "lock": "Lock Originally Available", "unlock": "Unlock Originally Available", "remove": "Remove and Lock Originally Available", "reset": "Remove and Unlock Originally Available", "tmdb": "Use TMDb Release", "omdb": "Use IMDb Release through OMDb", "mdb": "Use MdbList Release", "tvdb": "Use TVDb Release", "anidb": "Use AniDB Release", "mal": "Use MyAnimeList Release" } mass_image_options = { - "plex": "Use Plex Images", "tmdb": "Use TMDb Images" + "lock": "Lock Image", "unlock": "Unlock Image", "plex": "Use Plex Images", "tmdb": "Use TMDb Images" } mass_episode_rating_options = { - "lock": "Unlock Rating", "unlock": "Unlock Rating", "remove": "Remove and Lock Rating", "reset": "Remove and Unlock Rating", + "lock": "Lock Rating", "unlock": "Unlock Rating", "remove": "Remove and Lock Rating", "reset": "Remove and Unlock Rating", "tmdb": "Use TMDb Rating", "imdb": "Use IMDb Rating" } mass_rating_options = { @@ -106,9 +106,8 @@ library_operations = { "mass_user_rating_update": mass_rating_options, "mass_episode_user_rating_update": mass_episode_rating_options, "mass_original_title_update": mass_original_title_options, "mass_originally_available_update": mass_available_options, "mass_imdb_parental_labels": imdb_label_options, "mass_episode_imdb_parental_labels": imdb_label_options, - "mass_poster_update": mass_image_options, "mass_background_update": mass_image_options, - "mass_collection_mode": "mass_collection_mode", "metadata_backup": "metadata_backup", "delete_collections": "delete_collections", - "genre_mapper": "mapper", "content_rating_mapper": "mapper", + "mass_collection_mode": "mass_collection_mode", "mass_poster_update": "dict", "mass_background_update": "dict", + "metadata_backup": "dict", "delete_collections": "dict", "genre_mapper": "dict", "content_rating_mapper": "dict", } class ConfigFile: @@ -769,37 +768,47 @@ class ConfigFile: for op, data_type in library_operations.items(): if op not in lib["operations"]: continue - elif isinstance(data_type, list): + if isinstance(data_type, list): params[op] = check_for_attribute(lib["operations"], op, test_list=data_type, default_is_none=True, save=False) - elif data_type == "mass_collection_mode": + elif op == "mass_collection_mode": params[op] = util.check_collection_mode(lib["operations"][op]) - elif data_type in ["metadata_backup", "mapper", "delete_collections"]: - if not lib["operations"][op] or not isinstance(lib["operations"][op], dict): + elif data_type == "dict": + input_dict = lib["operations"][op] + if op in ["mass_poster_update", "mass_background_update"] and input_dict and not isinstance(input_dict, dict): + input_dict = {"source": input_dict} + + if not input_dict or not isinstance(input_dict, dict): raise Failed(f"Config Error: {op} must be a dictionary") - if data_type == "metadata_backup": + if op in ["mass_poster_update", "mass_background_update"]: + params[op] = { + "source": check_for_attribute(input_dict, "source", test_list=mass_image_options, default_is_none=True, save=False), + "seasons": check_for_attribute(input_dict, "seasons", var_type="bool", default=True, save=False), + "episodes": check_for_attribute(input_dict, "episodes", var_type="bool", default=True, save=False), + } + if op == "metadata_backup": default_path = os.path.join(default_dir, f"{str(library_name)}_Metadata_Backup.yml") try: - default_path = check_for_attribute(lib["operations"][op], "path", var_type="path", save=False) + default_path = check_for_attribute(input_dict, "path", var_type="path", save=False) except Failed as e: logger.debug(f"{e} using default {default_path}") params[op] = { "path": default_path, - "exclude": check_for_attribute(lib["operations"][op], "exclude", var_type="comma_list", default_is_none=True, save=False), - "sync_tags": check_for_attribute(lib["operations"][op], "sync_tags", var_type="bool", default=False, save=False), - "add_blank_entries": check_for_attribute(lib["operations"][op], "add_blank_entries", var_type="bool", default=True, save=False) + "exclude": check_for_attribute(input_dict, "exclude", var_type="comma_list", default_is_none=True, save=False), + "sync_tags": check_for_attribute(input_dict, "sync_tags", var_type="bool", default=False, save=False), + "add_blank_entries": check_for_attribute(input_dict, "add_blank_entries", var_type="bool", default=True, save=False) } - if data_type == "mapper": - params[op] = lib["operations"][op] - for old_value, new_value in lib["operations"][op].items(): + if "mapper" in op: + params[op] = input_dict + for old_value, new_value in input_dict.items(): if old_value == new_value: logger.warning(f"Config Warning: {op} value '{new_value}' ignored as it cannot be mapped to itself") else: params[op][old_value] = new_value if new_value else None - if data_type == "delete_collections": + if op == "delete_collections": params[op] = { - "managed": check_for_attribute(lib["operations"][op], "managed", var_type="bool", default_is_none=True, save=False), - "configured": check_for_attribute(lib["operations"][op], "configured", var_type="bool", default_is_none=True, save=False), - "less": check_for_attribute(lib["operations"][op], "less", var_type="int", default_is_none=True, save=False, int_min=1), + "managed": check_for_attribute(input_dict, "managed", var_type="bool", default_is_none=True, save=False), + "configured": check_for_attribute(input_dict, "configured", var_type="bool", default_is_none=True, save=False), + "less": check_for_attribute(input_dict, "less", var_type="int", default_is_none=True, save=False, int_min=1), } else: params[op] = check_for_attribute(lib["operations"], op, var_type=data_type, default=False, save=False) diff --git a/modules/operations.py b/modules/operations.py index bd7baf07..eacd1c21 100644 --- a/modules/operations.py +++ b/modules/operations.py @@ -516,7 +516,10 @@ class Operations: if self.library.mass_background_update: self.library.background_update(item, new_background, tmdb=tmdb_item.backdrop_url if tmdb_item else None) - if self.library.is_show: + if self.library.is_show and ( + self.library.mass_poster_update["seasons"] or self.library.mass_poster_update["episodes"] or + self.library.mass_background_update["seasons"] or self.library.mass_background_update["episodes"] + ): real_show = None try: real_show = tmdb_item.load_show() if tmdb_item else None @@ -524,37 +527,39 @@ class Operations: logger.error(e) tmdb_seasons = {s.season_number: s for s in real_show.seasons} if real_show else {} for season in self.library.query(item.seasons): - try: - season_poster, season_background, _, _ = self.library.find_item_assets(season, item_asset_directory=item_dir, folder_name=name) - except Failed: - season_poster = None - season_background = None - tmdb_poster = tmdb_seasons[season.seasonNumber].poster_url if season.seasonNumber in tmdb_seasons else None - if self.library.mass_poster_update: - self.library.poster_update(season, season_poster, tmdb=tmdb_poster, title=season.title if season else None) - if self.library.mass_background_update: - self.library.background_update(season, season_background, title=season.title if season else None) - - tmdb_episodes = {} - if season.seasonNumber in tmdb_seasons: - for episode in tmdb_seasons[season.seasonNumber].episodes: - episode._partial = False - try: - tmdb_episodes[episode.episode_number] = episode - except NotFound: - logger.error(f"TMDb Error: An Episode of Season {season.seasonNumber} was Not Found") - - for episode in self.library.query(season.episodes): + if self.library.mass_poster_update["seasons"] or self.library.mass_background_update["seasons"]: try: - episode_poster, episode_background, _, _ = self.library.find_item_assets(episode, item_asset_directory=item_dir, folder_name=name) + season_poster, season_background, _, _ = self.library.find_item_assets(season, item_asset_directory=item_dir, folder_name=name) except Failed: - episode_poster = None - episode_background = None - tmdb_poster = tmdb_episodes[episode.episodeNumber].still_url if episode.episodeNumber in tmdb_episodes else None + season_poster = None + season_background = None + tmdb_poster = tmdb_seasons[season.seasonNumber].poster_url if season.seasonNumber in tmdb_seasons else None if self.library.mass_poster_update: - self.library.poster_update(episode, episode_poster, tmdb=tmdb_poster, title=episode.title if episode else None) + self.library.poster_update(season, season_poster, tmdb=tmdb_poster, title=season.title if season else None) if self.library.mass_background_update: - self.library.background_update(episode, episode_background, title=episode.title if episode else None) + self.library.background_update(season, season_background, title=season.title if season else None) + + if self.library.mass_poster_update["episodes"] or self.library.mass_background_update["episodes"]: + tmdb_episodes = {} + if season.seasonNumber in tmdb_seasons: + for episode in tmdb_seasons[season.seasonNumber].episodes: + episode._partial = False + try: + tmdb_episodes[episode.episode_number] = episode + except NotFound: + logger.error(f"TMDb Error: An Episode of Season {season.seasonNumber} was Not Found") + + for episode in self.library.query(season.episodes): + try: + episode_poster, episode_background, _, _ = self.library.find_item_assets(episode, item_asset_directory=item_dir, folder_name=name) + except Failed: + episode_poster = None + episode_background = None + tmdb_poster = tmdb_episodes[episode.episodeNumber].still_url if episode.episodeNumber in tmdb_episodes else None + if self.library.mass_poster_update: + self.library.poster_update(episode, episode_poster, tmdb=tmdb_poster, title=episode.title if episode else None) + if self.library.mass_background_update: + self.library.background_update(episode, episode_background, title=episode.title if episode else None) episode_ops = [ self.library.mass_episode_audience_rating_update, self.library.mass_episode_critic_rating_update, diff --git a/modules/plex.py b/modules/plex.py index 078ba7f3..5af6161f 100644 --- a/modules/plex.py +++ b/modules/plex.py @@ -1176,7 +1176,7 @@ class Plex(Library): def image_update(self, item, image, tmdb=None, title=None, poster=True): text = f"{f'{title} ' if title else ''}{'Poster' if poster else 'Background'}" - attr = self.mass_poster_update if poster else self.mass_background_update + attr = self.mass_poster_update["source"] if poster else self.mass_background_update["source"] if attr == "lock": self.query(item.lockPoster if poster else item.lockArt) logger.info(f"{text} | Locked")