diff --git a/modules/anilist.py b/modules/anilist.py index 71205035..29e2806a 100644 --- a/modules/anilist.py +++ b/modules/anilist.py @@ -102,7 +102,7 @@ class AniList: if attr in ["start", "end"]: value = int(util.validate_date(value, f"anilist_search {key}", return_as="%Y%m%d")) elif attr in ["season", "format", "status", "genre", "tag", "tag_category"]: - value = self.options[attr.replace("_", " ").title()][value] + value = self.options[attr.replace("_", " ").title()][value.lower().replace(" / ", "-").replace(" ", "-")] if mod == "gte": value -= 1 elif mod == "lte": diff --git a/modules/builder.py b/modules/builder.py index 377ef348..4dcd4cee 100644 --- a/modules/builder.py +++ b/modules/builder.py @@ -40,7 +40,8 @@ method_alias = { "show_title": "title", "seasonyear": "year", "isadult": "adult", "startdate": "start", "enddate": "end", "averagescore": "score", "minimum_tag_percentage": "min_tag_percent", "minimumtagrank": "min_tag_percent", "minimum_tag_rank": "min_tag_percent", - "anilist_tag": "anilist_search", "anilist_genre": "anilist_search", "anilist_season": "anilist_search" + "anilist_tag": "anilist_search", "anilist_genre": "anilist_search", "anilist_season": "anilist_search", + "mal_producer": "mal_studio", "mal_licensor": "mal_studio" } filter_translation = { "actor": "actors", @@ -139,7 +140,7 @@ custom_sort_builders = [ "tautulli_popular", "tautulli_watched", "letterboxd_list", "icheckmovies_list", "anilist_top_rated", "anilist_popular", "anilist_season", "anilist_studio", "anilist_genre", "anilist_tag", "anilist_search", "mal_all", "mal_airing", "mal_upcoming", "mal_tv", "mal_movie", "mal_ova", "mal_special", - "mal_popular", "mal_favorite", "mal_suggested", "mal_userlist", "mal_season", "mal_genre", "mal_producer" + "mal_popular", "mal_favorite", "mal_suggested", "mal_userlist", "mal_season", "mal_genre", "mal_studio" ] class CollectionBuilder: @@ -763,9 +764,7 @@ class CollectionBuilder: new_dictionary = {} for search_method, search_data in dict_data.items(): search_attr, modifier, search_final = self._split(search_method) - if search_attr not in ["season", "year"] and search_data is None: - raise Failed(f"Collection Error: {method_name} {search_final} attribute is blank") - elif search_final not in anilist.searches: + if search_final not in anilist.searches: raise Failed(f"Collection Error: {method_name} {search_final} attribute not supported") elif search_attr == "season": new_dictionary[search_attr] = util.parse(search_attr, search_data, parent=method_name, default=current_season, options=util.seasons) @@ -777,6 +776,8 @@ class CollectionBuilder: if "season" not in dict_methods: logger.warning(f"Collection Warning: {method_name} season attribute not found using this season: {current_season} by default") new_dictionary["season"] = current_season + elif search_data is None: + raise Failed(f"Collection Error: {method_name} {search_final} attribute is blank") elif search_attr == "adult": new_dictionary[search_attr] = util.parse(search_attr, search_data, datatype="bool", parent=method_name) elif search_attr in ["episodes", "duration", "score", "popularity"]: @@ -829,7 +830,7 @@ class CollectionBuilder: for mal_id in util.get_int_list(method_data, "MyAnimeList ID"): self.builders.append((method_name, mal_id)) 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(method_name, method_data, datatype="int", default=10))) + self.builders.append((method_name, util.parse(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(method_name, method_data, datatype="dictlist"): if method_name == "mal_season": @@ -850,7 +851,7 @@ class CollectionBuilder: "sort_by": util.parse("sort_by", dict_data, methods=dict_methods, parent=method_name, default="score", options=mal.userlist_sort_options, translation=mal.userlist_sort_translation), "limit": util.parse("limit", dict_data, datatype="int", methods=dict_methods, default=100, parent=method_name, maximum=1000) })) - elif method_name in ["mal_genre", "mal_producer"]: + elif method_name in ["mal_genre", "mal_studio"]: id_name = f"{method_name[4:]}_id" final_data = [] for data in util.get_list(method_data): diff --git a/modules/mal.py b/modules/mal.py index 02416400..196f2135 100644 --- a/modules/mal.py +++ b/modules/mal.py @@ -7,7 +7,7 @@ logger = logging.getLogger("Plex Meta Manager") builders = [ "mal_id", "mal_all", "mal_airing", "mal_upcoming", "mal_tv", "mal_ova", "mal_movie", "mal_special", - "mal_popular", "mal_favorite", "mal_season", "mal_suggested", "mal_userlist", "mal_genre", "mal_producer" + "mal_popular", "mal_favorite", "mal_season", "mal_suggested", "mal_userlist", "mal_genre", "mal_studio" ] mal_ranked_name = { "mal_all": "all", "mal_airing": "airing", "mal_upcoming": "upcoming", "mal_tv": "tv", "mal_ova": "ova", @@ -17,7 +17,7 @@ mal_ranked_pretty = { "mal_all": "MyAnimeList All", "mal_airing": "MyAnimeList Airing", "mal_upcoming": "MyAnimeList Upcoming", "mal_tv": "MyAnimeList TV", "mal_ova": "MyAnimeList OVA", "mal_movie": "MyAnimeList Movie", "mal_special": "MyAnimeList Special", "mal_popular": "MyAnimeList Popular", - "mal_favorite": "MyAnimeList Favorite", "mal_genre": "MyAnimeList Genre", "mal_producer": "MyAnimeList Producer" + "mal_favorite": "MyAnimeList Favorite", "mal_genre": "MyAnimeList Genre", "mal_studio": "MyAnimeList Studio" } season_sort_translation = {"score": "anime_score", "anime_score": "anime_score", "members": "anime_num_list_users", "anime_num_list_users": "anime_num_list_users"} season_sort_options = ["score", "members"] @@ -191,15 +191,15 @@ class MyAnimeList: util.print_end() return mal_ids - def _producer(self, producer_id, limit): - data = self._jiken_request(f"/producer/{producer_id}") + def _studio(self, studio_id, limit): + data = self._jiken_request(f"/producer/{studio_id}") if "anime" not in data: - raise Failed(f"MyAnimeList Error: No MyAnimeList IDs for Producer ID: {producer_id}") + raise Failed(f"MyAnimeList Error: No MyAnimeList IDs for Studio ID: {studio_id}") mal_ids = [] count = 1 while True: if count > 1: - data = self._jiken_request(f"/producer/{producer_id}/{count}") + data = self._jiken_request(f"/producer/{studio_id}/{count}") if "anime" not in data: break mal_ids.extend([anime["mal_id"] for anime in data["anime"]]) @@ -218,9 +218,9 @@ class MyAnimeList: elif method == "mal_genre": logger.info(f"Processing {mal_ranked_pretty[method]} ID: {data['genre_id']}") mal_ids = self._genre(data["genre_id"], data["limit"]) - elif method == "mal_producer": - logger.info(f"Processing {mal_ranked_pretty[method]} ID: {data['producer_id']}") - mal_ids = self._producer(data["producer_id"], data["limit"]) + elif method == "mal_studio": + logger.info(f"Processing {mal_ranked_pretty[method]} ID: {data['studio_id']}") + mal_ids = self._studio(data["studio_id"], data["limit"]) elif method == "mal_season": logger.info(f"Processing MyAnimeList Season: {data['limit']} Anime from {data['season'].title()} {data['year']} sorted by {pretty_names[data['sort_by']]}") mal_ids = self._season(data["season"], data["year"], data["sort_by"], data["limit"]) diff --git a/modules/plex.py b/modules/plex.py index e7e9f113..e677cb1b 100644 --- a/modules/plex.py +++ b/modules/plex.py @@ -258,7 +258,7 @@ class Plex: self.metadatas.extend([c for c in meta_obj.metadata]) self.metadata_files.append(meta_obj) except Failed as e: - logger.error(e) + util.print_multiline(e, error=True) if len(self.metadata_files) == 0: logger.info("") @@ -455,14 +455,18 @@ class Plex: shutil.copyfile(temp_image, os.path.join(overlay_folder, f"{item.ratingKey}.png")) while util.is_locked(temp_image): time.sleep(1) - new_poster = Image.open(temp_image).convert("RGBA") - new_poster = new_poster.resize(overlay_image.size, Image.ANTIALIAS) - new_poster.paste(overlay_image, (0, 0), overlay_image) - new_poster.save(temp_image) - self.upload_file_poster(item, temp_image) - self.edit_tags("label", item, add_tags=[f"{overlay_name} Overlay"]) - poster_uploaded = True - logger.info(f"Detail: Overlay: {overlay_name} applied to {item.title}") + try: + new_poster = Image.open(temp_image).convert("RGBA") + new_poster = new_poster.resize(overlay_image.size, Image.ANTIALIAS) + new_poster.paste(overlay_image, (0, 0), overlay_image) + new_poster.save(temp_image) + self.upload_file_poster(item, temp_image) + self.edit_tags("label", item, add_tags=[f"{overlay_name} Overlay"]) + poster_uploaded = True + logger.info(f"Detail: Overlay: {overlay_name} applied to {item.title}") + except OSError as e: + util.print_stacktrace() + logger.error(f"Overlay Error: {e}") background_uploaded = False if background is not None: @@ -669,7 +673,7 @@ class Plex: try: yaml.round_trip_dump(self.missing, open(self.missing_path, "w")) except yaml.scanner.ScannerError as e: - logger.error(f"YAML Error: {util.tab_new_lines(e)}") + util.print_multiline(f"YAML Error: {util.tab_new_lines(e)}", error=True) def get_collection_items(self, collection, smart_label_collection): if smart_label_collection: diff --git a/plex_meta_manager.py b/plex_meta_manager.py index 92ca3858..4f6fe028 100644 --- a/plex_meta_manager.py +++ b/plex_meta_manager.py @@ -125,7 +125,7 @@ def start(config_path, is_test=False, time_scheduled=None, requested_collections update_libraries(config) except Exception as e: util.print_stacktrace() - logger.critical(e) + util.print_multiline(e, critical=True) logger.info("") util.separator(f"Finished {start_type}Run\nRun Time: {str(datetime.now() - start_time).split('.')[0]}") logger.removeHandler(file_handler)