From bf100636d1f070b941b11ffd7b3e7226160db8af Mon Sep 17 00:00:00 2001 From: meisnate12 Date: Sun, 30 Jan 2022 02:48:56 -0500 Subject: [PATCH] add more dynamic list changes --- modules/builder.py | 18 +++++++-------- modules/meta.py | 57 +++++++++++++++++++++++++--------------------- modules/tmdb.py | 3 +++ modules/util.py | 25 ++++++++++++-------- 4 files changed, 59 insertions(+), 44 deletions(-) diff --git a/modules/builder.py b/modules/builder.py index 75d4d153..5c90a7d8 100644 --- a/modules/builder.py +++ b/modules/builder.py @@ -841,7 +841,7 @@ class CollectionBuilder: for anidb_id in self.config.AniDB.validate_anidb_ids(method_data, self.language): self.builders.append((method_name, anidb_id)) elif method_name == "anidb_tag": - for dict_data, dict_methods in util.parse(self.Type, method_name, method_data, datatype="dictlist"): + for dict_data, dict_methods in util.parse(self.Type, method_name, method_data, datatype="listdict"): new_dictionary = {} if "tag" not in dict_methods: raise Failed(f"{self.Type} Error: anidb_tag tag attribute is required") @@ -864,7 +864,7 @@ class CollectionBuilder: elif self.current_time.month in [6, 7, 8]: current_season = "summer" else: current_season = "fall" default_year = self.current_year + 1 if self.current_time.month == 12 else self.current_year - for dict_data, dict_methods in util.parse(self.Type, method_name, method_data, datatype="dictlist"): + for dict_data, dict_methods in util.parse(self.Type, method_name, method_data, datatype="listdict"): new_dictionary = {} for search_method, search_data in dict_data.items(): search_attr, modifier = os.path.splitext(str(search_method).lower()) @@ -909,7 +909,7 @@ class CollectionBuilder: for flixpatrol_list in flixpatrol_lists: self.builders.append(("flixpatrol_url", flixpatrol_list)) elif method_name in flixpatrol.builders: - for dict_data, dict_methods in util.parse(self.Type, method_name, method_data, datatype="dictlist"): + for dict_data, dict_methods in util.parse(self.Type, method_name, method_data, datatype="listdict"): if method_name == "flixpatrol_demographics": data = { "generation": util.parse(self.Type, "generation", dict_data, methods=dict_methods, parent=method_name, options=flixpatrol.generations), @@ -979,7 +979,7 @@ class CollectionBuilder: elif method_name in ["mal_all", "mal_airing", "mal_upcoming", "mal_tv", "mal_ova", "mal_movie", "mal_special", "mal_popular", "mal_favorite", "mal_suggested"]: self.builders.append((method_name, util.parse(self.Type, method_name, method_data, datatype="int", default=10, maximum=100 if method_name == "mal_suggested" else 500))) elif method_name in ["mal_season", "mal_userlist"]: - for dict_data, dict_methods in util.parse(self.Type, method_name, method_data, datatype="dictlist"): + for dict_data, dict_methods in util.parse(self.Type, method_name, method_data, datatype="listdict"): if method_name == "mal_season": if self.current_time.month in [1, 2, 3]: default_season = "winter" elif self.current_time.month in [4, 5, 6]: default_season = "spring" @@ -1003,7 +1003,7 @@ class CollectionBuilder: final_data = [] for data in util.get_list(method_data): final_data.append(data if isinstance(data, dict) else {id_name: data, "limit": 0}) - for dict_data, dict_methods in util.parse(self.Type, method_name, method_data, datatype="dictlist"): + for dict_data, dict_methods in util.parse(self.Type, method_name, method_data, datatype="listdict"): self.builders.append((method_name, { id_name: util.parse(self.Type, id_name, dict_data, datatype="int", methods=dict_methods, parent=method_name, maximum=999999), "limit": util.parse(self.Type, "limit", dict_data, datatype="int", methods=dict_methods, default=0, parent=method_name) @@ -1013,7 +1013,7 @@ class CollectionBuilder: if method_name in ["plex_all", "plex_pilots"]: self.builders.append((method_name, self.collection_level)) elif method_name in ["plex_search", "plex_collectionless"]: - for dict_data, dict_methods in util.parse(self.Type, method_name, method_data, datatype="dictlist"): + for dict_data, dict_methods in util.parse(self.Type, method_name, method_data, datatype="listdict"): new_dictionary = {} if method_name == "plex_search": type_override = f"{self.collection_level}s" if self.collection_level in plex.collection_level_options else None @@ -1038,7 +1038,7 @@ class CollectionBuilder: self.builders.append((method_name, mdb_dict)) def _tautulli(self, method_name, method_data): - for dict_data, dict_methods in util.parse(self.Type, method_name, method_data, datatype="dictlist"): + for dict_data, dict_methods in util.parse(self.Type, method_name, method_data, datatype="listdict"): self.builders.append((method_name, { "list_type": "popular" if method_name == "tautulli_popular" else "watched", "list_days": util.parse(self.Type, "list_days", dict_data, datatype="int", methods=dict_methods, default=30, parent=method_name), @@ -1049,7 +1049,7 @@ class CollectionBuilder: def _tmdb(self, method_name, method_data): if method_name == "tmdb_discover": - for dict_data, dict_methods in util.parse(self.Type, method_name, method_data, datatype="dictlist"): + for dict_data, dict_methods in util.parse(self.Type, method_name, method_data, datatype="listdict"): new_dictionary = {"limit": util.parse(self.Type, "limit", dict_data, datatype="int", methods=dict_methods, default=100, parent=method_name)} for discover_method, discover_data in dict_data.items(): discover_attr, modifier = os.path.splitext(str(discover_method).lower()) @@ -1168,7 +1168,7 @@ class CollectionBuilder: self.builders.append((method_name[:-8] if method_name.endswith("_details") else method_name, value)) def _filters(self, method_name, method_data): - for dict_data, dict_methods in util.parse(self.Type, method_name, method_data, datatype="dictlist"): + for dict_data, dict_methods in util.parse(self.Type, method_name, method_data, datatype="listdict"): validate = True if "validate" in dict_data: if dict_data["validate"] is None: diff --git a/modules/meta.py b/modules/meta.py index 7836c56b..1a123201 100644 --- a/modules/meta.py +++ b/modules/meta.py @@ -10,7 +10,7 @@ logger = logging.getLogger("Plex Meta Manager") github_base = "https://raw.githubusercontent.com/meisnate12/Plex-Meta-Manager-Configs/master/" all_auto = ["genre"] -ms_auto = ["trakt_user_lists", "trakt_people_list"] +ms_auto = ["tmdb_popular_people", "trakt_user_lists", "trakt_people_list"] auto = { "Movie": ["tmdb_collection", "country"] + all_auto + ms_auto, "Show": ["network"] + all_auto + ms_auto, @@ -255,6 +255,9 @@ class MetadataFile(DataFile): else: auto_type = dynamic[methods["type"]].lower() exclude = util.parse("Config", "exclude", dynamic, parent=map_name, methods=methods, datatype="list") if "exclude" in methods else [] + add_ons = util.parse("Config", "add_ons", dynamic, parent=map_name, methods=methods, datatype="dictlist") if "add_ons" in methods else {} + for k, v in add_ons.items(): + exclude.extend(v) default_title_format = "<>" if auto_type in ["genre", "mood", "style", "country", "network"]: auto_list = {i.title: i.title for i in library.get_tags(auto_type) if i.title not in exclude} @@ -275,25 +278,19 @@ class MetadataFile(DataFile): auto_list[tmdb_item.collection.id] = tmdb_item.collection.name util.print_end() default_template = {"tmdb_collection_details": "<<tmdb_collection>>"} + elif auto_type == "trakt_user_lists": + auto_list = [] + for option in util.parse("Config", "data", dynamic, parent=map_name, methods=methods, datatype="list"): + auto_list.extend(self.config.Trakt.get_user_lists(option)) + default_template = {"trakt_list_details": "<<trakt_user_lists>>"} else: - if "data" not in methods: - raise Failed(f"Config Error: {map_name} data attribute not found") - elif not dynamic[methods["data"]]: - raise Failed(f"Config Error: {map_name} data attribute is blank") - else: - options = dynamic[methods["data"]] - if not isinstance(options, list): - options = [options] - if auto_type == "trakt_people_list": + default_template = {"tmdb_person": "<<trakt_people_list>>", "plex_search": {"all": {"actor": "tmdb"}}} + if auto_type == "tmdb_popular_people": + auto_list = self.config.TMDb.get_popular_people(util.parse("Config", "data", dynamic, parent=map_name, methods=methods, datatype="int", minimum=1)) + elif auto_type == "trakt_people_list": auto_list = [] - for option in options: + for option in util.parse("Config", "data", dynamic, parent=map_name, methods=methods, datatype="list"): auto_list.extend(self.config.Trakt.get_people(option)) - default_template = {"tmdb_person": "<<trakt_people_list>>", "plex_search": {"all": {"actor": "tmdb"}}} - elif auto_type == "trakt_user_lists": - auto_list = [] - for option in options: - auto_list.extend(self.config.Trakt.get_user_lists(option)) - default_template = {"trakt_list_details": "<<trakt_user_lists>>"} else: raise Failed(f"Config Error: {map_name} type attribute {dynamic[methods['type']]} invalid") title_format = default_title_format @@ -302,6 +299,8 @@ class MetadataFile(DataFile): if "<<title>>" not in title_format: logger.error(f"Config Error: <<title>> not in title_format: {title_format} using default: {default_title_format}") title_format = default_title_format + titles = util.parse("Config", "titles", dynamic, parent=map_name, methods=methods, datatype="dict") if "titles" in methods else {} + test = util.parse("Config", "test", dynamic, parent=map_name, methods=methods, default=False, datatype="bool") if "test" in methods else False if "<<library_type>>" in title_format: title_format = title_format.replace("<<library_type>>", library.type) dictionary_variables = util.parse("Config", "dictionary_variables", dynamic, parent=map_name, methods=methods, datatype="dictdict") if "dictionary_variables" in methods else {} @@ -317,21 +316,27 @@ class MetadataFile(DataFile): remove_prefix = util.parse("Config", "remove_prefix", dynamic, parent=map_name, methods=methods, datatype="commalist") if "remove_prefix" in methods else [] remove_suffix = util.parse("Config", "remove_suffix", dynamic, parent=map_name, methods=methods, datatype="commalist") if "remove_suffix" in methods else [] for key, value in auto_list.items(): - template_call = {"name": template_name, auto_type: key} + template_call = {"name": template_name, auto_type: [key].extend(add_ons[key]) if key in add_ons else key} for k, v in dictionary_variables.items(): if key in v: template_call[k] = v[key] - for prefix in remove_prefix: - if value.startswith(prefix): - value = value[len(prefix):].strip() - for suffix in remove_suffix: - if value.endswith(suffix): - value = value[:-len(suffix)].strip() - collection_title = title_format.replace("<<title>>", value) + if key in titles: + collection_title = titles[key] + else: + for prefix in remove_prefix: + if value.startswith(prefix): + value = value[len(prefix):].strip() + for suffix in remove_suffix: + if value.endswith(suffix): + value = value[:-len(suffix)].strip() + collection_title = title_format.replace("<<title>>", value) if collection_title in col_names: logger.warning(f"Config Warning: Skipping duplicate collection: {collection_title}") else: - self.collections[collection_title] = {"template": template_call} + col = {"template": template_call} + if test: + col["test"] = True + self.collections[collection_title] = col except Failed as e: logger.error(e) logger.error(f"{map_name} Dynamic Collection Failed") diff --git a/modules/tmdb.py b/modules/tmdb.py index ff5e346c..ff60da7d 100644 --- a/modules/tmdb.py +++ b/modules/tmdb.py @@ -138,6 +138,9 @@ class TMDb: try: return self.TMDb.list(tmdb_id) except TMDbException as e: raise Failed(f"TMDb Error: No List found for TMDb ID {tmdb_id}: {e}") + def get_popular_people(self, limit): + return {p.id: p.name for p in self.TMDb.popular_people().get_results(limit)} + def validate_tmdb_ids(self, tmdb_ids, tmdb_method): tmdb_list = util.get_int_list(tmdb_ids, f"TMDb {type_map[tmdb_method]} ID") tmdb_values = [] diff --git a/modules/util.py b/modules/util.py index 2c81caf2..1e2be6cb 100644 --- a/modules/util.py +++ b/modules/util.py @@ -502,7 +502,7 @@ def parse(error, attribute, data, datatype=None, methods=None, parent=None, defa except ValueError: pass return [] - elif datatype == "dictlist": + elif datatype == "listdict": final_list = [] for dict_data in get_list(value): if isinstance(dict_data, dict): @@ -510,15 +510,22 @@ def parse(error, attribute, data, datatype=None, methods=None, parent=None, defa else: raise Failed(f"{error} Error: {display} {dict_data} is not a dictionary") return final_list - elif datatype == "dictdict": - final_dict = {} + elif datatype in ["dict", "dictlist", "dictdict"]: if isinstance(value, dict): - for dict_key, dict_data in value.items(): - if isinstance(dict_data, dict) and dict_data: - final_dict[dict_key] = dict_data - else: - raise Failed(f"{error} Warning: {display} {dict_key} is not a dictionary") - return final_dict + if datatype == "dict": + return value + elif datatype == "dictlist": + return {k: v if isinstance(v, list) else [v] for k, v in value.items()} + else: + final_dict = {} + for dict_key, dict_data in value.items(): + if isinstance(dict_data, dict) and dict_data: + final_dict[dict_key] = dict_data + else: + raise Failed(f"{error} Warning: {display} {dict_key} is not a dictionary") + return final_dict + else: + raise Failed(f"{error} Error: {display} {value} is not a dictionary") elif methods and attribute not in methods: message = f"{display} not found" elif value is None: