diff --git a/modules/builder.py b/modules/builder.py index 7fff99d0..3362246d 100644 --- a/modules/builder.py +++ b/modules/builder.py @@ -86,9 +86,9 @@ class CollectionBuilder: else: raise Failed("Collection Error: template sub-attribute optional is blank") - for m in template: - if m not in self.data and m not in ["default", "optional"]: - if template[m]: + for method_name, attr_data in template: + if method_name not in self.data and method_name not in ["default", "optional"]: + if attr_data: def replace_txt(txt): txt = str(txt) for option in optional: @@ -108,33 +108,33 @@ class CollectionBuilder: try: return int(txt) except ValueError: return txt try: - if isinstance(template[m], dict): - a = {} - for sm in template[m]: - if isinstance(template[m][sm], list): + if isinstance(attr_data, dict): + discover_name = {} + for sm in attr_data: + if isinstance(attr_data[sm], list): temp_list = [] - for li in template[m][sm]: + for li in attr_data[sm]: temp_list.append(replace_txt(li)) - a[sm] = temp_list + discover_name[sm] = temp_list else: - a[sm] = replace_txt(template[m][sm]) - elif isinstance(template[m], list): - a = [] - for li in template[m]: + discover_name[sm] = replace_txt(attr_data[sm]) + elif isinstance(attr_data, list): + discover_name = [] + for li in attr_data: if isinstance(li, dict): temp_dict = {} for sm in li: temp_dict[sm] = replace_txt(li[sm]) - a.append(temp_dict) + discover_name.append(temp_dict) else: - a.append(replace_txt(li)) + discover_name.append(replace_txt(li)) else: - a = replace_txt(template[m]) + discover_name = replace_txt(attr_data) except Failed: continue - self.data[m] = a + self.data[method_name] = discover_name else: - raise Failed(f"Collection Error: template attribute {m} is blank") + raise Failed(f"Collection Error: template attribute {method_name} is blank") skip_collection = True if "schedule" not in methods: @@ -211,21 +211,21 @@ class CollectionBuilder: else: raise Failed("Collection Error: tmdb_person attribute is blank") - for m in self.data: - if "tmdb" in m.lower() and not config.TMDb: raise Failed(f"Collection Error: {m} requires TMDb to be configured") - elif "trakt" in m.lower() and not config.Trakt: raise Failed(f"Collection Error: {m} requires Trakt todo be configured") - elif "imdb" in m.lower() and not config.IMDb: raise Failed(f"Collection Error: {m} requires TMDb or Trakt to be configured") - elif "tautulli" in m.lower() and not self.library.Tautulli: raise Failed(f"Collection Error: {m} requires Tautulli to be configured") - elif "mal" in m.lower() and not config.MyAnimeList: raise Failed(f"Collection Error: {m} requires MyAnimeList to be configured") - elif self.data[m] is not None: + for method_name, method_data in self.data.items(): + if "tmdb" in method_name.lower() and not config.TMDb: raise Failed(f"Collection Error: {method_name} requires TMDb to be configured") + elif "trakt" in method_name.lower() and not config.Trakt: raise Failed(f"Collection Error: {method_name} requires Trakt todo be configured") + elif "imdb" in method_name.lower() and not config.IMDb: raise Failed(f"Collection Error: {method_name} requires TMDb or Trakt to be configured") + elif "tautulli" in method_name.lower() and not self.library.Tautulli: raise Failed(f"Collection Error: {method_name} requires Tautulli to be configured") + elif "mal" in method_name.lower() and not config.MyAnimeList: raise Failed(f"Collection Error: {method_name} requires MyAnimeList to be configured") + elif method_data is not None: logger.debug("") - logger.debug(f"Method: {m}") - logger.debug(f"Value: {self.data[m]}") - if m.lower() in util.method_alias: - method_name = util.method_alias[m.lower()] - logger.warning(f"Collection Warning: {m} attribute will run as {method_name}") + logger.debug(f"Method: {method_name}") + logger.debug(f"Value: {method_data}") + if method_name.lower() in util.method_alias: + method_name = util.method_alias[method_name.lower()] + logger.warning(f"Collection Warning: {method_name} attribute will run as {method_name}") else: - method_name = m.lower() + method_name = method_name.lower() if method_name in util.show_only_lists and self.library.is_movie: raise Failed(f"Collection Error: {method_name} attribute only works for show libraries") elif method_name in util.movie_only_lists and self.library.is_show: @@ -235,76 +235,76 @@ class CollectionBuilder: elif method_name not in util.collectionless_lists and self.collectionless: raise Failed(f"Collection Error: {method_name} attribute does not work for Collectionless collection") elif method_name == "summary": - self.summaries[method_name] = self.data[m] + self.summaries[method_name] = method_data elif method_name == "tmdb_summary": - self.summaries[method_name] = config.TMDb.get_movie_show_or_collection(util.regex_first_int(self.data[m], "TMDb ID"), self.library.is_movie).overview + self.summaries[method_name] = config.TMDb.get_movie_show_or_collection(util.regex_first_int(method_data, "TMDb ID"), self.library.is_movie).overview elif method_name == "tmdb_description": - self.summaries[method_name] = config.TMDb.get_list(util.regex_first_int(self.data[m], "TMDb List ID")).description + self.summaries[method_name] = config.TMDb.get_list(util.regex_first_int(method_data, "TMDb List ID")).description elif method_name == "tmdb_biography": - self.summaries[method_name] = config.TMDb.get_person(util.regex_first_int(self.data[m], "TMDb Person ID")).biography + self.summaries[method_name] = config.TMDb.get_person(util.regex_first_int(method_data, "TMDb Person ID")).biography elif method_name == "tvdb_summary": - self.summaries[method_name] = config.TVDb.get_movie_or_show(self.data[m], self.library.Plex.language, self.library.is_movie).summary + self.summaries[method_name] = config.TVDb.get_movie_or_show(method_data, self.library.Plex.language, self.library.is_movie).summary elif method_name == "tvdb_description": - self.summaries[method_name] = config.TVDb.get_list_description(self.data[m], self.library.Plex.language) + self.summaries[method_name] = config.TVDb.get_list_description(method_data, self.library.Plex.language) elif method_name == "trakt_description": - self.summaries[method_name] = config.Trakt.standard_list(config.Trakt.validate_trakt_list(util.get_list(self.data[m]))[0]).description + self.summaries[method_name] = config.Trakt.standard_list(config.Trakt.validate_trakt_list(util.get_list(method_data))[0]).description elif method_name == "letterboxd_description": - self.summaries[method_name] = config.Letterboxd.get_list_description(self.data[m], self.library.Plex.language) + self.summaries[method_name] = config.Letterboxd.get_list_description(method_data, self.library.Plex.language) elif method_name == "collection_mode": - if str(self.data[m]).lower() == "default": + if str(method_data).lower() == "default": self.details[method_name] = "default" - elif str(self.data[m]).lower() == "hide": + elif str(method_data).lower() == "hide": self.details[method_name] = "hide" - elif str(self.data[m]).lower() in ["hide_items", "hideitems"]: + elif str(method_data).lower() in ["hide_items", "hideitems"]: self.details[method_name] = "hideItems" - elif str(self.data[m]).lower() in ["show_items", "showitems"]: + elif str(method_data).lower() in ["show_items", "showitems"]: self.details[method_name] = "showItems" else: - raise Failed(f"Collection Error: {self.data[m]} 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)") + raise Failed(f"Collection 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_order": - if str(self.data[m]).lower() == "release": + if str(method_data).lower() == "release": self.details[method_name] = "release" - elif str(self.data[m]).lower() == "alpha": + elif str(method_data).lower() == "alpha": self.details[method_name] = "release" else: - raise Failed(f"Collection Error: {self.data[m]} collection_order invalid\n\trelease (Order Collection by release dates)\n\talpha (Order Collection Alphabetically)") + raise Failed(f"Collection Error: {method_data} collection_order invalid\n\trelease (Order Collection by release dates)\n\talpha (Order Collection Alphabetically)") elif method_name == "url_poster": - self.posters[method_name] = self.data[m] + self.posters[method_name] = method_data elif method_name == "tmdb_poster": - self.posters[method_name] = f"{config.TMDb.image_url}{config.TMDb.get_movie_show_or_collection(util.regex_first_int(self.data[m], 'TMDb ID'), self.library.is_movie).poster_path}" + self.posters[method_name] = f"{config.TMDb.image_url}{config.TMDb.get_movie_show_or_collection(util.regex_first_int(method_data, 'TMDb ID'), self.library.is_movie).poster_path}" elif method_name == "tmdb_profile": - self.posters[method_name] = f"{config.TMDb.image_url}{config.TMDb.get_person(util.regex_first_int(self.data[m], 'TMDb Person ID')).profile_path}" + self.posters[method_name] = f"{config.TMDb.image_url}{config.TMDb.get_person(util.regex_first_int(method_data, 'TMDb Person ID')).profile_path}" elif method_name == "tvdb_poster": - self.posters[method_name] = f"{config.TVDb.get_movie_or_series(self.data[m], self.library.Plex.language, self.library.is_movie).poster_path}" + self.posters[method_name] = f"{config.TVDb.get_movie_or_series(method_data, self.library.Plex.language, self.library.is_movie).poster_path}" elif method_name == "file_poster": - if os.path.exists(self.data[m]): - self.posters[method_name] = os.path.abspath(self.data[m]) + if os.path.exists(method_data): + self.posters[method_name] = os.path.abspath(method_data) else: - raise Failed(f"Collection Error: Poster Path Does Not Exist: {os.path.abspath(self.data[m])}") + raise Failed(f"Collection Error: Poster Path Does Not Exist: {os.path.abspath(method_data)}") elif method_name == "url_background": - self.backgrounds[method_name] = self.data[m] + self.backgrounds[method_name] = method_data elif method_name == "tmdb_background": - self.backgrounds[method_name] = f"{config.TMDb.image_url}{config.TMDb.get_movie_show_or_collection(util.regex_first_int(self.data[m], 'TMDb ID'), self.library.is_movie).poster_path}" + self.backgrounds[method_name] = f"{config.TMDb.image_url}{config.TMDb.get_movie_show_or_collection(util.regex_first_int(method_data, 'TMDb ID'), self.library.is_movie).poster_path}" elif method_name == "tvdb_background": - self.posters[method_name] = f"{config.TVDb.get_movie_or_series(self.data[m], self.library.Plex.language, self.library.is_movie).background_path}" + self.posters[method_name] = f"{config.TVDb.get_movie_or_series(method_data, self.library.Plex.language, self.library.is_movie).background_path}" elif method_name == "file_background": - if os.path.exists(self.data[m]): self.backgrounds[method_name] = os.path.abspath(self.data[m]) - else: raise Failed(f"Collection Error: Background Path Does Not Exist: {os.path.abspath(self.data[m])}") + if os.path.exists(method_data): self.backgrounds[method_name] = os.path.abspath(method_data) + else: raise Failed(f"Collection Error: Background Path Does Not Exist: {os.path.abspath(method_data)}") elif method_name == "label_sync_mode": - if self.data[m].lower() in ["append", "sync"]: self.details[method_name] = self.data[m].lower() + if str(method_data).lower() in ["append", "sync"]: self.details[method_name] = method_data.lower() else: raise Failed("Collection Error: label_sync_mode attribute must be either 'append' or 'sync'") elif method_name == "sync_mode": - if self.data[m].lower() in ["append", "sync"]: self.details[method_name] = self.data[m].lower() + if str(method_data).lower() in ["append", "sync"]: self.details[method_name] = method_data.lower() else: raise Failed("Collection Error: sync_mode attribute must be either 'append' or 'sync'") elif method_name in ["arr_tag", "label"]: - self.details[method_name] = util.get_list(self.data[m]) + self.details[method_name] = util.get_list(method_data) elif method_name in util.boolean_details: - if isinstance(self.data[m], bool): self.details[method_name] = self.data[m] - elif str(self.data[m]).lower() in ["t", "true"]: self.details[method_name] = True - elif str(self.data[m]).lower() in ["f", "false"]: self.details[method_name] = False + if isinstance(method_data, bool): self.details[method_name] = method_data + elif str(method_data).lower() in ["t", "true"]: self.details[method_name] = True + elif str(method_data).lower() in ["f", "false"]: self.details[method_name] = False else: raise Failed(f"Collection Error: {method_name} attribute must be either true or false") elif method_name in util.all_details: - self.details[method_name] = self.data[m] + self.details[method_name] = method_data elif method_name in ["year", "year.not"]: self.methods.append(("plex_search", [[(method_name, util.get_year_list(self.data[m], method_name))]])) elif method_name in ["decade", "decade.not"]: @@ -325,33 +325,33 @@ class CollectionBuilder: elif method_name == "plex_all": self.methods.append((method_name, [""])) elif method_name == "plex_collection": - self.methods.append((method_name, self.library.validate_collections(self.data[m] if isinstance(self.data[m], list) else [self.data[m]]))) + self.methods.append((method_name, self.library.validate_collections(method_data if isinstance(method_data, list) else [method_data]))) elif method_name == "anidb_popular": - list_count = util.regex_first_int(self.data[m], "List Size", default=40) + list_count = util.regex_first_int(method_data, "List Size", default=40) if 1 <= list_count <= 30: self.methods.append((method_name, [list_count])) else: logger.warning("Collection Error: anidb_popular must be an integer between 1 and 30 defaulting to 30") self.methods.append((method_name, [30])) elif method_name == "mal_id": - self.methods.append((method_name, util.get_int_list(self.data[m], "MyAnimeList ID"))) + self.methods.append((method_name, util.get_int_list(method_data, "MyAnimeList ID"))) elif method_name in ["anidb_id", "anidb_relation"]: - self.methods.append((method_name, config.AniDB.validate_anidb_list(util.get_int_list(self.data[m], "AniDB ID"), self.library.Plex.language))) + self.methods.append((method_name, config.AniDB.validate_anidb_list(util.get_int_list(method_data, "AniDB ID"), self.library.Plex.language))) elif method_name in ["anilist_id", "anilist_relations", "anilist_studio"]: - self.methods.append((method_name, config.AniList.validate_anilist_ids(util.get_int_list(self.data[m], "AniList ID"), studio=method_name == "anilist_studio"))) + self.methods.append((method_name, config.AniList.validate_anilist_ids(util.get_int_list(method_data, "AniList ID"), studio=method_name == "anilist_studio"))) elif method_name == "trakt_list": - self.methods.append((method_name, config.Trakt.validate_trakt_list(util.get_list(self.data[m])))) + self.methods.append((method_name, config.Trakt.validate_trakt_list(util.get_list(method_data)))) elif method_name == "trakt_list_details": - valid_list = config.Trakt.validate_trakt_list(util.get_list(self.data[m])) + valid_list = config.Trakt.validate_trakt_list(util.get_list(method_data)) item = config.Trakt.standard_list(valid_list[0]) if hasattr(item, "description") and item.description: self.summaries[method_name] = item.description self.methods.append((method_name[:-8], valid_list)) elif method_name == "trakt_watchlist": - self.methods.append((method_name, config.Trakt.validate_trakt_watchlist(util.get_list(self.data[m]), self.library.is_movie))) + self.methods.append((method_name, config.Trakt.validate_trakt_watchlist(util.get_list(method_data), self.library.is_movie))) elif method_name == "imdb_list": new_list = [] - for imdb_list in util.get_list(self.data[m], split=False): + for imdb_list in util.get_list(method_data, split=False): if isinstance(imdb_list, dict): dict_methods = {dm.lower(): dm for dm in imdb_list} if "url" in dict_methods and imdb_list[dict_methods["url"]]: @@ -365,13 +365,13 @@ class CollectionBuilder: new_list.append({"url": imdb_url, "limit": list_count}) self.methods.append((method_name, new_list)) elif method_name == "letterboxd_list": - self.methods.append((method_name, util.get_list(self.data[m], split=False))) + self.methods.append((method_name, util.get_list(method_data, split=False))) elif method_name == "letterboxd_list_details": - values = util.get_list(self.data[m], split=False) + values = util.get_list(method_data, split=False) self.summaries[method_name] = config.Letterboxd.get_list_description(values[0], self.library.Plex.language) self.methods.append((method_name[:-8], values)) elif method_name in util.dictionary_lists: - if isinstance(self.data[m], dict): + if isinstance(method_data, dict): def get_int(parent, method, data_in, methods_in, default_in, minimum=1, maximum=None): if method not in methods_in: logger.warning(f"Collection Warning: {parent} {methods_in[method]} attribute not found using {default_in} as default") @@ -386,50 +386,50 @@ class CollectionBuilder: logger.warning(f"Collection Warning: {parent} {methods_in[method]} attribute {data_in[methods_in[method]]} invalid must an integer >= {minimum} using {default_in} as default") return default_in if method_name == "filters": - for f in self.data[m]: - if f.lower() in util.method_alias or (f.lower().endswith(".not") and f.lower()[:-4] in util.method_alias): - filter_method = (util.method_alias[f.lower()[:-4]] + f.lower()[-4:]) if f.lower().endswith(".not") else util.method_alias[f.lower()] - logger.warning(f"Collection Warning: {f} filter will run as {filter_method}") + for filter_name, filter_data in method_data.items(): + if filter_name.lower() in util.method_alias or (filter_name.lower().endswith(".not") and filter_name.lower()[:-4] in util.method_alias): + filter_method = (util.method_alias[filter_name.lower()[:-4]] + filter_name.lower()[-4:]) if filter_name.lower().endswith(".not") else util.method_alias[filter_name.lower()] + logger.warning(f"Collection Warning: {filter_name} filter will run as {filter_method}") else: - filter_method = f.lower() + filter_method = filter_name.lower() if filter_method in util.movie_only_filters and self.library.is_show: raise Failed(f"Collection Error: {filter_method} filter only works for movie libraries") - elif self.data[m][f] is None: + elif filter_data is None: raise Failed(f"Collection Error: {filter_method} filter is blank") elif filter_method == "year": - filter_data = util.get_year_list(self.data[m][f], f"{filter_method} filter") + valid_data = util.get_year_list(filter_data, current_year, f"{filter_method} filter") elif filter_method in ["max_age", "duration.gte", "duration.lte", "tmdb_vote_count.gte", "tmdb_vote_count.lte"]: - filter_data = util.check_number(self.data[m][f], f"{filter_method} filter", minimum=1) + valid_data = util.check_number(filter_data, f"{filter_method} filter", minimum=1) elif filter_method in ["year.gte", "year.lte"]: - filter_data = util.check_number(self.data[m][f], f"{filter_method} filter", minimum=1800, maximum=current_year) + valid_data = util.check_year(filter_data, current_year, f"{filter_method} filter") elif filter_method in ["rating.gte", "rating.lte"]: - filter_data = util.check_number(self.data[m][f], f"{filter_method} filter", number_type="float", minimum=0.1, maximum=10) + valid_data = util.check_number(filter_data, f"{filter_method} filter", number_type="float", minimum=0.1, maximum=10) elif filter_method in ["originally_available.gte", "originally_available.lte"]: - filter_data = util.check_date(self.data[m][f], f"{filter_method} filter") + valid_data = util.check_date(filter_data, f"{filter_method} filter") elif filter_method == "original_language": - filter_data = util.get_list(self.data[m][f], lower=True) + valid_data = util.get_list(filter_data, lower=True) elif filter_method == "collection": - filter_data = self.data[m][f] if isinstance(self.data[m][f], list) else [self.data[m][f]] + valid_data = filter_data if isinstance(filter_data, list) else [filter_data] elif filter_method in util.all_filters: - filter_data = util.get_list(self.data[m][f]) + valid_data = util.get_list(filter_data) else: raise Failed(f"Collection Error: {filter_method} filter not supported") - self.filters.append((filter_method, filter_data)) + self.filters.append((filter_method, valid_data)) elif method_name == "plex_collectionless": new_dictionary = {} - dict_methods = {dm.lower(): dm for dm in self.data[m]} + dict_methods = {dm.lower(): dm for dm in method_data} prefix_list = [] - if "exclude_prefix" in dict_methods and self.data[m][dict_methods["exclude_prefix"]]: - if isinstance(self.data[m][dict_methods["exclude_prefix"]], list): - prefix_list.extend(self.data[m][dict_methods["exclude_prefix"]]) + if "exclude_prefix" in dict_methods and method_data[dict_methods["exclude_prefix"]]: + if isinstance(method_data[dict_methods["exclude_prefix"]], list): + prefix_list.extend(method_data[dict_methods["exclude_prefix"]]) else: - prefix_list.append(str(self.data[m][dict_methods["exclude_prefix"]])) + prefix_list.append(str(method_data[dict_methods["exclude_prefix"]])) exact_list = [] - if "exclude" in dict_methods and self.data[m][dict_methods["exclude"]]: - if isinstance(self.data[m][dict_methods["exclude"]], list): - exact_list.extend(self.data[m][dict_methods["exclude"]]) + if "exclude" in dict_methods and method_data[dict_methods["exclude"]]: + if isinstance(method_data[dict_methods["exclude"]], list): + exact_list.extend(method_data[dict_methods["exclude"]]) else: - exact_list.append(str(self.data[m][dict_methods["exclude"]])) + exact_list.append(str(method_data[dict_methods["exclude"]])) if len(prefix_list) == 0 and len(exact_list) == 0: raise Failed("Collection Error: you must have at least one exclusion") new_dictionary["exclude_prefix"] = prefix_list @@ -464,61 +464,61 @@ class CollectionBuilder: self.methods.append((method_name, [searches])) elif method_name == "tmdb_discover": new_dictionary = {"limit": 100} - for a in self.data[m]: - a_name = a.lower() - if self.data[m][a]: - if (self.library.is_movie and a_name in util.discover_movie) or (self.library.is_show and a_name in util.discover_tv): - if a_name == "language": - if re.compile("([a-z]{2})-([A-Z]{2})").match(str(self.data[m][a])): - new_dictionary[a_name] = str(self.data[m][a]) + for discover_name, discover_data in method_data: + discover_final = discover_name.lower() + if discover_data: + if (self.library.is_movie and discover_final in util.discover_movie) or (self.library.is_show and discover_final in util.discover_tv): + if discover_final == "language": + if re.compile("([a-z]{2})-([A-Z]{2})").match(str(discover_data)): + new_dictionary[discover_final] = str(discover_data) else: - raise Failed(f"Collection Error: {m} attribute {a_name}: {self.data[m][a]} must match pattern ([a-z]{{2}})-([A-Z]{{2}}) e.g. en-US") - elif a_name == "region": - if re.compile("^[A-Z]{2}$").match(str(self.data[m][a])): - new_dictionary[a_name] = str(self.data[m][a]) + raise Failed(f"Collection Error: {method_name} attribute {discover_final}: {discover_data} must match pattern ([a-z]{{2}})-([A-Z]{{2}}) e.g. en-US") + elif discover_final == "region": + if re.compile("^[A-Z]{2}$").match(str(discover_data)): + new_dictionary[discover_final] = str(discover_data) else: - raise Failed(f"Collection Error: {m} attribute {a_name}: {self.data[m][a]} must match pattern ^[A-Z]{{2}}$ e.g. US") - elif a_name == "sort_by": - if (self.library.is_movie and self.data[m][a] in util.discover_movie_sort) or (self.library.is_show and self.data[m][a] in util.discover_tv_sort): - new_dictionary[a_name] = self.data[m][a] + raise Failed(f"Collection Error: {method_name} attribute {discover_final}: {discover_data} must match pattern ^[A-Z]{{2}}$ e.g. US") + elif discover_final == "sort_by": + if (self.library.is_movie and discover_data in util.discover_movie_sort) or (self.library.is_show and discover_data in util.discover_tv_sort): + new_dictionary[discover_final] = discover_data else: - raise Failed(f"Collection Error: {m} attribute {a_name}: {self.data[m][a]} is invalid") - elif a_name == "certification_country": - if "certification" in self.data[m] or "certification.lte" in self.data[m] or "certification.gte" in self.data[m]: - new_dictionary[a_name] = self.data[m][a] + raise Failed(f"Collection Error: {method_name} attribute {discover_final}: {discover_data} is invalid") + elif discover_final == "certification_country": + if "certification" in method_data or "certification.lte" in method_data or "certification.gte" in method_data: + new_dictionary[discover_final] = discover_data else: - raise Failed(f"Collection Error: {m} attribute {a_name}: must be used with either certification, certification.lte, or certification.gte") - elif a_name in ["certification", "certification.lte", "certification.gte"]: - if "certification_country" in self.data[m]: - new_dictionary[a_name] = self.data[m][a] + raise Failed(f"Collection Error: {method_name} attribute {discover_final}: must be used with either certification, certification.lte, or certification.gte") + elif discover_final in ["certification", "certification.lte", "certification.gte"]: + if "certification_country" in method_data: + new_dictionary[discover_final] = discover_data else: - raise Failed(f"Collection Error: {m} attribute {a_name}: must be used with certification_country") - elif a_name in ["include_adult", "include_null_first_air_dates", "screened_theatrically"]: - if self.data[m][a] is True: - new_dictionary[a_name] = self.data[m][a] - elif a_name in util.discover_dates: - new_dictionary[a_name] = util.check_date(self.data[m][a], f"{m} attribute {a_name}", return_string=True) - elif a_name in ["primary_release_year", "year", "first_air_date_year"]: - new_dictionary[a_name] = util.check_number(self.data[m][a], f"{m} attribute {a_name}", minimum=1800, maximum=current_year + 1) - elif a_name in ["vote_count.gte", "vote_count.lte", "vote_average.gte", "vote_average.lte", "with_runtime.gte", "with_runtime.lte"]: - new_dictionary[a_name] = util.check_number(self.data[m][a], f"{m} attribute {a_name}", minimum=1) - elif a_name in ["with_cast", "with_crew", "with_people", "with_companies", "with_networks", "with_genres", "without_genres", "with_keywords", "without_keywords", "with_original_language", "timezone"]: - new_dictionary[a_name] = self.data[m][a] + raise Failed(f"Collection Error: {method_name} attribute {discover_final}: must be used with certification_country") + elif discover_final in ["include_adult", "include_null_first_air_dates", "screened_theatrically"]: + if discover_data is True: + new_dictionary[discover_final] = discover_data + elif discover_final in util.discover_dates: + new_dictionary[discover_final] = util.check_date(discover_data, f"{method_name} attribute {discover_final}", return_string=True) + elif discover_final in ["primary_release_year", "year", "first_air_date_year"]: + new_dictionary[discover_final] = util.check_number(discover_data, f"{method_name} attribute {discover_final}", minimum=1800, maximum=current_year + 1) + elif discover_final in ["vote_count.gte", "vote_count.lte", "vote_average.gte", "vote_average.lte", "with_runtime.gte", "with_runtime.lte"]: + new_dictionary[discover_final] = util.check_number(discover_data, f"{method_name} attribute {discover_final}", minimum=1) + elif discover_final in ["with_cast", "with_crew", "with_people", "with_companies", "with_networks", "with_genres", "without_genres", "with_keywords", "without_keywords", "with_original_language", "timezone"]: + new_dictionary[discover_final] = discover_data else: - raise Failed(f"Collection Error: {m} attribute {a_name} not supported") - elif a_name == "limit": - if isinstance(self.data[m][a], int) and self.data[m][a] > 0: - new_dictionary[a_name] = self.data[m][a] + raise Failed(f"Collection Error: {method_name} attribute {discover_final} not supported") + elif discover_final == "limit": + if isinstance(discover_data, int) and discover_data > 0: + new_dictionary[discover_final] = discover_data else: - raise Failed(f"Collection Error: {m} attribute {a_name}: must be a valid number greater then 0") + raise Failed(f"Collection Error: {method_name} attribute {discover_final}: must be a valid number greater then 0") else: - raise Failed(f"Collection Error: {m} attribute {a_name} not supported") + raise Failed(f"Collection Error: {method_name} attribute {discover_final} not supported") else: - raise Failed(f"Collection Error: {m} parameter {a_name} is blank") + raise Failed(f"Collection Error: {method_name} parameter {discover_final} is blank") if len(new_dictionary) > 1: self.methods.append((method_name, [new_dictionary])) else: - raise Failed(f"Collection Error: {m} had no valid fields") + raise Failed(f"Collection Error: {method_name} had no valid fields") elif "tautulli" in method_name: new_dictionary = {} if method_name == "tautulli_popular": @@ -527,22 +527,22 @@ class CollectionBuilder: new_dictionary["list_type"] = "watched" else: raise Failed(f"Collection Error: {method_name} attribute not supported") - dict_methods = {dm.lower(): dm for dm in self.data[m]} - new_dictionary["list_days"] = get_int(method_name, "list_days", self.data[m], dict_methods, 30) - new_dictionary["list_size"] = get_int(method_name, "list_size", self.data[m], dict_methods, 10) - new_dictionary["list_buffer"] = get_int(method_name, "list_buffer", self.data[m], dict_methods, 20) + dict_methods = {dm.lower(): dm for dm in method_data} + new_dictionary["list_days"] = get_int(method_name, "list_days", method_data, dict_methods, 30) + new_dictionary["list_size"] = get_int(method_name, "list_size", method_data, dict_methods, 10) + new_dictionary["list_buffer"] = get_int(method_name, "list_buffer", method_data, dict_methods, 20) self.methods.append((method_name, [new_dictionary])) elif method_name == "mal_season": new_dictionary = {"sort_by": "anime_num_list_users"} - dict_methods = {dm.lower(): dm for dm in self.data[m]} + dict_methods = {dm.lower(): dm for dm in method_data} if "sort_by" not in dict_methods: logger.warning("Collection Warning: mal_season sort_by attribute not found using members as default") - elif not self.data[m][dict_methods["sort_by"]]: + elif not method_data[dict_methods["sort_by"]]: logger.warning("Collection Warning: mal_season sort_by attribute is blank using members as default") - elif self.data[m][dict_methods["sort_by"]] not in util.mal_season_sort: - logger.warning(f"Collection Warning: mal_season sort_by attribute {self.data[m][dict_methods['sort_by']]} invalid must be either 'members' or 'score' using members as default") + elif method_data[dict_methods["sort_by"]] not in util.mal_season_sort: + logger.warning(f"Collection Warning: mal_season sort_by attribute {method_data[dict_methods['sort_by']]} invalid must be either 'members' or 'score' using members as default") else: - new_dictionary["sort_by"] = util.mal_season_sort[self.data[m][dict_methods["sort_by"]]] + new_dictionary["sort_by"] = util.mal_season_sort[method_data[dict_methods["sort_by"]]] if current_time.month in [1, 2, 3]: new_dictionary["season"] = "winter" elif current_time.month in [4, 5, 6]: new_dictionary["season"] = "spring" @@ -551,49 +551,49 @@ class CollectionBuilder: if "season" not in dict_methods: logger.warning(f"Collection Warning: mal_season season attribute not found using the current season: {new_dictionary['season']} as default") - elif not self.data[m][dict_methods["season"]]: + elif not method_data[dict_methods["season"]]: logger.warning(f"Collection Warning: mal_season season attribute is blank using the current season: {new_dictionary['season']} as default") - elif self.data[m][dict_methods["season"]] not in util.pretty_seasons: - logger.warning(f"Collection Warning: mal_season season attribute {self.data[m][dict_methods['season']]} invalid must be either 'winter', 'spring', 'summer' or 'fall' using the current season: {new_dictionary['season']} as default") + elif method_data[dict_methods["season"]] not in util.pretty_seasons: + logger.warning(f"Collection Warning: mal_season season attribute {method_data[dict_methods['season']]} invalid must be either 'winter', 'spring', 'summer' or 'fall' using the current season: {new_dictionary['season']} as default") else: - new_dictionary["season"] = self.data[m][dict_methods["season"]] + new_dictionary["season"] = method_data[dict_methods["season"]] - new_dictionary["year"] = get_int(method_name, "year", self.data[m], dict_methods, current_time.year, minimum=1917, maximum=current_time.year + 1) - new_dictionary["limit"] = get_int(method_name, "limit", self.data[m], dict_methods, 100, maximum=500) + new_dictionary["year"] = get_int(method_name, "year", method_data, dict_methods, current_time.year, minimum=1917, maximum=current_time.year + 1) + new_dictionary["limit"] = get_int(method_name, "limit", method_data, dict_methods, 100, maximum=500) self.methods.append((method_name, [new_dictionary])) elif method_name == "mal_userlist": new_dictionary = {"status": "all", "sort_by": "list_score"} - dict_methods = {dm.lower(): dm for dm in self.data[m]} + dict_methods = {dm.lower(): dm for dm in method_data} if "username" not in dict_methods: raise Failed("Collection Error: mal_userlist username attribute is required") - elif not self.data[m][dict_methods["username"]]: + elif not method_data[dict_methods["username"]]: raise Failed("Collection Error: mal_userlist username attribute is blank") else: - new_dictionary["username"] = self.data[m][dict_methods["username"]] + new_dictionary["username"] = method_data[dict_methods["username"]] if "status" not in dict_methods: logger.warning("Collection Warning: mal_season status attribute not found using all as default") - elif not self.data[m][dict_methods["status"]]: + elif not method_data[dict_methods["status"]]: logger.warning("Collection Warning: mal_season status attribute is blank using all as default") - elif self.data[m][dict_methods["status"]] not in util.mal_userlist_status: - logger.warning(f"Collection Warning: mal_season status attribute {self.data[m][dict_methods['status']]} invalid must be either 'all', 'watching', 'completed', 'on_hold', 'dropped' or 'plan_to_watch' using all as default") + elif method_data[dict_methods["status"]] not in util.mal_userlist_status: + logger.warning(f"Collection Warning: mal_season status attribute {method_data[dict_methods['status']]} invalid must be either 'all', 'watching', 'completed', 'on_hold', 'dropped' or 'plan_to_watch' using all as default") else: - new_dictionary["status"] = util.mal_userlist_status[self.data[m][dict_methods["status"]]] + new_dictionary["status"] = util.mal_userlist_status[method_data[dict_methods["status"]]] if "sort_by" not in dict_methods: logger.warning("Collection Warning: mal_season sort_by attribute not found using score as default") - elif not self.data[m][dict_methods["sort_by"]]: + elif not method_data[dict_methods["sort_by"]]: logger.warning("Collection Warning: mal_season sort_by attribute is blank using score as default") - elif self.data[m][dict_methods["sort_by"]] not in util.mal_userlist_sort: - logger.warning(f"Collection Warning: mal_season sort_by attribute {self.data[m][dict_methods['sort_by']]} invalid must be either 'score', 'last_updated', 'title' or 'start_date' using score as default") + elif method_data[dict_methods["sort_by"]] not in util.mal_userlist_sort: + logger.warning(f"Collection Warning: mal_season sort_by attribute {method_data[dict_methods['sort_by']]} invalid must be either 'score', 'last_updated', 'title' or 'start_date' using score as default") else: - new_dictionary["sort_by"] = util.mal_userlist_sort[self.data[m][dict_methods["sort_by"]]] + new_dictionary["sort_by"] = util.mal_userlist_sort[method_data[dict_methods["sort_by"]]] - new_dictionary["limit"] = get_int(method_name, "limit", self.data[m], dict_methods, 100, maximum=1000) + new_dictionary["limit"] = get_int(method_name, "limit", method_data, dict_methods, 100, maximum=1000) self.methods.append((method_name, [new_dictionary])) elif "anilist" in method_name: new_dictionary = {"sort_by": "score"} - dict_methods = {dm.lower(): dm for dm in self.data[m]} + dict_methods = {dm.lower(): dm for dm in method_data} if method_name == "anilist_season": if current_time.month in [12, 1, 2]: new_dictionary["season"] = "winter" elif current_time.month in [3, 4, 5]: new_dictionary["season"] = "spring" @@ -602,51 +602,51 @@ class CollectionBuilder: if "season" not in dict_methods: logger.warning(f"Collection Warning: anilist_season season attribute not found using the current season: {new_dictionary['season']} as default") - elif not self.data[m][dict_methods["season"]]: + elif not method_data[dict_methods["season"]]: logger.warning(f"Collection Warning: anilist_season season attribute is blank using the current season: {new_dictionary['season']} as default") - elif self.data[m][dict_methods["season"]] not in util.pretty_seasons: - logger.warning(f"Collection Warning: anilist_season season attribute {self.data[m][dict_methods['season']]} invalid must be either 'winter', 'spring', 'summer' or 'fall' using the current season: {new_dictionary['season']} as default") + elif method_data[dict_methods["season"]] not in util.pretty_seasons: + logger.warning(f"Collection Warning: anilist_season season attribute {method_data[dict_methods['season']]} invalid must be either 'winter', 'spring', 'summer' or 'fall' using the current season: {new_dictionary['season']} as default") else: - new_dictionary["season"] = self.data[m][dict_methods["season"]] + new_dictionary["season"] = method_data[dict_methods["season"]] - new_dictionary["year"] = get_int(method_name, "year", self.data[m], dict_methods, current_time.year, minimum=1917, maximum=current_time.year + 1) + new_dictionary["year"] = get_int(method_name, "year", method_data, dict_methods, current_time.year, minimum=1917, maximum=current_time.year + 1) elif method_name == "anilist_genre": if "genre" not in dict_methods: raise Failed(f"Collection Warning: anilist_genre genre attribute not found") - elif not self.data[m][dict_methods["genre"]]: + elif not method_data[dict_methods["genre"]]: raise Failed(f"Collection Warning: anilist_genre genre attribute is blank") else: - new_dictionary["genre"] = self.config.AniList.validate_genre(self.data[m][dict_methods["genre"]]) + new_dictionary["genre"] = self.config.AniList.validate_genre(method_data[dict_methods["genre"]]) elif method_name == "anilist_tag": if "tag" not in dict_methods: raise Failed(f"Collection Warning: anilist_tag tag attribute not found") - elif not self.data[m][dict_methods["tag"]]: + elif not method_data[dict_methods["tag"]]: raise Failed(f"Collection Warning: anilist_tag tag attribute is blank") else: - new_dictionary["tag"] = self.config.AniList.validate_tag(self.data[m][dict_methods["tag"]]) + new_dictionary["tag"] = self.config.AniList.validate_tag(method_data[dict_methods["tag"]]) if "sort_by" not in dict_methods: logger.warning(f"Collection Warning: {method_name} sort_by attribute not found using score as default") - elif not self.data[m][dict_methods["sort_by"]]: + elif not method_data[dict_methods["sort_by"]]: logger.warning(f"Collection Warning: {method_name} sort_by attribute is blank using score as default") - elif str(self.data[m][dict_methods["sort_by"]]).lower() not in ["score", "popular"]: - logger.warning(f"Collection Warning: {method_name} sort_by attribute {self.data[m][dict_methods['sort_by']]} invalid must be either 'score' or 'popular' using score as default") + elif str(method_data[dict_methods["sort_by"]]).lower() not in ["score", "popular"]: + logger.warning(f"Collection Warning: {method_name} sort_by attribute {method_data[dict_methods['sort_by']]} invalid must be either 'score' or 'popular' using score as default") else: - new_dictionary["sort_by"] = self.data[m][dict_methods["sort_by"]] + new_dictionary["sort_by"] = method_data[dict_methods["sort_by"]] - new_dictionary["limit"] = get_int(method_name, "limit", self.data[m], dict_methods, 0, maximum=500) + new_dictionary["limit"] = get_int(method_name, "limit", method_data, dict_methods, 0, maximum=500) self.methods.append((method_name, [new_dictionary])) else: - raise Failed(f"Collection Error: {m} attribute is not a dictionary: {self.data[m]}") + raise Failed(f"Collection Error: {method_name} attribute is not a dictionary: {method_data}") elif method_name in util.count_lists: - list_count = util.regex_first_int(self.data[m], "List Size", default=10) + list_count = util.regex_first_int(method_data, "List Size", default=10) if list_count < 1: logger.warning(f"Collection Warning: {method_name} must be an integer greater then 0 defaulting to 10") list_count = 10 self.methods.append((method_name, [list_count])) elif "tvdb" in method_name: - values = util.get_list(self.data[m]) + values = util.get_list(method_data) if method_name[-8:] == "_details": if method_name == "tvdb_movie_details": item = config.TVDb.get_movie(self.library.Plex.language, values[0]) @@ -670,7 +670,7 @@ class CollectionBuilder: else: self.methods.append((method_name, values)) elif method_name in util.tmdb_lists: - values = config.TMDb.validate_tmdb_list(util.get_int_list(self.data[m], f"TMDb {util.tmdb_type[method_name]} ID"), util.tmdb_type[method_name]) + values = config.TMDb.validate_tmdb_list(util.get_int_list(method_data, f"TMDb {util.tmdb_type[method_name]} ID"), util.tmdb_type[method_name]) if method_name[-8:] == "_details": if method_name in ["tmdb_collection_details", "tmdb_movie_details", "tmdb_show_details"]: item = config.TMDb.get_movie_show_or_collection(values[0], self.library.is_movie) @@ -694,13 +694,13 @@ class CollectionBuilder: else: self.methods.append((method_name, values)) elif method_name in util.all_lists: - self.methods.append((method_name, util.get_list(self.data[m]))) + self.methods.append((method_name, util.get_list(method_data))) elif method_name not in util.other_attributes: raise Failed(f"Collection Error: {method_name} attribute not supported") - elif m in util.all_lists or m in util.method_alias or m in util.plex_searches: - raise Failed(f"Collection Error: {m} attribute is blank") + elif method_name in util.all_lists or method_name in util.method_alias or method_name in util.plex_searches: + raise Failed(f"Collection Error: {method_name} attribute is blank") else: - logger.warning(f"Collection Warning: {m} attribute is blank") + logger.warning(f"Collection Warning: {method_name} attribute is blank") self.sync = self.library.sync_mode == "sync" if "sync_mode" in methods: diff --git a/modules/config.py b/modules/config.py index 45aea8cd..69ea0c2c 100644 --- a/modules/config.py +++ b/modules/config.py @@ -267,47 +267,47 @@ class Config: self.libraries = [] try: libs = check_for_attribute(self.data, "libraries", throw=True) except Failed as e: raise Failed(e) - for lib in libs: + for library_name, lib in libs.items(): util.separator() params = {} - if "library_name" in libs[lib] and libs[lib]["library_name"]: - params["name"] = str(libs[lib]["library_name"]) - logger.info(f"Connecting to {params['name']} ({lib}) Library...") + if "library_name" in lib and lib["library_name"]: + params["name"] = str(lib["library_name"]) + logger.info(f"Connecting to {params['name']} ({library_name}) Library...") else: - params["name"] = str(lib) + params["name"] = str(library_name) logger.info(f"Connecting to {params['name']} Library...") - params["asset_directory"] = check_for_attribute(libs[lib], "asset_directory", parent="settings", var_type="list_path", default=self.general["asset_directory"], default_is_none=True, save=False) + params["asset_directory"] = check_for_attribute(lib, "asset_directory", parent="settings", var_type="list_path", default=self.general["asset_directory"], default_is_none=True, save=False) if params["asset_directory"] is None: logger.warning("Config Warning: Assets will not be used asset_directory attribute must be set under config or under this specific Library") - if "settings" in libs[lib] and libs[lib]["settings"] and "sync_mode" in libs[lib]["settings"]: - params["sync_mode"] = check_for_attribute(libs[lib], "sync_mode", parent="settings", test_list=["append", "sync"], options=" append (Only Add Items to the Collection)\n sync (Add & Remove Items from the Collection)", default=self.general["sync_mode"], do_print=False, save=False) + if "settings" in lib and lib["settings"] and "sync_mode" in lib["settings"]: + params["sync_mode"] = check_for_attribute(lib, "sync_mode", parent="settings", test_list=["append", "sync"], options=" append (Only Add Items to the Collection)\n sync (Add & Remove Items from the Collection)", default=self.general["sync_mode"], do_print=False, save=False) else: - params["sync_mode"] = check_for_attribute(libs[lib], "sync_mode", test_list=["append", "sync"], options=" append (Only Add Items to the Collection)\n sync (Add & Remove Items from the Collection)", default=self.general["sync_mode"], do_print=False, save=False) + params["sync_mode"] = check_for_attribute(lib, "sync_mode", test_list=["append", "sync"], options=" append (Only Add Items to the Collection)\n sync (Add & Remove Items from the Collection)", default=self.general["sync_mode"], do_print=False, save=False) - if "settings" in libs[lib] and libs[lib]["settings"] and "show_unmanaged" in libs[lib]["settings"]: - params["show_unmanaged"] = check_for_attribute(libs[lib], "show_unmanaged", parent="settings", var_type="bool", default=self.general["show_unmanaged"], do_print=False, save=False) + if "settings" in lib and lib["settings"] and "show_unmanaged" in lib["settings"]: + params["show_unmanaged"] = check_for_attribute(lib, "show_unmanaged", parent="settings", var_type="bool", default=self.general["show_unmanaged"], do_print=False, save=False) else: - params["show_unmanaged"] = check_for_attribute(libs[lib], "show_unmanaged", var_type="bool", default=self.general["show_unmanaged"], do_print=False, save=False) + params["show_unmanaged"] = check_for_attribute(lib, "show_unmanaged", var_type="bool", default=self.general["show_unmanaged"], do_print=False, save=False) - if "settings" in libs[lib] and libs[lib]["settings"] and "show_filtered" in libs[lib]["settings"]: - params["show_filtered"] = check_for_attribute(libs[lib], "show_filtered", parent="settings", var_type="bool", default=self.general["show_filtered"], do_print=False, save=False) + if "settings" in lib and lib["settings"] and "show_filtered" in lib["settings"]: + params["show_filtered"] = check_for_attribute(lib, "show_filtered", parent="settings", var_type="bool", default=self.general["show_filtered"], do_print=False, save=False) else: - params["show_filtered"] = check_for_attribute(libs[lib], "show_filtered", var_type="bool", default=self.general["show_filtered"], do_print=False, save=False) + params["show_filtered"] = check_for_attribute(lib, "show_filtered", var_type="bool", default=self.general["show_filtered"], do_print=False, save=False) - if "settings" in libs[lib] and libs[lib]["settings"] and "show_missing" in libs[lib]["settings"]: - params["show_missing"] = check_for_attribute(libs[lib], "show_missing", parent="settings", var_type="bool", default=self.general["show_missing"], do_print=False, save=False) + if "settings" in lib and lib["settings"] and "show_missing" in lib["settings"]: + params["show_missing"] = check_for_attribute(lib, "show_missing", parent="settings", var_type="bool", default=self.general["show_missing"], do_print=False, save=False) else: - params["show_missing"] = check_for_attribute(libs[lib], "show_missing", var_type="bool", default=self.general["show_missing"], do_print=False, save=False) + params["show_missing"] = check_for_attribute(lib, "show_missing", var_type="bool", default=self.general["show_missing"], do_print=False, save=False) - if "settings" in libs[lib] and libs[lib]["settings"] and "save_missing" in libs[lib]["settings"]: - params["save_missing"] = check_for_attribute(libs[lib], "save_missing", parent="settings", var_type="bool", default=self.general["save_missing"], do_print=False, save=False) + if "settings" in lib and lib["settings"] and "save_missing" in lib["settings"]: + params["save_missing"] = check_for_attribute(lib, "save_missing", parent="settings", var_type="bool", default=self.general["save_missing"], do_print=False, save=False) else: - params["save_missing"] = check_for_attribute(libs[lib], "save_missing", var_type="bool", default=self.general["save_missing"], do_print=False, save=False) + params["save_missing"] = check_for_attribute(lib, "save_missing", var_type="bool", default=self.general["save_missing"], do_print=False, save=False) - if "mass_genre_update" in libs[lib] and libs[lib]["mass_genre_update"]: - params["mass_genre_update"] = check_for_attribute(libs[lib], "mass_genre_update", test_list=["tmdb", "omdb"], options=" tmdb (Use TMDb Metadata)\n omdb (Use IMDb Metadata through OMDb)", default_is_none=True, save=False) + if "mass_genre_update" in lib and lib["mass_genre_update"]: + params["mass_genre_update"] = check_for_attribute(lib, "mass_genre_update", test_list=["tmdb", "omdb"], options=" tmdb (Use TMDb Metadata)\n omdb (Use IMDb Metadata through OMDb)", default_is_none=True, save=False) else: params["mass_genre_update"] = None @@ -316,12 +316,12 @@ class Config: logger.error("Config Error: mass_genre_update cannot be omdb without a successful OMDb Connection") try: - params["metadata_path"] = check_for_attribute(libs[lib], "metadata_path", var_type="path", default=os.path.join(default_dir, f"{lib}.yml"), throw=True) - params["library_type"] = check_for_attribute(libs[lib], "library_type", test_list=["movie", "show"], options=" movie (For Movie Libraries)\n show (For Show Libraries)", throw=True) + params["metadata_path"] = check_for_attribute(lib, "metadata_path", var_type="path", default=os.path.join(default_dir, f"{library_name}.yml"), throw=True) + params["library_type"] = check_for_attribute(lib, "library_type", test_list=["movie", "show"], options=" movie (For Movie Libraries)\n show (For Show Libraries)", throw=True) params["plex"] = {} - params["plex"]["url"] = check_for_attribute(libs[lib], "url", parent="plex", default=self.general["plex"]["url"], req_default=True, save=False) - params["plex"]["token"] = check_for_attribute(libs[lib], "token", parent="plex", default=self.general["plex"]["token"], req_default=True, save=False) - params["plex"]["timeout"] = check_for_attribute(libs[lib], "timeout", parent="plex", var_type="int", default=self.general["plex"]["timeout"], save=False) + params["plex"]["url"] = check_for_attribute(lib, "url", parent="plex", default=self.general["plex"]["url"], req_default=True, save=False) + params["plex"]["token"] = check_for_attribute(lib, "token", parent="plex", default=self.general["plex"]["token"], req_default=True, save=False) + params["plex"]["timeout"] = check_for_attribute(lib, "timeout", parent="plex", var_type="int", default=self.general["plex"]["timeout"], save=False) library = PlexAPI(params, self.TMDb, self.TVDb) logger.info(f"{params['name']} Library Connection Successful") except Failed as e: @@ -329,47 +329,47 @@ class Config: logger.info(f"{params['name']} Library Connection Failed") continue - if self.general["radarr"]["url"] or "radarr" in libs[lib]: + if self.general["radarr"]["url"] or "radarr" in lib: logger.info(f"Connecting to {params['name']} library's Radarr...") radarr_params = {} try: - radarr_params["url"] = check_for_attribute(libs[lib], "url", parent="radarr", default=self.general["radarr"]["url"], req_default=True, save=False) - radarr_params["token"] = check_for_attribute(libs[lib], "token", parent="radarr", default=self.general["radarr"]["token"], req_default=True, save=False) - radarr_params["version"] = check_for_attribute(libs[lib], "version", parent="radarr", test_list=["v2", "v3"], options=" v2 (For Radarr 0.2)\n v3 (For Radarr 3.0)", default=self.general["radarr"]["version"], save=False) - radarr_params["quality_profile"] = check_for_attribute(libs[lib], "quality_profile", parent="radarr", default=self.general["radarr"]["quality_profile"], req_default=True, save=False) - radarr_params["root_folder_path"] = check_for_attribute(libs[lib], "root_folder_path", parent="radarr", default=self.general["radarr"]["root_folder_path"], req_default=True, save=False) - radarr_params["add"] = check_for_attribute(libs[lib], "add", parent="radarr", var_type="bool", default=self.general["radarr"]["add"], save=False) - radarr_params["search"] = check_for_attribute(libs[lib], "search", parent="radarr", var_type="bool", default=self.general["radarr"]["search"], save=False) - radarr_params["tag"] = check_for_attribute(libs[lib], "search", parent="radarr", var_type="lower_list", default=self.general["radarr"]["tag"], default_is_none=True, save=False) + radarr_params["url"] = check_for_attribute(lib, "url", parent="radarr", default=self.general["radarr"]["url"], req_default=True, save=False) + radarr_params["token"] = check_for_attribute(lib, "token", parent="radarr", default=self.general["radarr"]["token"], req_default=True, save=False) + radarr_params["version"] = check_for_attribute(lib, "version", parent="radarr", test_list=["v2", "v3"], options=" v2 (For Radarr 0.2)\n v3 (For Radarr 3.0)", default=self.general["radarr"]["version"], save=False) + radarr_params["quality_profile"] = check_for_attribute(lib, "quality_profile", parent="radarr", default=self.general["radarr"]["quality_profile"], req_default=True, save=False) + radarr_params["root_folder_path"] = check_for_attribute(lib, "root_folder_path", parent="radarr", default=self.general["radarr"]["root_folder_path"], req_default=True, save=False) + radarr_params["add"] = check_for_attribute(lib, "add", parent="radarr", var_type="bool", default=self.general["radarr"]["add"], save=False) + radarr_params["search"] = check_for_attribute(lib, "search", parent="radarr", var_type="bool", default=self.general["radarr"]["search"], save=False) + radarr_params["tag"] = check_for_attribute(lib, "search", parent="radarr", var_type="lower_list", default=self.general["radarr"]["tag"], default_is_none=True, save=False) library.Radarr = RadarrAPI(self.TMDb, radarr_params) except Failed as e: util.print_multiline(e) logger.info(f"{params['name']} library's Radarr Connection {'Failed' if library.Radarr is None else 'Successful'}") - if self.general["sonarr"]["url"] or "sonarr" in libs[lib]: + if self.general["sonarr"]["url"] or "sonarr" in lib: logger.info(f"Connecting to {params['name']} library's Sonarr...") sonarr_params = {} try: - sonarr_params["url"] = check_for_attribute(libs[lib], "url", parent="sonarr", default=self.general["sonarr"]["url"], req_default=True, save=False) - sonarr_params["token"] = check_for_attribute(libs[lib], "token", parent="sonarr", default=self.general["sonarr"]["token"], req_default=True, save=False) - sonarr_params["version"] = check_for_attribute(libs[lib], "version", parent="sonarr", test_list=["v2", "v3"], options=" v2 (For Sonarr 0.2)\n v3 (For Sonarr 3.0)", default=self.general["sonarr"]["version"], save=False) - sonarr_params["quality_profile"] = check_for_attribute(libs[lib], "quality_profile", parent="sonarr", default=self.general["sonarr"]["quality_profile"], req_default=True, save=False) - sonarr_params["root_folder_path"] = check_for_attribute(libs[lib], "root_folder_path", parent="sonarr", default=self.general["sonarr"]["root_folder_path"], req_default=True, save=False) - sonarr_params["add"] = check_for_attribute(libs[lib], "add", parent="sonarr", var_type="bool", default=self.general["sonarr"]["add"], save=False) - sonarr_params["search"] = check_for_attribute(libs[lib], "search", parent="sonarr", var_type="bool", default=self.general["sonarr"]["search"], save=False) - sonarr_params["season_folder"] = check_for_attribute(libs[lib], "season_folder", parent="sonarr", var_type="bool", default=self.general["sonarr"]["season_folder"], save=False) - sonarr_params["tag"] = check_for_attribute(libs[lib], "search", parent="sonarr", var_type="lower_list", default=self.general["sonarr"]["tag"], default_is_none=True, save=False) + sonarr_params["url"] = check_for_attribute(lib, "url", parent="sonarr", default=self.general["sonarr"]["url"], req_default=True, save=False) + sonarr_params["token"] = check_for_attribute(lib, "token", parent="sonarr", default=self.general["sonarr"]["token"], req_default=True, save=False) + sonarr_params["version"] = check_for_attribute(lib, "version", parent="sonarr", test_list=["v2", "v3"], options=" v2 (For Sonarr 0.2)\n v3 (For Sonarr 3.0)", default=self.general["sonarr"]["version"], save=False) + sonarr_params["quality_profile"] = check_for_attribute(lib, "quality_profile", parent="sonarr", default=self.general["sonarr"]["quality_profile"], req_default=True, save=False) + sonarr_params["root_folder_path"] = check_for_attribute(lib, "root_folder_path", parent="sonarr", default=self.general["sonarr"]["root_folder_path"], req_default=True, save=False) + sonarr_params["add"] = check_for_attribute(lib, "add", parent="sonarr", var_type="bool", default=self.general["sonarr"]["add"], save=False) + sonarr_params["search"] = check_for_attribute(lib, "search", parent="sonarr", var_type="bool", default=self.general["sonarr"]["search"], save=False) + sonarr_params["season_folder"] = check_for_attribute(lib, "season_folder", parent="sonarr", var_type="bool", default=self.general["sonarr"]["season_folder"], save=False) + sonarr_params["tag"] = check_for_attribute(lib, "search", parent="sonarr", var_type="lower_list", default=self.general["sonarr"]["tag"], default_is_none=True, save=False) library.Sonarr = SonarrAPI(self.TVDb, sonarr_params, library.Plex.language) except Failed as e: util.print_multiline(e) logger.info(f"{params['name']} library's Sonarr Connection {'Failed' if library.Sonarr is None else 'Successful'}") - if self.general["tautulli"]["url"] or "tautulli" in libs[lib]: + if self.general["tautulli"]["url"] or "tautulli" in lib: logger.info(f"Connecting to {params['name']} library's Tautulli...") tautulli_params = {} try: - tautulli_params["url"] = check_for_attribute(libs[lib], "url", parent="tautulli", default=self.general["tautulli"]["url"], req_default=True, save=False) - tautulli_params["apikey"] = check_for_attribute(libs[lib], "apikey", parent="tautulli", default=self.general["tautulli"]["apikey"], req_default=True, save=False) + tautulli_params["url"] = check_for_attribute(lib, "url", parent="tautulli", default=self.general["tautulli"]["url"], req_default=True, save=False) + tautulli_params["apikey"] = check_for_attribute(lib, "apikey", parent="tautulli", default=self.general["tautulli"]["apikey"], req_default=True, save=False) library.Tautulli = TautulliAPI(tautulli_params) except Failed as e: util.print_multiline(e) @@ -404,11 +404,11 @@ class Config: util.separator(f"{library.name} Library {'Test ' if test else ''}Collections") collections = {c: library.collections[c] for c in util.get_list(requested_collections) if c in library.collections} if requested_collections else library.collections if collections: - for c in collections: - if test and ("test" not in collections[c] or collections[c]["test"] is not True): + for mapping_name, collection_attrs in collections.items(): + if test and ("test" not in collection_attrs or collection_attrs["test"] is not True): no_template_test = True - if "template" in collections[c] and collections[c]["template"]: - for data_template in util.get_list(collections[c]["template"], split=False): + if "template" in collection_attrs and collection_attrs["template"]: + for data_template in util.get_list(collection_attrs["template"], split=False): if "name" in data_template \ and data_template["name"] \ and library.templates \ @@ -421,13 +421,14 @@ class Config: continue try: logger.info("") - util.separator(f"{c} Collection") + util.separator(f"{mapping_name} Collection") logger.info("") rating_key_map = {} try: - builder = CollectionBuilder(self, library, c, collections[c]) + builder = CollectionBuilder(self, library, mapping_name, collection_attrs) except Failed as ef: + util.print_stacktrace() util.print_multiline(ef, error=True) continue except Exception as ee: @@ -436,11 +437,11 @@ class Config: continue try: - collection_obj = library.get_collection(c) + collection_obj = library.get_collection(mapping_name) collection_name = collection_obj.title except Failed: collection_obj = None - collection_name = c + collection_name = mapping_name if len(builder.schedule) > 0: util.print_multiline(builder.schedule, info=True) diff --git a/modules/plex.py b/modules/plex.py index 3f783efc..66dc5c55 100644 --- a/modules/plex.py +++ b/modules/plex.py @@ -230,21 +230,21 @@ class PlexAPI: logger.info("") if not self.metadata: raise Failed("No metadata to edit") - for m in self.metadata: - methods = {mm.lower(): mm for mm in self.metadata[m]} - if test and ("test" not in methods or self.metadata[m][methods["test"]] is not True): + for mapping_name, meta in self.metadata.items(): + methods = {mm.lower(): mm for mm in meta} + if test and ("test" not in methods or meta[methods["test"]] is not True): continue logger.info("") util.separator() logger.info("") year = None if "year" in methods: - year = util.check_number(self.metadata[m][methods["year"]], "year", minimum=1800, maximum=datetime.now().year + 1) + year = util.check_number(meta[methods["year"]], "year", minimum=1800, maximum=datetime.now().year + 1) - title = m + title = mapping_name if "title" in methods: - if self.metadata[m][methods["title"]] is None: logger.error("Metadata Error: title attribute is blank") - else: title = self.metadata[m][methods["title"]] + if meta[methods["title"]] is None: logger.error("Metadata Error: title attribute is blank") + else: title = meta[methods["title"]] item = self.search_item(title, year=year) @@ -252,15 +252,15 @@ class PlexAPI: item = self.search_item(f"{title} (SUB)", year=year) if item is None and "alt_title" in methods: - if self.metadata[m][methods["alt_title"]] is None: + if meta[methods["alt_title"]] is None: logger.error("Metadata Error: alt_title attribute is blank") else: - alt_title = self.metadata[m]["alt_title"] + alt_title = meta["alt_title"] item = self.search_item(alt_title, year=year) if item is None: - logger.error(f"Plex Error: Item {m} not found") - logger.error(f"Skipping {m}") + logger.error(f"Plex Error: Item {mapping_name} not found") + logger.error(f"Skipping {mapping_name}") continue item_type = "Movie" if self.is_movie else "Show" @@ -269,9 +269,9 @@ class PlexAPI: tmdb_item = None try: if "tmdb_id" in methods: - if self.metadata[m][methods["tmdb_id"]] is None: logger.error("Metadata Error: tmdb_id attribute is blank") - elif self.is_show: logger.error("Metadata Error: tmdb_id attribute only works with movie libraries") - else: tmdb_item = TMDb.get_show(util.regex_first_int(self.metadata[m][methods["tmdb_id"]], "Show")) + if meta[methods["tmdb_id"]] is None: logger.error("Metadata Error: tmdb_id attribute is blank") + elif self.is_show: logger.error("Metadata Error: tmdb_id attribute only works with movie libraries") + else: tmdb_item = TMDb.get_show(util.regex_first_int(meta[methods["tmdb_id"]], "Show")) except Failed as e: logger.error(e) @@ -294,33 +294,33 @@ class PlexAPI: logger.info(f"Detail: {name} updated to {value}") else: logger.error(f"Metadata Error: {name} attribute is blank") - add_edit("title", item.title, self.metadata[m], methods, value=title) - add_edit("sort_title", item.titleSort, self.metadata[m], methods, key="titleSort") - add_edit("originally_available", str(item.originallyAvailableAt)[:-9], self.metadata[m], methods, key="originallyAvailableAt", value=originally_available) - add_edit("rating", item.rating, self.metadata[m], methods, value=rating) - add_edit("content_rating", item.contentRating, self.metadata[m], methods, key="contentRating") - add_edit("original_title", item.originalTitle, self.metadata[m], methods, key="originalTitle", value=original_title) - add_edit("studio", item.studio, self.metadata[m], methods, value=studio) - add_edit("tagline", item.tagline, self.metadata[m], methods, value=tagline) - add_edit("summary", item.summary, self.metadata[m], methods, value=summary) + add_edit("title", item.title, meta, methods, value=title) + add_edit("sort_title", item.titleSort, meta, methods, key="titleSort") + add_edit("originally_available", str(item.originallyAvailableAt)[:-9], meta, methods, key="originallyAvailableAt", value=originally_available) + add_edit("rating", item.rating, meta, methods, value=rating) + add_edit("content_rating", item.contentRating, meta, methods, key="contentRating") + add_edit("original_title", item.originalTitle, meta, methods, key="originalTitle", value=original_title) + add_edit("studio", item.studio, meta, methods, value=studio) + add_edit("tagline", item.tagline, meta, methods, value=tagline) + add_edit("summary", item.summary, meta, methods, value=summary) if len(edits) > 0: logger.debug(f"Details Update: {edits}") try: item.edit(**edits) item.reload() - logger.info(f"{item_type}: {m} Details Update Successful") + logger.info(f"{item_type}: {mapping_name} Details Update Successful") except BadRequest: util.print_stacktrace() - logger.error(f"{item_type}: {m} Details Update Failed") + logger.error(f"{item_type}: {mapping_name} Details Update Failed") else: - logger.info(f"{item_type}: {m} Details Update Not Needed") + logger.info(f"{item_type}: {mapping_name} Details Update Not Needed") advance_edits = {} if self.is_show: if "episode_sorting" in methods: - if self.metadata[m][methods["episode_sorting"]]: - method_data = str(self.metadata[m][methods["episode_sorting"]]).lower() + if meta[methods["episode_sorting"]]: + method_data = str(meta[methods["episode_sorting"]]).lower() if method_data in ["default", "oldest", "newest"]: if method_data == "default" and item.episodeSort != "-1": advance_edits["episodeSort"] = "-1" @@ -331,13 +331,13 @@ class PlexAPI: if "episodeSort" in advance_edits: logger.info(f"Detail: episode_sorting updated to {method_data}") else: - logger.error(f"Metadata Error: {self.metadata[m][methods['episode_sorting']]} episode_sorting attribute invalid") + logger.error(f"Metadata Error: {meta[methods['episode_sorting']]} episode_sorting attribute invalid") else: logger.error(f"Metadata Error: episode_sorting attribute is blank") if "keep_episodes" in methods: - if self.metadata[m][methods["keep_episodes"]]: - method_data = str(self.metadata[m][methods["keep_episodes"]]).lower() + if meta[methods["keep_episodes"]]: + method_data = str(meta[methods["keep_episodes"]]).lower() if method_data in ["all", "5_latest", "3_latest", "latest", "past_3", "past_7", "past_30"]: if method_data == "all" and item.autoDeletionItemPolicyUnwatchedLibrary != 0: advance_edits["autoDeletionItemPolicyUnwatchedLibrary"] = 0 @@ -356,13 +356,13 @@ class PlexAPI: if "autoDeletionItemPolicyUnwatchedLibrary" in advance_edits: logger.info(f"Detail: keep_episodes updated to {method_data}") else: - logger.error(f"Metadata Error: {self.metadata[m][methods['keep_episodes']]} keep_episodes attribute invalid") + logger.error(f"Metadata Error: {meta[methods['keep_episodes']]} keep_episodes attribute invalid") else: logger.error(f"Metadata Error: keep_episodes attribute is blank") if "delete_episodes" in methods: - if self.metadata[m][methods["delete_episodes"]]: - method_data = str(self.metadata[m][methods["delete_episodes"]]).lower() + if meta[methods["delete_episodes"]]: + method_data = str(meta[methods["delete_episodes"]]).lower() if method_data in ["never", "day", "week", "refresh"]: if method_data == "never" and item.autoDeletionItemPolicyWatchedLibrary != 0: advance_edits["autoDeletionItemPolicyWatchedLibrary"] = 0 @@ -375,13 +375,13 @@ class PlexAPI: if "autoDeletionItemPolicyWatchedLibrary" in advance_edits: logger.info(f"Detail: delete_episodes updated to {method_data}") else: - logger.error(f"Metadata Error: {self.metadata[m][methods['delete_episodes']]} delete_episodes attribute invalid") + logger.error(f"Metadata Error: {meta[methods['delete_episodes']]} delete_episodes attribute invalid") else: logger.error(f"Metadata Error: delete_episodes attribute is blank") if "season_display" in methods: - if self.metadata[m][methods["season_display"]]: - method_data = str(self.metadata[m][methods["season_display"]]).lower() + if meta[methods["season_display"]]: + method_data = str(meta[methods["season_display"]]).lower() if method_data in ["default", "hide", "show"]: if method_data == "default" and item.flattenSeasons != -1: advance_edits["flattenSeasons"] = -1 @@ -392,13 +392,13 @@ class PlexAPI: if "flattenSeasons" in advance_edits: logger.info(f"Detail: season_display updated to {method_data}") else: - logger.error(f"Metadata Error: {self.metadata[m][methods['season_display']]} season_display attribute invalid") + logger.error(f"Metadata Error: {meta[methods['season_display']]} season_display attribute invalid") else: logger.error(f"Metadata Error: season_display attribute is blank") if "episode_ordering" in methods: - if self.metadata[m][methods["episode_ordering"]]: - method_data = str(self.metadata[m][methods["episode_ordering"]]).lower() + if meta[methods["episode_ordering"]]: + method_data = str(meta[methods["episode_ordering"]]).lower() if method_data in ["default", "tmdb_aired", "tvdb_aired", "tvdb_dvd", "tvdb_absolute"]: if method_data == "default" and item.showOrdering is not None: advance_edits["showOrdering"] = None @@ -413,13 +413,13 @@ class PlexAPI: if "showOrdering" in advance_edits: logger.info(f"Detail: episode_ordering updated to {method_data}") else: - logger.error(f"Metadata Error: {self.metadata[m][methods['episode_ordering']]} episode_ordering attribute invalid") + logger.error(f"Metadata Error: {meta[methods['episode_ordering']]} episode_ordering attribute invalid") else: logger.error(f"Metadata Error: episode_ordering attribute is blank") if "metadata_language" in methods: - if self.metadata[m][methods["metadata_language"]]: - method_data = str(self.metadata[m][methods["metadata_language"]]).lower() + if meta[methods["metadata_language"]]: + method_data = str(meta[methods["metadata_language"]]).lower() lower_languages = {la.lower(): la for la in util.plex_languages} if method_data in lower_languages: if method_data == "default" and item.languageOverride is None: @@ -429,13 +429,13 @@ class PlexAPI: if "languageOverride" in advance_edits: logger.info(f"Detail: metadata_language updated to {method_data}") else: - logger.error(f"Metadata Error: {self.metadata[m][methods['metadata_language']]} metadata_language attribute invalid") + logger.error(f"Metadata Error: {meta[methods['metadata_language']]} metadata_language attribute invalid") else: logger.error(f"Metadata Error: metadata_language attribute is blank") if "use_original_title" in methods: - if self.metadata[m][methods["use_original_title"]]: - method_data = str(self.metadata[m][methods["use_original_title"]]).lower() + if meta[methods["use_original_title"]]: + method_data = str(meta[methods["use_original_title"]]).lower() if method_data in ["default", "no", "yes"]: if method_data == "default" and item.useOriginalTitle != -1: advance_edits["useOriginalTitle"] = -1 @@ -446,7 +446,7 @@ class PlexAPI: if "useOriginalTitle" in advance_edits: logger.info(f"Detail: use_original_title updated to {method_data}") else: - logger.error(f"Metadata Error: {self.metadata[m][methods['use_original_title']]} use_original_title attribute invalid") + logger.error(f"Metadata Error: {meta[methods['use_original_title']]} use_original_title attribute invalid") else: logger.error(f"Metadata Error: use_original_title attribute is blank") @@ -457,29 +457,29 @@ class PlexAPI: logger.info(check_dict) item.editAdvanced(**advance_edits) item.reload() - logger.info(f"{item_type}: {m} Advanced Details Update Successful") + logger.info(f"{item_type}: {mapping_name} Advanced Details Update Successful") except BadRequest: util.print_stacktrace() - logger.error(f"{item_type}: {m} Details Update Failed") + logger.error(f"{item_type}: {mapping_name} Details Update Failed") else: - logger.info(f"{item_type}: {m} Details Update Not Needed") + logger.info(f"{item_type}: {mapping_name} Details Update Not Needed") genres = [] if tmdb_item: genres.extend([genre.name for genre in tmdb_item.genres]) if "genre" in methods: - if self.metadata[m][methods["genre"]]: - genres.extend(util.get_list(self.metadata[m][methods["genre"]])) + if meta[methods["genre"]]: + genres.extend(util.get_list(meta[methods["genre"]])) else: logger.error("Metadata Error: genre attribute is blank") if len(genres) > 0: item_genres = [genre.tag for genre in item.genres] if "genre_sync_mode" in methods: - if self.metadata[m][methods["genre_sync_mode"]] is None: + if meta[methods["genre_sync_mode"]] is None: logger.error("Metadata Error: genre_sync_mode attribute is blank defaulting to append") - elif str(self.metadata[m][methods["genre_sync_mode"]]).lower() not in ["append", "sync"]: + elif str(meta[methods["genre_sync_mode"]]).lower() not in ["append", "sync"]: logger.error("Metadata Error: genre_sync_mode attribute must be either 'append' or 'sync' defaulting to append") - elif str(self.metadata[m]["genre_sync_mode"]).lower() == "sync": + elif str(meta["genre_sync_mode"]).lower() == "sync": for genre in (g for g in item_genres if g not in genres): item.removeGenre(genre) logger.info(f"Detail: Genre {genre} removed") @@ -488,15 +488,15 @@ class PlexAPI: logger.info(f"Detail: Genre {genre} added") if "label" in methods: - if self.metadata[m][methods["label"]]: + if meta[methods["label"]]: item_labels = [label.tag for label in item.labels] - labels = util.get_list(self.metadata[m][methods["label"]]) + labels = util.get_list(meta[methods["label"]]) if "label_sync_mode" in methods: - if self.metadata[m][methods["label_sync_mode"]] is None: + if meta[methods["label_sync_mode"]] is None: logger.error("Metadata Error: label_sync_mode attribute is blank defaulting to append") - elif str(self.metadata[m][methods["label_sync_mode"]]).lower() not in ["append", "sync"]: + elif str(meta[methods["label_sync_mode"]]).lower() not in ["append", "sync"]: logger.error("Metadata Error: label_sync_mode attribute must be either 'append' or 'sync' defaulting to append") - elif str(self.metadata[m][methods["label_sync_mode"]]).lower() == "sync": + elif str(meta[methods["label_sync_mode"]]).lower() == "sync": for label in (la for la in item_labels if la not in labels): item.removeLabel(label) logger.info(f"Detail: Label {label} removed") @@ -507,15 +507,15 @@ class PlexAPI: logger.error("Metadata Error: label attribute is blank") if "seasons" in methods and self.is_show: - if self.metadata[m][methods["seasons"]]: - for season_id in self.metadata[m][methods["seasons"]]: + if meta[methods["seasons"]]: + for season_id in meta[methods["seasons"]]: logger.info("") - logger.info(f"Updating season {season_id} of {m}...") + logger.info(f"Updating season {season_id} of {mapping_name}...") if isinstance(season_id, int): try: season = item.season(season_id) except NotFound: logger.error(f"Metadata Error: Season: {season_id} not found") else: - season_dict = self.metadata[m][methods["seasons"]][season_id] + season_dict = meta[methods["seasons"]][season_id] season_methods = {sm.lower(): sm for sm in season_dict} if "title" in season_methods and season_dict[season_methods["title"]]: @@ -552,19 +552,19 @@ class PlexAPI: logger.error("Metadata Error: seasons attribute is blank") if "episodes" in methods and self.is_show: - if self.metadata[m][methods["episodes"]]: - for episode_str in self.metadata[m][methods["episodes"]]: + if meta[methods["episodes"]]: + for episode_str in meta[methods["episodes"]]: logger.info("") match = re.search("[Ss]\\d+[Ee]\\d+", episode_str) if match: output = match.group(0)[1:].split("E" if "E" in match.group(0) else "e") episode_id = int(output[0]) season_id = int(output[1]) - logger.info(f"Updating episode S{episode_id}E{season_id} of {m}...") + logger.info(f"Updating episode S{episode_id}E{season_id} of {mapping_name}...") try: episode = item.episode(season=season_id, episode=episode_id) except NotFound: logger.error(f"Metadata Error: episode {episode_id} of season {season_id} not found") else: - episode_dict = self.metadata[m][methods["episodes"]][episode_str] + episode_dict = meta[methods["episodes"]][episode_str] episode_methods = {em.lower(): em for em in episode_dict} if "title" in episode_methods and episode_dict[episode_methods["title"]]: