diff --git a/modules/anidb.py b/modules/anidb.py index 82ee48cb..06aa4748 100644 --- a/modules/anidb.py +++ b/modules/anidb.py @@ -19,9 +19,8 @@ class AniDB: self.config = config self.username = params["username"] if params else None self.password = params["password"] if params else None - if params: - if not self._login(self.username, self.password).xpath("//li[@class='sub-menu my']/@title"): - raise Failed("AniDB Error: Login failed") + if params and not self._login(self.username, self.password).xpath("//li[@class='sub-menu my']/@title"): + raise Failed("AniDB Error: Login failed") def _request(self, url, language=None, post=None): if post: diff --git a/modules/anilist.py b/modules/anilist.py index d1bc31c9..bdefc1fc 100644 --- a/modules/anilist.py +++ b/modules/anilist.py @@ -1,7 +1,6 @@ import logging, time from modules import util from modules.util import Failed -from retrying import retry logger = logging.getLogger("Plex Meta Manager") @@ -22,7 +21,6 @@ class AniList: self.tags = {t["name"].lower(): t["name"] for t in self._request(tag_query, {})["data"]["MediaTagCollection"]} self.genres = {g.lower(): g for g in self._request(genre_query, {})["data"]["GenreCollection"]} - @retry(stop_max_attempt_number=2, retry_on_exception=util.retry_if_not_failed) def _request(self, query, variables): response = self.config.post(base_url, json={"query": query, "variables": variables}) json_obj = response.json() diff --git a/modules/convert.py b/modules/convert.py index ac0ad97d..50d6a875 100644 --- a/modules/convert.py +++ b/modules/convert.py @@ -13,20 +13,31 @@ class Convert: self.config = config self.AniDBIDs = self.config.get_html(anidb_url) - def _anidb(self, input_id, to_id, fail=False): - ids = self.AniDBIDs.xpath(f"//anime[contains(@anidbid, '{input_id}')]/@{to_id}") - if len(ids) > 0: - try: - if len(ids[0]) > 0: - return util.get_list(ids[0]) if to_id == "imdbid" else int(ids[0]) - raise ValueError - except ValueError: - fail_text = f"Convert Error: No {util.pretty_ids[to_id]} ID found for AniDB ID: {input_id}" + def _anidb(self, anidb_id, fail=False): + tvdbid = self.AniDBIDs.xpath(f"//anime[contains(@anidbid, '{anidb_id}')]/@tvdbid") + imdbid = self.AniDBIDs.xpath(f"//anime[contains(@anidbid, '{anidb_id}')]/@imdbid") + if len(tvdbid) > 0: + if len(imdbid[0]) > 0: + imdb_ids = util.get_list(imdbid[0]) + tmdb_ids = [] + for imdb in imdb_ids: + tmdb_id = self.imdb_to_tmdb(imdb) + if tmdb_id: + tmdb_ids.append(tmdb_id) + if tmdb_ids: + return None, imdb_ids, tmdb_ids + else: + fail_text = f"Convert Error: No TMDb ID found for AniDB ID: {anidb_id}" + else: + try: + return int(tvdbid[0]), [], [] + except ValueError: + fail_text = f"Convert Error: No TVDb ID or IMDb ID found for AniDB ID: {anidb_id}" else: - fail_text = f"Convert Error: AniDB ID: {input_id} not found" + fail_text = f"Convert Error: AniDB ID: {anidb_id} not found" if fail: raise Failed(fail_text) - return [] if to_id == "imdbid" else None + return None, [], [] def _arms_ids(self, anilist_ids=None, anidb_ids=None, mal_ids=None): all_ids = [] @@ -70,20 +81,14 @@ class Convert: show_ids = [] movie_ids = [] for anidb_id in anidb_list: - imdb_ids = self.anidb_to_imdb(anidb_id) - tmdb_ids = [] - if imdb_ids: - for imdb_id in imdb_ids: - tmdb_id = self.imdb_to_tmdb(imdb_id) - if tmdb_id: - tmdb_ids.append(tmdb_id) - tvdb_id = self.anidb_to_tvdb(anidb_id) - if tvdb_id: - show_ids.append(tvdb_id) - if tmdb_ids: - movie_ids.extend(tmdb_ids) - if not tvdb_id and not tmdb_ids: - logger.error(f"Convert Error: No TVDb ID or IMDb ID found for AniDB ID: {anidb_id}") + try: + tvdb_id, _, tmdb_ids = self._anidb(anidb_id, fail=True) + if tvdb_id: + show_ids.append(tvdb_id) + if tmdb_ids: + movie_ids.extend(tmdb_ids) + except Failed as e: + logger.error(e) return movie_ids, show_ids def anilist_to_ids(self, anilist_ids): @@ -104,12 +109,6 @@ class Convert: logger.error(f"Convert Error: AniDB ID not found for MyAnimeList ID: {id_set['myanimelist']}") return self.anidb_to_ids(anidb_ids) - def anidb_to_tvdb(self, anidb_id, fail=False): - return self._anidb(anidb_id, "tvdbid", fail=fail) - - def anidb_to_imdb(self, anidb_id, fail=False): - return self._anidb(anidb_id, "imdbid", fail=fail) - def tmdb_to_imdb(self, tmdb_id, is_movie=True, fail=False): media_type = "movie" if is_movie else "show" expired = False @@ -162,11 +161,11 @@ class Convert: return cache_id tvdb_id = None try: - tvdb_id = self.config.TMDb.convert_from(tmdb_id, "tvdb_id", False) + tvdb_id = int(self.config.TMDb.convert_from(tmdb_id, "tvdb_id", False)) except Failed: if self.config.Trakt: try: - tvdb_id = self.config.Trakt.convert(tmdb_id, "tmdb", "tvdb", "show") + tvdb_id = int(self.config.Trakt.convert(tmdb_id, "tmdb", "tvdb", "show")) except Failed: pass if fail and tvdb_id is None: @@ -240,24 +239,21 @@ class Convert: def get_id(self, item, library): expired = None + tmdb_id = [] + tvdb_id = [] + imdb_id = [] + anidb_id = None if self.config.Cache: cache_id, media_type, expired = self.config.Cache.query_guid_map(item.guid) if cache_id and not expired: media_id_type = "movie" if "movie" in media_type else "show" return media_id_type, util.get_list(cache_id, int_list=True) try: - tmdb_id = None - imdb_id = None - tvdb_id = None - anidb_id = None guid = requests.utils.urlparse(item.guid) item_type = guid.scheme.split(".")[-1] check_id = guid.netloc if item_type == "plex": - tmdb_id = [] - imdb_id = [] - tvdb_id = [] try: for guid_tag in library.get_guids(item): url_parsed = requests.utils.urlparse(guid_tag.id) @@ -269,12 +265,13 @@ class Convert: util.print_stacktrace() raise Failed("No External GUIDs found") if not tvdb_id and not imdb_id and not tmdb_id: + library.query(item.refresh) raise Failed("Refresh Metadata") - elif item_type == "imdb": imdb_id = check_id - elif item_type == "thetvdb": tvdb_id = int(check_id) - elif item_type == "themoviedb": tmdb_id = int(check_id) + elif item_type == "imdb": imdb_id.append(check_id) + elif item_type == "thetvdb": tvdb_id.append(int(check_id)) + elif item_type == "themoviedb": tmdb_id.append(int(check_id)) elif item_type == "hama": - if check_id.startswith("tvdb"): tvdb_id = int(re.search("-(.*)", check_id).group(1)) + if check_id.startswith("tvdb"): tvdb_id.append(int(re.search("-(.*)", check_id).group(1))) elif check_id.startswith("anidb"): anidb_id = re.search("-(.*)", check_id).group(1) else: raise Failed(f"Hama Agent ID: {check_id} not supported") elif item_type == "myanimelist": @@ -285,51 +282,28 @@ class Convert: else: raise Failed(f"Agent {item_type} not supported") if anidb_id: - tvdb_id = self.anidb_to_tvdb(anidb_id) - if not tvdb_id: - imdb_id = self.anidb_to_imdb(anidb_id) - if not imdb_id and not tvdb_id: - raise Failed(f"Unable to convert AniDB ID: {anidb_id} to TVDb ID or IMDb ID") - - if not tmdb_id and imdb_id: - if isinstance(imdb_id, list): - tmdb_id = [] + ani_tvdb, ani_imdb, ani_tmdb = self._anidb(anidb_id, fail=True) + if ani_imdb: + imdb_id.extend(ani_imdb) + if ani_tmdb: + tmdb_id.extend(ani_tmdb) + if ani_tvdb: + tvdb_id.append(ani_tvdb) + else: + if not tmdb_id and imdb_id: for imdb in imdb_id: - try: - tmdb_id.append(self.imdb_to_tmdb(imdb, fail=True)) - except Failed: - continue - else: - tmdb_id = self.imdb_to_tmdb(imdb_id) - if not tmdb_id: - raise Failed(f"Unable to convert IMDb ID: {util.compile_list(imdb_id)} to TMDb ID") - if not anidb_id and not tvdb_id and tmdb_id and library.is_show: - if isinstance(tmdb_id, list): - tvdb_id = [] + tmdb = self.imdb_to_tmdb(imdb, is_movie=library.is_movie) + if tmdb: + tmdb_id.append(tmdb) + + if not tvdb_id and tmdb_id and library.is_show: for tmdb in tmdb_id: - try: - tvdb_id.append(self.tmdb_to_tvdb(tmdb, fail=True)) - except Failed: - continue - else: - tvdb_id = self.tmdb_to_tvdb(tmdb_id) - if not tvdb_id: - raise Failed(f"Unable to convert TMDb ID: {util.compile_list(tmdb_id)} to TVDb ID") + tvdb = self.tmdb_to_tvdb(tmdb) + if tvdb: + tvdb_id.append(tvdb) + if not tvdb_id: + raise Failed(f"Unable to convert TMDb ID: {util.compile_list(tmdb_id)} to TVDb ID") - if tvdb_id: - if isinstance(tvdb_id, list): - new_tvdb_id = [] - for tvdb in tvdb_id: - try: - new_tvdb_id.append(int(tvdb)) - except ValueError: - continue - tvdb_id = new_tvdb_id - else: - try: - tvdb_id = int(tvdb_id) - except ValueError: - tvdb_id = None def update_cache(cache_ids, id_type, guid_type): if self.config.Cache: diff --git a/modules/plex.py b/modules/plex.py index 335e3fd8..09f04c4f 100644 --- a/modules/plex.py +++ b/modules/plex.py @@ -288,7 +288,8 @@ class Plex: self.split_duplicates = params["split_duplicates"] self.radarr_add_all = params["radarr_add_all"] self.sonarr_add_all = params["sonarr_add_all"] - self.mass_update = self.mass_genre_update or self.mass_audience_rating_update or self.mass_critic_rating_update or self.split_duplicates or self.radarr_add_all or self.sonarr_add_all + self.mass_update = self.mass_genre_update or self.mass_audience_rating_update or self.mass_critic_rating_update \ + or self.mass_trakt_rating_update or self.split_duplicates or self.radarr_add_all or self.sonarr_add_all self.clean_bundles = params["plex"]["clean_bundles"] self.empty_trash = params["plex"]["empty_trash"] self.optimize = params["plex"]["optimize"] @@ -677,24 +678,15 @@ class Plex: if item.ratingKey not in self.movie_rating_key_map and item.ratingKey not in self.show_rating_key_map: id_type, main_id = self.config.Convert.get_id(item, self) if main_id: - if not isinstance(main_id, list): - main_id = [main_id] if id_type == "movie": self.movie_rating_key_map[item.ratingKey] = main_id[0] - for m in main_id: - if m in self.movie_map: - self.movie_map[m].append(item.ratingKey) - else: - self.movie_map[m] = [item.ratingKey] + util.add_dict_list(main_id, item.ratingKey, self.movie_map) elif id_type == "show": self.show_rating_key_map[item.ratingKey] = main_id[0] - for m in main_id: - if m in self.show_map: - self.show_map[m].append(item.ratingKey) - else: - self.show_map[m] = [item.ratingKey] + util.add_dict_list(main_id, item.ratingKey, self.show_map) logger.info("") logger.info(util.adjust_space(f"Processed {len(items)} {'Movies' if self.is_movie else 'Shows'}")) + return items def get_tmdb_from_map(self, item): return self.movie_rating_key_map[item.ratingKey] if item.ratingKey in self.movie_rating_key_map else None diff --git a/modules/util.py b/modules/util.py index 8fab6fb3..d2347cd1 100644 --- a/modules/util.py +++ b/modules/util.py @@ -61,6 +61,13 @@ def tab_new_lines(data): def make_ordinal(n): return f"{n}{'th' if 11 <= (n % 100) <= 13 else ['th', 'st', 'nd', 'rd', 'th'][min(n % 10, 4)]}" +def add_dict_list(keys, value, dict_map): + for key in keys: + if key in dict_map: + dict_map[key].append(value) + else: + dict_map[key] = [value] + def compile_list(data): if isinstance(data, list): text = "" diff --git a/plex_meta_manager.py b/plex_meta_manager.py index d3a1694f..62fb0c3c 100644 --- a/plex_meta_manager.py +++ b/plex_meta_manager.py @@ -144,9 +144,9 @@ def update_libraries(config): logger.info("") util.separator(f"Mapping {library.name} Library", space=False, border=False) logger.info("") - library.map_guids() + items = library.map_guids() if not config.test_mode and not config.resume_from and not collection_only and library.mass_update: - mass_metadata(config, library) + mass_metadata(config, library, items) for metadata in library.metadata_files: logger.info("") util.separator(f"Running Metadata File\n{metadata.path}") @@ -245,7 +245,7 @@ def update_libraries(config): if library.optimize: library.query(library.PlexServer.library.optimize) -def mass_metadata(config, library): +def mass_metadata(config, library, items): logger.info("") util.separator(f"Mass Editing {'Movie' if library.is_movie else 'Show'} Library: {library.name}") logger.info("") @@ -258,7 +258,6 @@ def mass_metadata(config, library): sonarr_adds = [] trakt_ratings = config.Trakt.user_ratings(library.is_movie) if library.mass_trakt_rating_update else [] - items = library.get_all() for i, item in enumerate(items, 1): library.reload(item) util.print_return(f"Processing: {i}/{len(items)} {item.title}") @@ -290,7 +289,7 @@ def mass_metadata(config, library): try: tmdb_item = config.TMDb.get_movie(tmdb_id) if library.is_movie else config.TMDb.get_show(tmdb_id) except Failed as e: - logger.info(util.adjust_space(str(e))) + logger.error(util.adjust_space(str(e))) else: logger.info(util.adjust_space(f"{item.title[:25]:<25} | No TMDb ID for Guid: {item.guid}")) @@ -305,7 +304,7 @@ def mass_metadata(config, library): try: omdb_item = config.OMDb.get_omdb(imdb_id) except Failed as e: - logger.info(util.adjust_space(str(e))) + logger.error(util.adjust_space(str(e))) except Exception: logger.error(f"IMDb ID: {imdb_id}") raise diff --git a/requirements.txt b/requirements.txt index d913beed..1d9c3b89 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,6 +1,6 @@ PlexAPI==4.7.0 tmdbv3api==1.7.6 -arrapi==1.1.1 +arrapi==1.1.2 lxml requests>=2.4.2 ruamel.yaml