diff --git a/modules/builder.py b/modules/builder.py index a606b048..2163520f 100644 --- a/modules/builder.py +++ b/modules/builder.py @@ -220,11 +220,14 @@ class CollectionBuilder: methods = {m.lower(): m for m in self.data} if "template" in methods: + logger.info("") + logger.info("Validating Method: template") if not self.metadata.templates: raise Failed("Collection Error: No templates found") elif not self.data[methods["template"]]: raise Failed("Collection Error: template attribute is blank") else: + logger.debug(f"Value: {self.data[methods['template']]}") for variables in util.get_list(self.data[methods["template"]], split=False): if not isinstance(variables, dict): raise Failed("Collection Error: template attribute is not a dictionary") @@ -329,66 +332,105 @@ class CollectionBuilder: except Failed: continue - skip_collection = True - if "schedule" not in methods: - skip_collection = False - elif not self.data[methods["schedule"]]: - logger.error("Collection Error: schedule attribute is blank. Running daily") - skip_collection = False - else: - schedule_list = util.get_list(self.data[methods["schedule"]]) - next_month = current_time.replace(day=28) + timedelta(days=4) - last_day = next_month - timedelta(days=next_month.day) - for schedule in schedule_list: - run_time = str(schedule).lower() - if run_time.startswith("day") or run_time.startswith("daily"): - skip_collection = False - elif run_time.startswith("week") or run_time.startswith("month") or run_time.startswith("year"): - match = re.search("\\(([^)]+)\\)", run_time) - if match: - param = match.group(1) - if run_time.startswith("week"): - if param.lower() in util.days_alias: - weekday = util.days_alias[param.lower()] - self.schedule += f"\nScheduled weekly on {util.pretty_days[weekday]}" - if weekday == current_time.weekday(): - skip_collection = False - else: - logger.error(f"Collection Error: weekly schedule attribute {schedule} invalid must be a day of the week i.e. weekly(Monday)") - elif run_time.startswith("month"): - try: - if 1 <= int(param) <= 31: - self.schedule += f"\nScheduled monthly on the {util.make_ordinal(param)}" - if current_time.day == int(param) or (current_time.day == last_day.day and int(param) > last_day.day): + if "schedule" in methods: + logger.info("") + logger.info("Validating Method: schedule") + if not self.data[methods["schedule"]]: + raise Failed("Collection Error: schedule attribute is blank") + else: + logger.debug(f"Value: {self.data[methods['schedule']]}") + skip_collection = True + schedule_list = util.get_list(self.data[methods["schedule"]]) + next_month = current_time.replace(day=28) + timedelta(days=4) + last_day = next_month - timedelta(days=next_month.day) + for schedule in schedule_list: + run_time = str(schedule).lower() + if run_time.startswith("day") or run_time.startswith("daily"): + skip_collection = False + elif run_time.startswith("week") or run_time.startswith("month") or run_time.startswith("year"): + match = re.search("\\(([^)]+)\\)", run_time) + if match: + param = match.group(1) + if run_time.startswith("week"): + if param.lower() in util.days_alias: + weekday = util.days_alias[param.lower()] + self.schedule += f"\nScheduled weekly on {util.pretty_days[weekday]}" + if weekday == current_time.weekday(): skip_collection = False else: - logger.error(f"Collection Error: monthly schedule attribute {schedule} invalid must be between 1 and 31") - except ValueError: - logger.error(f"Collection Error: monthly schedule attribute {schedule} invalid must be an integer") - elif run_time.startswith("year"): - match = re.match("^(1[0-2]|0?[1-9])/(3[01]|[12][0-9]|0?[1-9])$", param) - if match: - month = int(match.group(1)) - day = int(match.group(2)) - self.schedule += f"\nScheduled yearly on {util.pretty_months[month]} {util.make_ordinal(day)}" - if current_time.month == month and (current_time.day == day or (current_time.day == last_day.day and day > last_day.day)): - skip_collection = False - else: - logger.error(f"Collection Error: yearly schedule attribute {schedule} invalid must be in the MM/DD format i.e. yearly(11/22)") + logger.error(f"Collection Error: weekly schedule attribute {schedule} invalid must be a day of the week i.e. weekly(Monday)") + elif run_time.startswith("month"): + try: + if 1 <= int(param) <= 31: + self.schedule += f"\nScheduled monthly on the {util.make_ordinal(param)}" + if current_time.day == int(param) or (current_time.day == last_day.day and int(param) > last_day.day): + skip_collection = False + else: + logger.error(f"Collection Error: monthly schedule attribute {schedule} invalid must be between 1 and 31") + except ValueError: + logger.error(f"Collection Error: monthly schedule attribute {schedule} invalid must be an integer") + elif run_time.startswith("year"): + match = re.match("^(1[0-2]|0?[1-9])/(3[01]|[12][0-9]|0?[1-9])$", param) + if match: + month = int(match.group(1)) + day = int(match.group(2)) + self.schedule += f"\nScheduled yearly on {util.pretty_months[month]} {util.make_ordinal(day)}" + if current_time.month == month and (current_time.day == day or (current_time.day == last_day.day and day > last_day.day)): + skip_collection = False + else: + logger.error(f"Collection Error: yearly schedule attribute {schedule} invalid must be in the MM/DD format i.e. yearly(11/22)") + else: + logger.error(f"Collection Error: failed to parse schedule: {schedule}") else: - logger.error(f"Collection Error: failed to parse schedule: {schedule}") - else: - logger.error(f"Collection Error: schedule attribute {schedule} invalid") - if len(self.schedule) == 0: - skip_collection = False - if skip_collection: - raise Failed(f"{self.schedule}\n\nCollection {self.name} not scheduled to run") + logger.error(f"Collection Error: schedule attribute {schedule} invalid") + if len(self.schedule) == 0: + skip_collection = False + if skip_collection: + raise Failed(f"{self.schedule}\n\nCollection {self.name} not scheduled to run") self.run_again = "run_again" in methods self.collectionless = "plex_collectionless" in methods + self.run_again = False + if "run_again" in methods: + logger.info("") + logger.info("Validating Method: run_again") + if not self.data[methods["run_again"]]: + logger.warning(f"Collection Warning: run_again attribute is blank defaulting to false") + else: + logger.debug(f"Value: {self.data[methods['run_again']]}") + self.run_again = util.get_bool("run_again", self.data[methods["run_again"]]) + + self.sync = self.library.sync_mode == "sync" + if "sync_mode" in methods: + logger.info("") + logger.info("Validating Method: sync_mode") + if not self.data[methods["sync_mode"]]: + logger.warning(f"Collection Warning: sync_mode attribute is blank using general: {self.library.sync_mode}") + else: + logger.debug(f"Value: {self.data[methods['sync_mode']]}") + if self.data[methods["sync_mode"]].lower() not in ["append", "sync"]: + logger.warning(f"Collection Warning: {self.data[methods['sync_mode']]} sync_mode invalid using general: {self.library.sync_mode}") + else: + self.sync = self.data[methods["sync_mode"]].lower() == "sync" + + self.build_collection = True + if "build_collection" in methods: + logger.info("") + logger.info("Validating Method: build_collection") + if not self.data[methods["build_collection"]]: + logger.warning(f"Collection Warning: build_collection attribute is blank defaulting to true") + else: + logger.debug(f"Value: {self.data[methods['build_collection']]}") + self.build_collection = util.get_bool("build_collection", self.data[methods["build_collection"]]) + if "tmdb_person" in methods: - if self.data[methods["tmdb_person"]]: + logger.info("") + logger.info("Validating Method: build_collection") + if not self.data[methods["tmdb_person"]]: + raise Failed("Collection Error: tmdb_person attribute is blank") + else: + logger.debug(f"Value: {self.data[methods['tmdb_person']]}") valid_names = [] for tmdb_id in util.get_int_list(self.data[methods["tmdb_person"]], "TMDb Person ID"): person = config.TMDb.get_person(tmdb_id) @@ -401,43 +443,48 @@ class CollectionBuilder: self.details["tmdb_person"] = valid_names else: raise Failed(f"Collection Error: No valid TMDb Person IDs in {self.data[methods['tmdb_person']]}") - else: - raise Failed("Collection Error: tmdb_person attribute is blank") self.smart_sort = "random" self.smart_label_collection = False if "smart_label" in methods: + logger.info("") + logger.info("Validating Method: smart_label") self.smart_label_collection = True - if self.data[methods["smart_label"]]: + if not self.data[methods["smart_label"]]: + logger.warning("Collection Error: smart_label attribute is blank defaulting to random") + else: + logger.debug(f"Value: {self.data[methods['smart_label']]}") if (self.library.is_movie and str(self.data[methods["smart_label"]]).lower() in plex.movie_smart_sorts) \ or (self.library.is_show and str(self.data[methods["smart_label"]]).lower() in plex.show_smart_sorts): self.smart_sort = str(self.data[methods["smart_label"]]).lower() else: - logger.info("") logger.warning(f"Collection Error: smart_label attribute: {self.data[methods['smart_label']]} is invalid defaulting to random") - else: - logger.info("") - logger.warning("Collection Error: smart_label attribute is blank defaulting to random") self.smart_url = None self.smart_type_key = None if "smart_url" in methods: - if self.data[methods["smart_url"]]: + logger.info("") + logger.info("Validating Method: smart_url") + if not self.data[methods["smart_url"]]: + raise Failed("Collection Error: smart_url attribute is blank") + else: + logger.debug(f"Value: {self.data[methods['smart_url']]}") try: self.smart_url, self.smart_type_key = library.get_smart_filter_from_uri(self.data[methods["smart_url"]]) except ValueError: raise Failed("Collection Error: smart_url is incorrectly formatted") - else: - raise Failed("Collection Error: smart_url attribute is blank") self.smart_filter_details = "" if "smart_filter" in methods: + logger.info("") + logger.info("Validating Method: smart_filter") filter_details = "\n" smart_filter = self.data[methods["smart_filter"]] if smart_filter is None: raise Failed(f"Collection Error: smart_filter attribute is blank") if not isinstance(smart_filter, dict): raise Failed(f"Collection Error: smart_filter must be a dictionary: {smart_filter}") + logger.debug(f"Value: {self.data[methods['smart_filter']]}") smart_methods = {m.lower(): m for m in smart_filter} if "any" in smart_methods and "all" in smart_methods: raise Failed(f"Collection Error: Cannot have more then one base") @@ -611,6 +658,10 @@ class CollectionBuilder: self.smart = self.smart_url or self.smart_label_collection for method_key, method_data in self.data.items(): + if method_key.lower() in ignored_details: + continue + logger.info("") + logger.info(f"Validating Method: {method_key}") if "trakt" in method_key.lower() and not config.Trakt: raise Failed(f"Collection Error: {method_key} requires Trakt todo be configured") elif "imdb" in method_key.lower() and not config.IMDb: raise Failed(f"Collection Error: {method_key} requires TMDb or Trakt to be configured") elif "radarr" in method_key.lower() and not self.library.Radarr: raise Failed(f"Collection Error: {method_key} requires Radarr to be configured") @@ -618,8 +669,6 @@ class CollectionBuilder: elif "tautulli" in method_key.lower() and not self.library.Tautulli: raise Failed(f"Collection Error: {method_key} requires Tautulli to be configured") elif "mal" in method_key.lower() and not config.MyAnimeList: raise Failed(f"Collection Error: {method_key} requires MyAnimeList to be configured") elif method_data is not None: - logger.debug("") - logger.debug(f"Validating Method: {method_key}") logger.debug(f"Value: {method_data}") if method_key.lower() in method_alias: method_name = method_alias[method_key.lower()] @@ -1226,15 +1275,6 @@ class CollectionBuilder: else: logger.warning(f"Collection Warning: {method_key} attribute is blank") - self.sync = self.library.sync_mode == "sync" - if "sync_mode" in methods: - if not self.data[methods["sync_mode"]]: - logger.warning(f"Collection Warning: sync_mode attribute is blank using general: {self.library.sync_mode}") - elif self.data[methods["sync_mode"]].lower() not in ["append", "sync"]: - logger.warning(f"Collection Warning: {self.data[methods['sync_mode']]} sync_mode invalid using general: {self.library.sync_mode}") - else: - self.sync = self.data[methods["sync_mode"]].lower() == "sync" - if self.add_to_radarr is None: self.add_to_radarr = self.library.Radarr.add if self.library.Radarr else False if self.add_to_sonarr is None: @@ -1250,13 +1290,6 @@ class CollectionBuilder: self.details["collection_mode"] = "hide" self.sync = True - self.build_collection = True - if "build_collection" in methods: - if not self.data[methods["build_collection"]]: - logger.warning(f"Collection Warning: build_collection attribute is blank defaulting to true") - else: - self.build_collection = util.get_bool("build_collection", self.data[methods["build_collection"]]) - if self.build_collection: try: self.obj = library.get_collection(self.name) diff --git a/plex_meta_manager.py b/plex_meta_manager.py index e4df9845..623b934c 100644 --- a/plex_meta_manager.py +++ b/plex_meta_manager.py @@ -159,7 +159,6 @@ def update_libraries(config, is_test, requested_collections, resume_from): if not is_test and not requested_collections and ((library.show_unmanaged and not library_only) or (library.assets_for_all and not collection_only)): logger.info("") util.separator(f"Other {library.name} Library Operations") - logger.info("") unmanaged_collections = [] for col in library.get_all_collections(): if col.title not in library.collections: