diff --git a/VERSION b/VERSION index c27f700e..8be94918 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -1.16.3-develop11 +1.16.3-develop12 diff --git a/docs/config/libraries.md b/docs/config/libraries.md index fd768509..cbc1cee5 100644 --- a/docs/config/libraries.md +++ b/docs/config/libraries.md @@ -141,7 +141,8 @@ The four path types are outlined as follows: * `- file:` refers to a metadata file which is located within the system that PMM is being run from. * `- folder:` refers to a directory containing metadata files which is located within the system that PMM is being run from. -* `- git:` refers to a metadata file which is hosted on GitHub. This file is assumed to be in the [Configs Repo](https://github.com/meisnate12/Plex-Meta-Manager-Configs) unless the user has specified a custom repository with the [`custom-repo` Setting Attribute](settings.md#custom-repo). +* `- git:` refers to a metadata file which is hosted on the [Configs Repo](https://github.com/meisnate12/Plex-Meta-Manager-Configs). +* `- repo:` refers to a metadata file which is hosted on a custom repository specified aby the user with the [`custom-repo` Setting Attribute](settings.md#custom-repo). * `- url:` refers to a metadata file which is hosted publicly on the internet. Within the above example, PMM will: diff --git a/docs/config/operations.md b/docs/config/operations.md index 8fed22ec..04317d61 100644 --- a/docs/config/operations.md +++ b/docs/config/operations.md @@ -29,7 +29,7 @@ The available attributes for the operations attribute are as follows | `mass_trakt_rating_update` | Updates every movie/show's user rating in the library to match your custom rating on Trakt if there is one
**Values:** `true` or `false` | | `mass_collection_mode` | Updates every Collection in your library to the specified Collection Mode
**Values:** `default`: Library default
`hide`: Hide Collection
`hide_items`: Hide Items in this Collection
`show_items`: Show this Collection and its Items
`default`Library default
`hide`Hide Collection
`hide_items`Hide Items in this Collection
`show_items`Show this Collection and its Items
| | `update_blank_track_titles` | Search though every track in a music library and replace any blank track titles with the tracks sort title
**Values:** `true` or `false` | -| `remove_title_parentheses` | Search through every title and remove all ending parentheses in an items title if the title isn not locked. | +| `remove_title_parentheses` | Search through every title and remove all ending parentheses in an items title if the title isn not locked.
**Values:** `true` or `false` | | `split_duplicates` | Splits all duplicate movies/shows found in this library
**Values:** `true` or `false` | | `radarr_add_all` | Adds every item in the library to Radarr. The existing paths in plex will be used as the root folder of each item, if the paths in Plex are not the same as your Radarr paths you can use the `plex_path` and `radarr_path` [Radarr](radarr) details to convert the paths.
**Values:** `true` or `false` | | `radarr_remove_by_tag` | Removes every item from Radarr with the Tags given
**Values:** List or comma separated string of tags | diff --git a/modules/builder.py b/modules/builder.py index a7774ef7..99fe215e 100644 --- a/modules/builder.py +++ b/modules/builder.py @@ -102,7 +102,7 @@ ignored_details = [ "validate_builders", "libraries", "sync_to_users", "collection_name", "playlist_name", "name", "blank_collection" ] details = [ - "ignore_ids", "ignore_imdb_ids", "server_preroll", "changes_webhooks", "collection_mode", "limit", "url_theme", + "ignore_ids", "ignore_imdb_ids", "server_preroll", "changes_webhooks", "collection_filtering", "collection_mode", "limit", "url_theme", "file_theme", "minimum_items", "label", "album_sorting", "cache_builders", "tmdb_region" ] + boolean_details + scheduled_boolean + string_details collectionless_details = ["collection_order", "plex_collectionless", "label", "label_sync_mode", "test"] + \ @@ -173,6 +173,7 @@ all_filters = boolean_filters + special_filters + \ [f"{f}{m}" for f in date_filters for m in date_modifiers] + \ [f"{f}{m}" for f in number_filters for m in number_modifiers] smart_invalid = ["collection_order", "collection_level"] +smart_only = ["collection_filtering"] smart_url_invalid = ["filters", "run_again", "sync_mode", "show_filtered", "show_missing", "save_missing", "smart_label"] + radarr_details + sonarr_details custom_sort_builders = [ "plex_search", "plex_pilots", "tmdb_list", "tmdb_popular", "tmdb_now_playing", "tmdb_top_rated", @@ -190,7 +191,7 @@ custom_sort_builders = [ ] episode_parts_only = ["plex_pilots"] parts_collection_valid = [ - "filters", "plex_all", "plex_search", "trakt_list", "trakt_list_details", "collection_mode", "label", "visible_library", "limit", + "filters", "plex_all", "plex_search", "trakt_list", "trakt_list_details", "collection_filtering", "collection_mode", "label", "visible_library", "limit", "visible_home", "visible_shared", "show_missing", "save_missing", "missing_only_released", "server_preroll", "changes_webhooks", "item_lock_background", "item_lock_poster", "item_lock_title", "item_refresh", "item_refresh_delay", "imdb_list", "cache_builders", "url_theme", "file_theme" @@ -201,7 +202,7 @@ playlist_attributes = [ "server_preroll", "changes_webhooks", "minimum_items", "cache_builders" ] + custom_sort_builders + summary_details + poster_details + radarr_details + sonarr_details music_attributes = [ - "non_item_remove_label", "item_label", "item_assets", "item_lock_background", "item_lock_poster", "item_lock_title", + "non_item_remove_label", "item_label", "item_assets", "collection_filtering", "item_lock_background", "item_lock_poster", "item_lock_title", "item_refresh", "item_refresh_delay", "plex_search", "plex_all", "filters" ] + details + summary_details + poster_details + background_details @@ -628,6 +629,8 @@ class CollectionBuilder: raise Failed(f"{self.Type} Error: {method_final} attribute not allowed with Collection Level: {self.collection_level.capitalize()}") elif self.smart and method_name in smart_invalid: raise Failed(f"{self.Type} Error: {method_final} attribute only allowed with normal collections") + elif not self.smart and method_name in smart_only: + raise Failed(f"{self.Type} Error: {method_final} attribute only allowed with smart collections") elif self.collectionless and method_name not in collectionless_details: raise Failed(f"{self.Type} Error: {method_final} attribute not allowed for Collectionless collection") elif self.smart_url and method_name in all_builders + smart_url_invalid: @@ -806,7 +809,15 @@ class CollectionBuilder: elif method_name == "tmdb_region": self.tmdb_region = util.parse(self.Type, method_name, method_data, options=self.config.TMDb.iso_3166_1) elif method_name == "collection_mode": - self.details[method_name] = util.check_collection_mode(method_data) + if method_data and str(method_data).lower() in plex.collection_mode_options: + self.details[method_name] = plex.collection_mode_options[str(method_data).lower()] + else: + logger.error(f"Config Error: {method_data} collection_mode invalid\n\tdefault (Library default)\n\thide (Hide Collection)\n\thide_items (Hide Items in this Collection)\n\tshow_items (Show this Collection and its Items)") + elif method_name == "collection_filtering": + if method_data and str(method_data).lower() in plex.collection_filtering_options: + self.details[method_name] = str(method_data).lower() + else: + logger.error(f"Config Error: {method_data} collection_filtering invalid\n\tadmin (Always the server admin user)\n\tuser (User currently viewing the content)") elif method_name == "minimum_items": self.minimum = util.parse(self.Type, method_name, method_data, datatype="int", minimum=1) elif method_name == "limit": @@ -2459,6 +2470,9 @@ class CollectionBuilder: if "collection_mode" in self.details: self.library.collection_mode_query(self.obj, self.details["collection_mode"]) + if "collection_filtering" in self.details: + self.library.edit_query(self.obj, {"collectionFilterBasedOnUser": 0 if self.details["collection_filtering"] == "admin" else 1}, advanced=True) + if "collection_order" in self.details: if int(self.obj.collectionSort) not in plex.collection_order_keys\ or plex.collection_order_keys[int(self.obj.collectionSort)] != self.details["collection_order"]: diff --git a/modules/plex.py b/modules/plex.py index a8560127..8c30068f 100644 --- a/modules/plex.py +++ b/modules/plex.py @@ -130,6 +130,12 @@ 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} collection_order_options = ["release", "alpha", "custom"] +collection_filtering_options = ["user", "admin"] +collection_mode_options = { + "default": "default", "hide": "hide", + "hide_items": "hideItems", "hideitems": "hideItems", + "show_items": "showItems", "showitems": "showItems" +} collection_level_show_options = ["episode", "season"] collection_level_music_options = ["album", "track"] collection_level_options = collection_level_show_options + collection_level_music_options @@ -522,7 +528,7 @@ class Plex(Library): def collection_mode_query(self, collection, data): if int(collection.collectionMode) not in collection_mode_keys or collection_mode_keys[int(collection.collectionMode)] != data: collection.modeUpdate(mode=data) - logger.info(f"Collection Mode | data") + logger.info(f"Collection Mode | {data}") @retry(stop_max_attempt_number=6, wait_fixed=10000, retry_on_exception=util.retry_if_not_plex) def collection_order_query(self, collection, data): @@ -546,7 +552,6 @@ class Plex(Library): item.editAdvanced(**edits) else: item.edit(**edits) - self.reload(item) @retry(stop_max_attempt_number=6, wait_fixed=10000, retry_on_exception=util.retry_if_not_plex) def _upload_image(self, item, image): diff --git a/modules/util.py b/modules/util.py index fecea18c..de5dd64c 100644 --- a/modules/util.py +++ b/modules/util.py @@ -65,11 +65,6 @@ pretty_months = { } seasons = ["current", "winter", "spring", "summer", "fall"] pretty_ids = {"anidbid": "AniDB", "imdbid": "IMDb", "mal_id": "MyAnimeList", "themoviedb_id": "TMDb", "thetvdb_id": "TVDb", "tvdbid": "TVDb"} -collection_mode_options = { - "default": "default", "hide": "hide", - "hide_items": "hideItems", "hideitems": "hideItems", - "show_items": "showItems", "showitems": "showItems" -} advance_tags_to_edit = { "Movie": ["metadata_language", "use_original_title"], "Show": ["episode_sorting", "keep_episodes", "delete_episodes", "season_display", "episode_ordering", @@ -317,12 +312,6 @@ def is_string_filter(values, modifier, data): if jailbreak: break return (jailbreak and modifier in [".not", ".isnot"]) or (not jailbreak and modifier in ["", ".is", ".begins", ".ends", ".regex"]) -def check_collection_mode(collection_mode): - if collection_mode and str(collection_mode).lower() in collection_mode_options: - return collection_mode_options[str(collection_mode).lower()] - else: - raise Failed(f"Config Error: {collection_mode} collection_mode invalid\n\tdefault (Library default)\n\thide (Hide Collection)\n\thide_items (Hide Items in this Collection)\n\tshow_items (Show this Collection and its Items)") - def check_day(_m, _d): if _m in [1, 3, 5, 7, 8, 10, 12] and _d > 31: return _m, 31 diff --git a/plex_meta_manager.py b/plex_meta_manager.py index 0aec3422..7e58c61a 100644 --- a/plex_meta_manager.py +++ b/plex_meta_manager.py @@ -622,8 +622,6 @@ def library_operations(config, library): new_genres = tvdb_item.genres elif anidb_item and library.mass_genre_update == "anidb": new_genres = anidb_item.tags - else: - raise Failed if not new_genres: logger.info(f"{item.title[:25]:<25} | No Genres Found") if library.genre_mapper: