diff --git a/modules/builder.py b/modules/builder.py index a9083a14..ef0d1b9c 100644 --- a/modules/builder.py +++ b/modules/builder.py @@ -8,6 +8,8 @@ from plexapi.exceptions import BadRequest, NotFound logger = logging.getLogger("Plex Meta Manager") image_file_details = ["file_poster", "file_background", "asset_directory"] +advance_new_agent = ["item_metadata_language", "item_use_original_title"] +advance_show = ["item_episode_sorting", "item_keep_episodes", "item_delete_episodes", "item_season_display", "item_episode_sorting"] method_alias = { "actors": "actor", "role": "actor", "roles": "actor", "content_ratings": "content_rating", "contentRating": "content_rating", "contentRatings": "content_rating", @@ -155,6 +157,7 @@ class CollectionBuilder: "show_missing": library.show_missing, "save_missing": library.save_missing } + self.item_details = {} self.radarr_options = {} self.sonarr_options = {} self.missing_movies = [] @@ -454,6 +457,20 @@ class CollectionBuilder: self.details["label.sync"] = util.get_list(method_data) else: self.details[method_name] = util.get_list(method_data) + elif method_name in ["item_label", "item_label.sync"]: + if "item_label" in self.data and "item_label.sync" in self.data: + raise Failed(f"Collection Error: Cannot use item_label and item_label.sync together") + self.item_details[method_name] = util.get_list(method_data) + elif method_name in plex.item_advance_keys: + key, options = plex.item_advance_keys[method_name] + if method_name in advance_new_agent and self.library.agent not in plex.new_plex_agents: + logger.error(f"Metadata Error: {method_name} attribute only works for with the New Plex Movie Agent and New Plex TV Agent") + elif method_name in advance_show and not self.library.is_show: + logger.error(f"Metadata Error: {method_name} attribute only works for show libraries") + elif str(method_data).lower() not in options: + logger.error(f"Metadata Error: {method_data} {method_name} attribute invalid") + else: + self.item_details[method_name] = str(method_data).lower() elif method_name in boolean_details: self.details[method_name] = util.get_bool(method_name, method_data) elif method_name in all_details: @@ -1162,6 +1179,36 @@ class CollectionBuilder: collection.addLabel(label) logger.info(f"Detail: Label {label} added") + if len(self.item_details) > 0: + labels = None + if "item_label" in self.item_details or "item_label.sync" in self.item_details: + labels = util.get_list(self.item_details["item_label" if "item_label" in self.item_details else "item_label.sync"]) + for item in collection.items(): + if labels is not None: + item_labels = [label.tag for label in item.labels] + if "item_label.sync" in self.item_details: + for label in (la for la in item_labels if la not in labels): + item.removeLabel(label) + logger.info(f"Detail: Label {label} removed from {item.title}") + for label in (la for la in labels if la not in item_labels): + item.addLabel(label) + logger.info(f"Detail: Label {label} added to {item.title}") + advance_edits = {} + for method_name, method_data in self.item_details.items(): + if method_name in plex.item_advance_keys: + key, options = plex.item_advance_keys[method_name] + if getattr(item, key) != options[method_data]: + advance_edits[key] = options[method_data] + if len(advance_edits) > 0: + logger.debug(f"Details Update: {advance_edits}") + try: + item.editAdvanced(**advance_edits) + item.reload() + logger.info(f"{'Movie' if self.library.is_movie else 'Show'}: {item.title} Advanced Details Update Successful") + except BadRequest: + util.print_stacktrace() + logger.error(f"{'Movie' if self.library.is_movie else 'Show'}: {item.title} Advanced Details Update Failed") + if len(edits) > 0: logger.debug(edits) collection.edit(**edits) diff --git a/modules/plex.py b/modules/plex.py index ab09609f..82ccfa24 100644 --- a/modules/plex.py +++ b/modules/plex.py @@ -35,6 +35,25 @@ plex_languages = ["default", "ar-SA", "ca-ES", "cs-CZ", "da-DK", "de-DE", "el-GR metadata_language_options = {lang.lower(): lang for lang in plex_languages} metadata_language_options["default"] = None use_original_title_options = {"default": -1, "no": 0, "yes": 1} +advance_keys = { + "episode_sorting": ("episodeSort", episode_sorting_options), + "keep_episodes": ("autoDeletionItemPolicyUnwatchedLibrary", keep_episodes_options), + "delete_episodes": ("autoDeletionItemPolicyWatchedLibrary", delete_episodes_options), + "season_display": ("flattenSeasons", season_display_options), + "episode_ordering": ("showOrdering", episode_ordering_options), + "metadata_language": ("languageOverride", metadata_language_options), + "use_original_title": ("useOriginalTitle", use_original_title_options) +} +item_advance_keys = { + "item_episode_sorting": ("episodeSort", episode_sorting_options), + "item_keep_episodes": ("autoDeletionItemPolicyUnwatchedLibrary", keep_episodes_options), + "item_delete_episodes": ("autoDeletionItemPolicyWatchedLibrary", delete_episodes_options), + "item_season_display": ("flattenSeasons", season_display_options), + "item_episode_ordering": ("showOrdering", episode_ordering_options), + "item_metadata_language": ("languageOverride", metadata_language_options), + "item_use_original_title": ("useOriginalTitle", use_original_title_options) +} +new_plex_agents = ["tv.plex.agents.movie", "tv.plex.agents.series"] filter_alias = { "actor": "actors", "audience_rating": "audienceRating", @@ -125,6 +144,7 @@ class PlexAPI: if not self.Plex: raise Failed(f"Plex Error: Plex Library {params['name']} not found") + self.agent = self.Plex.agent self.is_movie = self.Plex.type == "movie" self.is_show = self.Plex.type == "show" @@ -504,17 +524,18 @@ class PlexAPI: else: logger.error(f"Metadata Error: {name} attribute is blank") - def add_advanced_edit(attr, options, key=None, show_library=False): - if key is None: - key = attr - if attr in methods: - if show_library and not self.is_show: + def add_advanced_edit(attr, obj, group, alias, show_library=False, new_agent=False): + key, options = advance_keys[attr] + if attr in alias: + if new_agent and self.agent not in new_plex_agents: + logger.error(f"Metadata Error: {attr} attribute only works for with the New Plex Movie Agent and New Plex TV Agent") + elif show_library and not self.is_show: logger.error(f"Metadata Error: {attr} attribute only works for show libraries") - elif meta[methods[attr]]: - method_data = str(meta[methods[attr]]).lower() + elif group[alias[attr]]: + method_data = str(group[alias[attr]]).lower() if method_data not in options: - logger.error(f"Metadata Error: {meta[methods[attr]]} {attr} attribute invalid") - elif getattr(item, key) != options[method_data]: + logger.error(f"Metadata Error: {group[alias[attr]]} {attr} attribute invalid") + elif getattr(obj, key) != options[method_data]: advance_edits[key] = options[method_data] logger.info(f"Detail: {attr} updated to {method_data}") else: @@ -675,19 +696,17 @@ class PlexAPI: logger.error(f"{item_type}: {mapping_name} Details Update Failed") advance_edits = {} - add_advanced_edit("episode_sorting", episode_sorting_options, key="episodeSort", show_library=True) - add_advanced_edit("keep_episodes", keep_episodes_options, key="autoDeletionItemPolicyUnwatchedLibrary", show_library=True) - add_advanced_edit("delete_episodes", delete_episodes_options, key="autoDeletionItemPolicyWatchedLibrary", show_library=True) - add_advanced_edit("season_display", season_display_options, key="flattenSeasons", show_library=True) - add_advanced_edit("episode_ordering", episode_ordering_options, key="showOrdering", show_library=True) - add_advanced_edit("metadata_language", metadata_language_options, key="languageOverride") - add_advanced_edit("use_original_title", use_original_title_options, key="useOriginalTitle") + add_advanced_edit("episode_sorting", item, meta, methods, show_library=True) + add_advanced_edit("keep_episodes", item, meta, methods, show_library=True) + add_advanced_edit("delete_episodes", item, meta, methods, show_library=True) + add_advanced_edit("season_display", item, meta, methods, show_library=True) + add_advanced_edit("episode_ordering", item, meta, methods, show_library=True) + add_advanced_edit("metadata_language", item, meta, methods, new_agent=True) + add_advanced_edit("use_original_title", item, meta, methods, new_agent=True) if len(advance_edits) > 0: logger.debug(f"Details Update: {advance_edits}") updated = True try: - check_dict = {pref.id: list(pref.enumValues.keys()) for pref in item.preferences()} - logger.info(check_dict) item.editAdvanced(**advance_edits) item.reload() logger.info(f"{item_type}: {mapping_name} Advanced Details Update Successful") diff --git a/plex_meta_manager.py b/plex_meta_manager.py index da8be078..bd0b1bd9 100644 --- a/plex_meta_manager.py +++ b/plex_meta_manager.py @@ -89,7 +89,7 @@ util.centered("| |_) | |/ _ \\ \\/ / | |\\/| |/ _ \\ __/ _` | | |\\/| |/ _` | '_ util.centered("| __/| | __/> < | | | | __/ || (_| | | | | | (_| | | | | (_| | (_| | __/ | ") util.centered("|_| |_|\\___/_/\\_\\ |_| |_|\\___|\\__\\__,_| |_| |_|\\__,_|_| |_|\\__,_|\\__, |\\___|_| ") util.centered(" |___/ ") -util.centered(" Version: 1.7.2-Beta3 ") +util.centered(" Version: 1.7.2-Beta4 ") util.separator() if my_tests: