def trakt_authentication(): from media.trakt import Trakt trakt = Trakt(cfg) if trakt.oauth_authentication(): log.info("Authentication information saved; please restart the application") exit()
def movie(movie_id, folder=None, no_search=False): from media.radarr import Radarr from media.trakt import Trakt # replace radarr root_folder if folder is supplied if folder: cfg['radarr']['root_folder'] = folder # validate trakt api_key trakt = Trakt(cfg) radarr = Radarr(cfg.radarr.url, cfg.radarr.api_key) validate_trakt(trakt, False) validate_pvr(radarr, 'Radarr', False) profile_id = get_profile_id(radarr, cfg.radarr.profile) # get trakt movie trakt_movie = trakt.get_movie(movie_id) if not trakt_movie: log.error("Aborting due to failure to retrieve Trakt movie") return None else: log.info("Retrieved Trakt movie information for %s: %s (%d)", movie_id, trakt_movie['title'], trakt_movie['year']) # add movie to radarr if radarr.add_movie(trakt_movie['ids']['tmdb'], trakt_movie['title'], trakt_movie['year'], trakt_movie['ids']['slug'], profile_id, cfg.radarr.root_folder, not no_search): log.info("ADDED %s (%d)", trakt_movie['title'], trakt_movie['year']) else: log.error("FAILED adding %s (%d)", trakt_movie['title'], trakt_movie['year']) return
def callback_remove_recommended(media_type, media_info): from media.trakt import Trakt trakt = Trakt(cfg) if not media_info[media_type]['title'] or not media_info[media_type]['year']: log.debug("Skipping removing %s item from recommended list as no title/year was available:\n%s", media_type, media_info) return media_name = '%s (%d)' % (media_info[media_type]['title'], media_info[media_type]['year']) if trakt.remove_recommended_item(media_type, media_info[media_type]['ids']['trakt']): log.info("Removed rejected recommended %s: %s", media_type, media_name) else: log.info("FAILED removing rejected recommended %s: %s", media_type, media_name)
def show(show_id, folder=None, no_search=False): from media.sonarr import Sonarr from media.trakt import Trakt from helpers import sonarr as sonarr_helper # replace sonarr root_folder if folder is supplied if folder: cfg['sonarr']['root_folder'] = folder trakt = Trakt(cfg) sonarr = Sonarr(cfg.sonarr.url, cfg.sonarr.api_key) validate_trakt(trakt, False) validate_pvr(sonarr, 'Sonarr', False) profile_id = get_profile_id(sonarr, cfg.sonarr.profile) profile_tags = get_profile_tags(sonarr) # get trakt show trakt_show = trakt.get_show(show_id) if not trakt_show: log.error("Aborting due to failure to retrieve Trakt show") return None else: log.info("Retrieved Trakt show information for %s: %s (%d)", show_id, trakt_show['title'], trakt_show['year']) # determine which tags to use when adding this series use_tags = sonarr_helper.series_tag_id_from_network( profile_tags, cfg.sonarr.tags, trakt_show['network']) # add show to sonarr if sonarr.add_series(trakt_show['ids']['tvdb'], trakt_show['title'], trakt_show['ids']['slug'], profile_id, cfg.sonarr.root_folder, use_tags, not no_search): log.info("ADDED %s (%d) with tags: %s", trakt_show['title'], trakt_show['year'], sonarr_helper.readable_tag_from_ids(profile_tags, use_tags)) else: log.error("FAILED adding %s (%d) with tags: %s", trakt_show['title'], trakt_show['year'], sonarr_helper.readable_tag_from_ids(profile_tags, use_tags)) return
def movies(list_type, add_limit=0, add_delay=2.5, sort='votes', rating=None, genre=None, folder=None, actor=None, no_search=False, notifications=False, authenticate_user=None, ignore_blacklist=False, remove_rejected_from_recommended=False): from media.radarr import Radarr from media.trakt import Trakt from helpers import misc as misc_helper from helpers import radarr as radarr_helper from helpers import trakt as trakt_helper from helpers import rating as rating_helper added_movies = 0 # remove genre from movies blacklisted_genres if supplied if genre: misc_helper.unblacklist_genres(genre, cfg['filters']['movies']['blacklisted_genres']) # replace radarr root_folder if folder is supplied if folder: cfg['radarr']['root_folder'] = folder # validate trakt api_key trakt = Trakt(cfg) radarr = Radarr(cfg.radarr.url, cfg.radarr.api_key) validate_trakt(trakt, notifications) validate_pvr(radarr, 'Radarr', notifications) profile_id = get_profile_id(radarr, cfg.radarr.profile) pvr_objects_list = get_objects(radarr, 'Radarr', notifications) # get trakt movies list if list_type.lower() == 'anticipated': trakt_objects_list = trakt.get_anticipated_movies(genres=genre, languages=cfg.filters.movies.allowed_languages) elif list_type.lower() == 'trending': trakt_objects_list = trakt.get_trending_movies(genres=genre, languages=cfg.filters.movies.allowed_languages) elif list_type.lower() == 'popular': trakt_objects_list = trakt.get_popular_movies(genres=genre, languages=cfg.filters.movies.allowed_languages) elif list_type.lower() == 'boxoffice': trakt_objects_list = trakt.get_boxoffice_movies() elif list_type.lower() == 'person': if not actor: log.error("You must specify an actor with the --actor / -a parameter when using the person list type!") return None trakt_objects_list = trakt.get_person_movies(person=actor, genres=genre, languages=cfg.filters.movies.allowed_languages) elif list_type.lower() == 'recommended': trakt_objects_list = trakt.get_recommended_movies(authenticate_user, genres=genre, languages=cfg.filters.movies.allowed_languages) elif list_type.lower().startswith('played'): most_type = misc_helper.substring_after(list_type.lower(), "_") trakt_objects_list = trakt.get_most_played_movies(genres=genre, languages=cfg.filters.movies.allowed_languages, most_type=most_type if most_type else None) elif list_type.lower().startswith('watched'): most_type = misc_helper.substring_after(list_type.lower(), "_") trakt_objects_list = trakt.get_most_watched_movies(genres=genre, languages=cfg.filters.movies.allowed_languages, most_type=most_type if most_type else None) elif list_type.lower() == 'watchlist': trakt_objects_list = trakt.get_watchlist_movies(authenticate_user) else: trakt_objects_list = trakt.get_user_list_movies(list_type, authenticate_user) if not trakt_objects_list: log.error("Aborting due to failure to retrieve Trakt %s movies list", list_type) if notifications: callback_notify( {'event': 'abort', 'type': 'movies', 'list_type': list_type, 'reason': 'Failure to retrieve Trakt %s movies list' % list_type}) return None else: log.info("Retrieved Trakt %s movies list, movies found: %d", list_type, len(trakt_objects_list)) # set remove_rejected_recommended to False if this is not the recommended list if list_type.lower() != 'recommended': 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) if processed_movies_list is None: log.error("Aborting due to failure to remove existing Radarr movies from retrieved Trakt movies list") if notifications: callback_notify({'event': 'abort', 'type': 'movies', 'list_type': list_type, 'reason': 'Failure to remove existing Radarr movies from retrieved ' 'Trakt %s movies list' % list_type}) return None else: log.info("Removed existing Radarr movies from Trakt movies list, movies left to process: %d", len(processed_movies_list)) # sort filtered movie list if sort == 'release': sorted_movies_list = misc_helper.sorted_list(processed_movies_list, 'movie', 'released') log.info("Sorted movies list to process by release date") elif sort == 'rating': sorted_movies_list = misc_helper.sorted_list(processed_movies_list, 'movie', 'rating') log.info("Sorted movies list to process by highest rating") else: sorted_movies_list = misc_helper.sorted_list(processed_movies_list, 'movie', 'votes') log.info("Sorted movies list to process by highest votes") # loop movies log.info("Processing list now...") for movie in sorted_movies_list: try: # check if genre matches genre supplied via argument if genre and not misc_helper.allowed_genres(genre, 'movie', movie): log.debug("Skipping: %s because it was not from %s genre(s)", movie['movie']['title'], genre.lower()) continue # check if movie passes out blacklist criteria inspection if not trakt_helper.is_movie_blacklisted(movie, cfg.filters.movies, ignore_blacklist, callback_remove_recommended if remove_rejected_from_recommended else None): # Assuming the movie is not blacklisted, proceed to pull RT score if the user wishes to restrict movieRating = None if rating is not None and 'omdb' in cfg and 'api_key' in cfg['omdb'] and cfg['omdb']['api_key']: movieRating = rating_helper.get_rating(cfg['omdb']['api_key'], movie) if movieRating == -1: log.debug("Skipping: %s because it did not have a rating/lacked imdbID", movie['movie']['title']) continue if (rating is None or movieRating is None) or movieRating >= rating: log.info("Adding: %s (%d) | Genres: %s | Country: %s", movie['movie']['title'], movie['movie']['year'], ', '.join(movie['movie']['genres']), movie['movie']['country'].upper()) # add movie to radarr if radarr.add_movie(movie['movie']['ids']['tmdb'], movie['movie']['title'], movie['movie']['year'], movie['movie']['ids']['slug'], profile_id, cfg.radarr.root_folder, not no_search): log.info("ADDED %s (%d)", movie['movie']['title'], movie['movie']['year']) if notifications: callback_notify({'event': 'add_movie', 'list_type': list_type, 'movie': movie['movie']}) added_movies += 1 else: log.error("FAILED adding %s (%d)", movie['movie']['title'], movie['movie']['year']) else: log.info("SKIPPING: %s (%d) | Genres: %s | Country: %s", movie['movie']['title'], movie['movie']['year'], ', '.join(movie['movie']['genres']), movie['movie']['country'].upper()) # stop adding movies, if added_movies >= add_limit if add_limit and added_movies >= add_limit: break # sleep before adding any more time.sleep(add_delay) except Exception: log.exception("Exception while processing movie %s: ", movie['movie']['title']) log.info("Added %d new movie(s) to Radarr", added_movies) # send notification if notifications and (cfg.notifications.verbose or added_movies > 0): notify.send(message="Added %d movies from Trakt's %s list" % (added_movies, list_type)) return added_movies
def shows(list_type, add_limit=0, add_delay=2.5, sort='votes', genre=None, folder=None, actor=None, no_search=False, notifications=False, authenticate_user=None, ignore_blacklist=False, remove_rejected_from_recommended=False): from media.sonarr import Sonarr from media.trakt import Trakt from helpers import misc as misc_helper from helpers import sonarr as sonarr_helper from helpers import trakt as trakt_helper added_shows = 0 # remove genre from shows blacklisted_genres if supplied if genre: misc_helper.unblacklist_genres(genre, cfg['filters']['shows']['blacklisted_genres']) # replace sonarr root_folder if folder is supplied if folder: cfg['sonarr']['root_folder'] = folder # validate trakt client_id trakt = Trakt(cfg) sonarr = Sonarr(cfg.sonarr.url, cfg.sonarr.api_key) validate_trakt(trakt, notifications) validate_pvr(sonarr, 'Sonarr', notifications) profile_id = get_profile_id(sonarr, cfg.sonarr.profile) profile_tags = get_profile_tags(sonarr) pvr_objects_list = get_objects(sonarr, 'Sonarr', notifications) # get trakt series list if list_type.lower() == 'anticipated': trakt_objects_list = trakt.get_anticipated_shows(genres=genre, languages=cfg.filters.shows.allowed_languages) elif list_type.lower() == 'trending': trakt_objects_list = trakt.get_trending_shows(genres=genre, languages=cfg.filters.shows.allowed_languages) elif list_type.lower() == 'popular': trakt_objects_list = trakt.get_popular_shows(genres=genre, languages=cfg.filters.shows.allowed_languages) elif list_type.lower() == 'person': if not actor: log.error("You must specify an actor with the --actor / -a parameter when using the person list type!") return None trakt_objects_list = trakt.get_person_shows(person=actor, genres=genre, languages=cfg.filters.shows.allowed_languages) elif list_type.lower() == 'recommended': trakt_objects_list = trakt.get_recommended_shows(authenticate_user, genres=genre, languages=cfg.filters.shows.allowed_languages) elif list_type.lower().startswith('played'): most_type = misc_helper.substring_after(list_type.lower(), "_") trakt_objects_list = trakt.get_most_played_shows(genres=genre, languages=cfg.filters.shows.allowed_languages, most_type=most_type if most_type else None) elif list_type.lower().startswith('watched'): most_type = misc_helper.substring_after(list_type.lower(), "_") trakt_objects_list = trakt.get_most_watched_shows(genres=genre, languages=cfg.filters.shows.allowed_languages, most_type=most_type if most_type else None) elif list_type.lower() == 'watchlist': trakt_objects_list = trakt.get_watchlist_shows(authenticate_user) else: trakt_objects_list = trakt.get_user_list_shows(list_type, authenticate_user) if not trakt_objects_list: log.error("Aborting due to failure to retrieve Trakt %s shows list", list_type) if notifications: callback_notify( {'event': 'abort', 'type': 'shows', 'list_type': list_type, 'reason': 'Failure to retrieve Trakt %s shows list' % list_type}) return None else: log.info("Retrieved Trakt %s shows list, shows found: %d", list_type, len(trakt_objects_list)) # set remove_rejected_recommended to False if this is not the recommended list if list_type.lower() != 'recommended': remove_rejected_from_recommended = False # build filtered series list without series that exist in sonarr processed_series_list = sonarr_helper.remove_existing_series(pvr_objects_list, trakt_objects_list, callback_remove_recommended if remove_rejected_from_recommended else None) if processed_series_list is None: log.error("Aborting due to failure to remove existing Sonarr shows from retrieved Trakt shows list") if notifications: callback_notify({'event': 'abort', 'type': 'shows', 'list_type': list_type, 'reason': 'Failure to remove existing Sonarr shows from retrieved Trakt %s shows list' % list_type}) return None else: log.info("Removed existing Sonarr shows from Trakt shows list, shows left to process: %d", len(processed_series_list)) # sort filtered series list if sort == 'release': sorted_series_list = misc_helper.sorted_list(processed_series_list, 'show', 'first_aired') log.info("Sorted shows list to process by release date") elif sort == 'rating': sorted_series_list = misc_helper.sorted_list(processed_series_list, 'show', 'rating') log.info("Sorted shows list to process by highest rating") else: sorted_series_list = misc_helper.sorted_list(processed_series_list, 'show', 'votes') log.info("Sorted shows list to process by highest votes") # loop series_list log.info("Processing list now...") for series in sorted_series_list: try: # check if genre matches genre supplied via argument if genre and not misc_helper.allowed_genres(genre, 'show', series): log.debug("Skipping: %s because it was not from %s genre(s)", series['show']['title'], genre.lower()) continue # check if series passes out blacklist criteria inspection if not trakt_helper.is_show_blacklisted(series, cfg.filters.shows, ignore_blacklist, callback_remove_recommended if remove_rejected_from_recommended else None): log.info("Adding: %s | Genres: %s | Network: %s | Country: %s", series['show']['title'], ', '.join(series['show']['genres']), series['show']['network'], series['show']['country'].upper()) # determine which tags to use when adding this series use_tags = sonarr_helper.series_tag_id_from_network(profile_tags, cfg.sonarr.tags, series['show']['network']) # add show to sonarr if sonarr.add_series(series['show']['ids']['tvdb'], series['show']['title'], series['show']['ids']['slug'], profile_id, cfg.sonarr.root_folder, use_tags, not no_search): log.info("ADDED %s (%d) with tags: %s", series['show']['title'], series['show']['year'], sonarr_helper.readable_tag_from_ids(profile_tags, use_tags)) if notifications: callback_notify({'event': 'add_show', 'list_type': list_type, 'show': series['show']}) added_shows += 1 else: log.error("FAILED adding %s (%d) with tags: %s", series['show']['title'], series['show']['year'], sonarr_helper.readable_tag_from_ids(profile_tags, use_tags)) # stop adding shows, if added_shows >= add_limit if add_limit and added_shows >= add_limit: break # sleep before adding any more time.sleep(add_delay) except Exception: log.exception("Exception while processing show %s: ", series['show']['title']) log.info("Added %d new show(s) to Sonarr", added_shows) # send notification if notifications and (cfg.notifications.verbose or added_shows > 0): notify.send(message="Added %d shows from Trakt's %s list" % (added_shows, list_type)) return added_shows
def shows(list_type, add_limit=0, add_delay=2.5, genre=None, no_search=False, notifications=False): added_shows = 0 # validate trakt api_key trakt = Trakt(cfg.trakt.api_key) if not trakt.validate_api_key(): log.error("Aborting due to failure to validate Trakt API Key") if notifications: callback_notify({ 'event': 'abort', 'type': 'shows', 'list_type': list_type, 'reason': 'Failure to validate Trakt API Key' }) return None else: log.info("Validated Trakt API Key") # validate sonarr url & api_key sonarr = Sonarr(cfg.sonarr.url, cfg.sonarr.api_key) if not sonarr.validate_api_key(): log.error("Aborting due to failure to validate Sonarr URL / API Key") if notifications: callback_notify({ 'event': 'abort', 'type': 'shows', 'list_type': list_type, 'reason': 'Failure to validate Sonarr URL / API Key' }) return None else: log.info("Validated Sonarr URL & API Key") # retrieve profile id for requested profile profile_id = sonarr.get_profile_id(cfg.sonarr.profile) if not profile_id or not profile_id > 0: log.error("Aborting due to failure to retrieve Profile ID for: %s", cfg.sonarr.profile) if notifications: callback_notify({ 'event': 'abort', 'type': 'shows', 'list_type': list_type, 'reason': 'Failure to retrieve Sonarr Profile ID of %s' % cfg.sonarr.profile }) return None else: log.info("Retrieved Profile ID for %s: %d", cfg.sonarr.profile, profile_id) # retrieve profile tags profile_tags = sonarr.get_tags() if profile_tags is None: log.error("Aborting due to failure to retrieve Tag ID's") if notifications: callback_notify({ 'event': 'abort', 'type': 'shows', 'list_type': list_type, 'reason': "Failure to retrieve Sonarr Tag ID's" }) return None else: log.info("Retrieved %d Tag ID's", len(profile_tags)) # get sonarr series list sonarr_series_list = sonarr.get_series() if not sonarr_series_list: log.error("Aborting due to failure to retrieve Sonarr shows list") if notifications: callback_notify({ 'event': 'abort', 'type': 'shows', 'list_type': list_type, 'reason': 'Failure to retrieve Sonarr shows list' }) return None else: log.info("Retrieved Sonarr shows list, shows found: %d", len(sonarr_series_list)) # get trakt series list trakt_series_list = None if list_type.lower() == 'anticipated': trakt_series_list = trakt.get_anticipated_shows() elif list_type.lower() == 'trending': trakt_series_list = trakt.get_trending_shows() elif list_type.lower() == 'popular': trakt_series_list = trakt.get_popular_shows() else: log.error("Aborting due to unknown Trakt list type") if notifications: callback_notify({ 'event': 'abort', 'type': 'shows', 'list_type': list_type, 'reason': 'Failure to determine Trakt list type' }) return None if not trakt_series_list: log.error("Aborting due to failure to retrieve Trakt %s shows list", list_type) if notifications: callback_notify({ 'event': 'abort', 'type': 'shows', 'list_type': list_type, 'reason': 'Failure to retrieve Trakt %s shows list' % list_type }) return None else: log.info("Retrieved Trakt %s shows list, shows found: %d", list_type, len(trakt_series_list)) # build filtered series list without series that exist in sonarr processed_series_list = helpers.sonarr_remove_existing_series( sonarr_series_list, trakt_series_list) if processed_series_list is None: log.error( "Aborting due to failure to remove existing Sonarr shows from retrieved Trakt shows list" ) if notifications: callback_notify({ 'event': 'abort', 'type': 'shows', 'list_type': list_type, 'reason': 'Failure to remove existing Sonarr shows from retrieved Trakt %s shows list' % list_type }) return None else: log.info( "Removed existing Sonarr shows from Trakt shows list, shows left to process: %d", len(processed_series_list)) # sort filtered series list by highest votes sorted_series_list = sorted(processed_series_list, key=lambda k: k['show']['votes'], reverse=True) log.info("Sorted shows list to process by highest votes") # loop series_list log.info("Processing list now...") for series in sorted_series_list: try: # check if genre matches genre supplied via argument if genre and genre.lower() not in series['show']['genres']: log.debug("Skipping: %s because it was not from %s genre", series['show']['title'], genre.lower()) continue # check if series passes out blacklist criteria inspection if not helpers.trakt_is_show_blacklisted(series, cfg.filters.shows): log.info("Adding: %s | Genres: %s | Network: %s | Country: %s", series['show']['title'], ', '.join(series['show']['genres']), series['show']['network'], series['show']['country'].upper()) # determine which tags to use when adding this series use_tags = helpers.sonarr_series_tag_id_from_network( profile_tags, cfg.sonarr.tags, series['show']['network']) # add show to sonarr if sonarr.add_series(series['show']['ids']['tvdb'], series['show']['title'], series['show']['ids']['slug'], profile_id, cfg.sonarr.root_folder, use_tags, not no_search): log.info( "ADDED %s (%d) with tags: %s", series['show']['title'], series['show']['year'], helpers.sonarr_readable_tag_from_ids( profile_tags, use_tags)) if notifications: callback_notify({ 'event': 'add_show', 'list_type': list_type, 'show': series['show'] }) added_shows += 1 else: log.error( "FAILED adding %s (%d) with tags: %s", series['show']['title'], series['show']['year'], helpers.sonarr_readable_tag_from_ids( profile_tags, use_tags)) # stop adding shows, if added_shows >= add_limit if add_limit and added_shows >= add_limit: break # sleep before adding any more time.sleep(add_delay) except Exception: log.exception("Exception while processing show %s: ", series['show']['title']) log.info("Added %d new show(s) to Sonarr", added_shows) # send notification if notifications: notify.send(message="Added %d shows from Trakt's %s list" % (added_shows, list_type)) return added_shows
def movies(list_type, add_limit=0, add_delay=2.5, genre=None, no_search=False, notifications=False): added_movies = 0 # validate trakt api_key trakt = Trakt(cfg.trakt.api_key) if not trakt.validate_api_key(): log.error("Aborting due to failure to validate Trakt API Key") if notifications: callback_notify({ 'event': 'abort', 'type': 'movies', 'list_type': list_type, 'reason': 'Failure to validate Trakt API Key' }) return None else: log.info("Validated Trakt API Key") # validate radarr url & api_key radarr = Radarr(cfg.radarr.url, cfg.radarr.api_key) if not radarr.validate_api_key(): log.error("Aborting due to failure to validate Radarr URL / API Key") if notifications: callback_notify({ 'event': 'abort', 'type': 'movies', 'list_type': list_type, 'reason': 'Failure to validate Radarr URL / API Key' }) return None else: log.info("Validated Radarr URL & API Key") # retrieve profile id for requested profile profile_id = radarr.get_profile_id(cfg.radarr.profile) if not profile_id or not profile_id > 0: log.error("Aborting due to failure to retrieve Profile ID for: %s", cfg.radarr.profile) if notifications: callback_notify({ 'event': 'abort', 'type': 'movies', 'list_type': list_type, 'reason': 'Failure to retrieve Radarr Profile ID of %s' % cfg.radarr.profile }) return None else: log.info("Retrieved Profile ID for %s: %d", cfg.radarr.profile, profile_id) # get radarr movies list radarr_movie_list = radarr.get_movies() if not radarr_movie_list: log.error("Aborting due to failure to retrieve Radarr movies list") if notifications: callback_notify({ 'event': 'abort', 'type': 'movies', 'list_type': list_type, 'reason': 'Failure to retrieve Radarr movies list' }) return None else: log.info("Retrieved Radarr movies list, movies found: %d", len(radarr_movie_list)) # get trakt movies list trakt_movies_list = None if list_type.lower() == 'anticipated': trakt_movies_list = trakt.get_anticipated_movies() elif list_type.lower() == 'trending': trakt_movies_list = trakt.get_trending_movies() elif list_type.lower() == 'popular': trakt_movies_list = trakt.get_popular_movies() elif list_type.lower() == 'boxoffice': trakt_movies_list = trakt.get_boxoffice_movies() else: log.error("Aborting due to unknown Trakt list type") if notifications: callback_notify({ 'event': 'abort', 'type': 'movies', 'list_type': list_type, 'reason': 'Failure to determine Trakt list type' }) return None if not trakt_movies_list: log.error("Aborting due to failure to retrieve Trakt %s movies list", list_type) if notifications: callback_notify({ 'event': 'abort', 'type': 'movies', 'list_type': list_type, 'reason': 'Failure to retrieve Trakt %s movies list' % list_type }) return None else: log.info("Retrieved Trakt %s movies list, movies found: %d", list_type, len(trakt_movies_list)) # build filtered movie list without movies that exist in radarr processed_movies_list = helpers.radarr_remove_existing_movies( radarr_movie_list, trakt_movies_list) if processed_movies_list is None: log.error( "Aborting due to failure to remove existing Radarr movies from retrieved Trakt movies list" ) if notifications: callback_notify({ 'event': 'abort', 'type': 'movies', 'list_type': list_type, 'reason': 'Failure to remove existing Radarr movies from retrieved ' 'Trakt %s movies list' % list_type }) return None else: log.info( "Removed existing Radarr movies from Trakt movies list, movies left to process: %d", len(processed_movies_list)) # sort filtered movie list by highest votes sorted_movies_list = sorted(processed_movies_list, key=lambda k: k['movie']['votes'], reverse=True) log.info("Sorted movie list to process by highest votes") # loop movies log.info("Processing list now...") for movie in sorted_movies_list: try: # check if genre matches genre supplied via argument if genre and genre.lower() not in movie['movie']['genres']: log.debug("Skipping: %s because it was not from %s genre", movie['movie']['title'], genre.lower()) continue # check if movie passes out blacklist criteria inspection if not helpers.trakt_is_movie_blacklisted(movie, cfg.filters.movies): log.info("Adding: %s (%d) | Genres: %s | Country: %s", movie['movie']['title'], movie['movie']['year'], ', '.join(movie['movie']['genres']), movie['movie']['country'].upper()) # add movie to radarr if radarr.add_movie(movie['movie']['ids']['tmdb'], movie['movie']['title'], movie['movie']['year'], movie['movie']['ids']['slug'], profile_id, cfg.radarr.root_folder, not no_search): log.info("ADDED %s (%d)", movie['movie']['title'], movie['movie']['year']) if notifications: callback_notify({ 'event': 'add_movie', 'list_type': list_type, 'movie': movie['movie'] }) added_movies += 1 else: log.error("FAILED adding %s (%d)", movie['movie']['title'], movie['movie']['year']) # stop adding movies, if added_movies >= add_limit if add_limit and added_movies >= add_limit: break # sleep before adding any more time.sleep(add_delay) except Exception: log.exception("Exception while processing movie %s: ", movie['movie']['title']) log.info("Added %d new movie(s) to Radarr", added_movies) # send notification if notifications: notify.send(message="Added %d movies from Trakt's %s list" % (added_movies, list_type)) return added_movies