diff --git a/helpers/radarr.py b/helpers/radarr.py index f19b230..afd88ae 100644 --- a/helpers/radarr.py +++ b/helpers/radarr.py @@ -3,8 +3,26 @@ from misc.log import logger log = logger.get_logger(__name__) +def filter_trakt_movies_list(trakt_movies, callback): + new_movies_list = [] + try: + for tmp in trakt_movies: + if 'movie' not in tmp or 'ids' not in tmp['movie'] or 'tmdb' not in tmp['movie']['ids']: + log.debug("Removing movie from Trakt list as it did not have the required fields: %s", tmp) + if callback: + callback('movie', tmp) + continue + new_movies_list.append(tmp) + + return new_movies_list + except Exception: + log.exception("Exception filtering Trakt movies list: ") + return None + + def movies_to_tmdb_dict(radarr_movies): movies = {} + try: for tmp in radarr_movies: if 'tmdbId' not in tmp: @@ -20,10 +38,6 @@ def movies_to_tmdb_dict(radarr_movies): def remove_existing_movies(radarr_movies, trakt_movies, callback=None): new_movies_list = [] - if not radarr_movies or not trakt_movies: - log.error("Inappropriate parameters were supplied") - return None - try: # turn radarr movies result into a dict with tmdb id as keys processed_movies = movies_to_tmdb_dict(radarr_movies) @@ -32,24 +46,94 @@ def remove_existing_movies(radarr_movies, trakt_movies, callback=None): # loop list adding to movies that do not already exist for tmp in trakt_movies: - if 'movie' not in tmp or 'ids' not in tmp['movie'] or 'tmdb' not in tmp['movie']['ids']: - log.debug("Skipping movie because it did not have required fields: %s", tmp) + # check if movie exists in processed_movies + if tmp['movie']['ids']['tmdb'] in processed_movies: + movie_year = str(tmp['movie']['year']) if tmp['movie']['year'] else '????' + log.debug("Removing existing movie: \'%s (%s)\'", tmp['movie']['title'], movie_year) if callback: callback('movie', tmp) continue + new_movies_list.append(tmp) + + movies_removed = len(trakt_movies) - len(new_movies_list) + log.debug("Filtered %d movies from Trakt list that were already in Radarr.", movies_removed) + + return new_movies_list, movies_removed + except Exception: + log.exception("Exception removing existing movies from Trakt list: ") + return None + + +def exclusions_to_tmdb_dict(radarr_exclusions): + movie_exclusions = {} + + try: + for tmp in radarr_exclusions: + if 'tmdbId' not in tmp: + log.debug("Could not handle movie: %s", tmp['movieTitle']) + continue + movie_exclusions[tmp['tmdbId']] = tmp + return movie_exclusions + except Exception: + log.exception("Exception processing Radarr movie exclusions to TMDB dict: ") + return None + + +def remove_existing_exclusions(radarr_exclusions, trakt_movies, callback=None): + new_movies_list = [] + + try: + # turn radarr movie exclusions result into a dict with tmdb id as keys + processed_movies = exclusions_to_tmdb_dict(radarr_exclusions) + if not processed_movies: + return None + + # loop list adding to movies that do not already exist + for tmp in trakt_movies: # check if movie exists in processed_movies if tmp['movie']['ids']['tmdb'] in processed_movies: movie_year = str(tmp['movie']['year']) if tmp['movie']['year'] else '????' - log.debug("Removing existing movie: \'%s (%s)\'", tmp['movie']['title'], movie_year) + log.debug("Removing excluded movie: \'%s (%s)\'", tmp['movie']['title'], movie_year) if callback: callback('movie', tmp) continue - new_movies_list.append(tmp) - log.debug("Filtered %d Trakt movies to %d movies that weren't already in Radarr", len(trakt_movies), - len(new_movies_list)) - return new_movies_list + movies_removed = len(trakt_movies) - len(new_movies_list) + log.debug("Filtered %d movies from Trakt list that were excluded in Radarr.", movies_removed) + + return new_movies_list, movies_removed except Exception: - log.exception("Exception removing existing movies from Trakt list: ") + log.exception("Exception removing excluded movies from Trakt list: ") + return None + + +def remove_existing_and_excluded_movies(radarr_movies, radarr_exclusions, trakt_movies, callback=None): + if not radarr_movies or not radarr_exclusions or not trakt_movies: + log.error("Inappropriate parameters were supplied.") + return None + + try: + # clean up trakt_movies list + trakt_movies = filter_trakt_movies_list(trakt_movies, callback) + if not trakt_movies: + return None + + # filter out existing movies in radarr from new trakt list + preprocessed_movies_list, movies_removed_1 = remove_existing_movies(radarr_movies, trakt_movies, callback) + if not preprocessed_movies_list: + return None + + # filter out radarr exclusions from the list above + processed_movies_list, movies_removed_2 = remove_existing_exclusions(radarr_exclusions, + preprocessed_movies_list, + callback) + if not processed_movies_list: + return None + + movies_removed_total = movies_removed_1 + movies_removed_2 + log.debug("Filtered a total of %d movies from the Trakt movies list.", movies_removed_total) + return processed_movies_list + except Exception: + log.exception("Exception removing existing and excluded movies from Trakt list: ") return None diff --git a/helpers/sonarr.py b/helpers/sonarr.py index 155eaeb..19568e7 100644 --- a/helpers/sonarr.py +++ b/helpers/sonarr.py @@ -34,6 +34,23 @@ def readable_tag_from_ids(profile_tag_ids, chosen_tag_ids): return None +def filter_trakt_series_list(trakt_series, callback): + new_series_list = [] + try: + for tmp in trakt_series: + if 'show' not in tmp or 'ids' not in tmp['show'] or 'tvdb' not in tmp['show']['ids']: + log.debug("Removing shows from Trakt list as it did not have the required fields: %s", tmp) + if callback: + callback('movie', tmp) + continue + new_series_list.append(tmp) + + return new_series_list + except Exception: + log.exception("Exception filtering Trakt shows list: ") + return None + + def series_to_tvdb_dict(sonarr_series): series = {} try: @@ -52,10 +69,15 @@ def remove_existing_series(sonarr_series, trakt_series, callback=None): new_series_list = [] if not sonarr_series or not trakt_series: - log.error("Inappropriate parameters were supplied") + log.error("Inappropriate parameters were supplied.") return None try: + # clean up trakt_series list + trakt_series = filter_trakt_series_list(trakt_series, callback) + if not trakt_series: + return None + # turn sonarr series result into a dict with tvdb id as keys processed_series = series_to_tvdb_dict(sonarr_series) if not processed_series: @@ -63,11 +85,6 @@ def remove_existing_series(sonarr_series, trakt_series, callback=None): # loop list adding to series that do not already exist for tmp in trakt_series: - if 'show' not in tmp or 'ids' not in tmp['show'] or 'tvdb' not in tmp['show']['ids']: - log.debug("Skipping show because it did not have required fields: %s", tmp) - if callback: - callback('show', tmp) - continue # check if show exists in processed_series if tmp['show']['ids']['tvdb'] in processed_series: show_year = str(tmp['show']['year']) if tmp['show']['year'] else '????' @@ -78,8 +95,8 @@ def remove_existing_series(sonarr_series, trakt_series, callback=None): new_series_list.append(tmp) - log.debug("Filtered %d Trakt shows to %d shows that weren't already in Sonarr", len(trakt_series), - len(new_series_list)) + series_removed = len(trakt_series) - len(new_series_list) + log.debug("Filtered %d shows from Trakt list that were already in Sonarr.", series_removed) return new_series_list except Exception: log.exception("Exception removing existing shows from Trakt list: ") diff --git a/media/radarr.py b/media/radarr.py index 7b544d5..ffc62b4 100644 --- a/media/radarr.py +++ b/media/radarr.py @@ -11,6 +11,9 @@ class Radarr(PVR): def get_objects(self): return self._get_objects('api/movie') + def get_exclusions(self): + return self._get_objects('api/exclusions') + @backoff.on_predicate(backoff.expo, lambda x: x is None, max_tries=4, on_backoff=backoff_handler) def add_movie(self, movie_tmdb_id, movie_title, movie_year, movie_title_slug, quality_profile_id, root_folder, min_availability_temp, search_missing=False): diff --git a/traktarr.py b/traktarr.py index a81ce0f..e1f24a6 100755 --- a/traktarr.py +++ b/traktarr.py @@ -139,12 +139,25 @@ def get_profile_tags(pvr): def get_objects(pvr, pvr_type, notifications): objects_list = pvr.get_objects() + objects_type = 'movies' if pvr_type.lower() == 'radarr' else 'shows' if not objects_list: - log.error("Aborting due to failure to retrieve shows list from %s", pvr_type) + log.error("Aborting due to failure to retrieve %s list from %s", objects_type, pvr_type) if notifications: - callback_notify({'event': 'error', 'reason': 'Failure to retrieve shows list from %s' % pvr_type}) + callback_notify({'event': 'error', 'reason': 'Failure to retrieve %s list from %s' % (objects_type, pvr_type)}) + exit() + log.info("Retrieved %s %s list, %s found: %d", pvr_type, objects_type, objects_type, len(objects_list)) + return objects_list + + +def get_exclusions(pvr, pvr_type, notifications): + objects_list = pvr.get_exclusions() + objects_type = 'movie' if pvr_type.lower() == 'radarr' else 'show' + if not objects_list: + log.error("Aborting due to failure to retrieve %s exclusion list from %s", objects_type, pvr_type) + if notifications: + callback_notify({'event': 'error', 'reason': 'Failure to retrieve %s exclusions list from %s' % + (objects_type, pvr_type)}) exit() - objects_type = 'movies' if pvr_type.lower() == 'radarr' else 'shows' log.info("Retrieved %s %s list, %s found: %d", pvr_type, objects_type, objects_type, len(objects_list)) return objects_list @@ -746,6 +759,7 @@ def movies(list_type, add_limit=0, add_delay=2.5, sort='votes', rotten_tomatoes= quality_profile_id = get_quality_profile_id(radarr, cfg.radarr.quality) pvr_objects_list = get_objects(radarr, 'Radarr', notifications) + pvr_exclusions_list = get_exclusions(radarr, 'Radarr', notifications) # get trakt movies list if list_type.lower() == 'anticipated': @@ -805,9 +819,12 @@ def movies(list_type, add_limit=0, add_delay=2.5, sort='votes', rotten_tomatoes= remove_rejected_from_recommended = False # build filtered movie list without movies that exist in radarr - processed_movies_list = radarr_helper.remove_existing_movies(pvr_objects_list, trakt_objects_list, - callback_remove_recommended - if remove_rejected_from_recommended else None) + processed_movies_list = radarr_helper.remove_existing_and_excluded_movies(pvr_objects_list, + pvr_exclusions_list, + trakt_objects_list, + callback_remove_recommended + if remove_rejected_from_recommended else + None) if processed_movies_list is None: log.error("Aborting due to failure to remove existing Radarr movies from retrieved Trakt movies list") if notifications: