added recommended list type for shows and movies, and --remove-rejected-recommended

pull/43/head
James 7 years ago committed by desimaniac
parent 80e2553891
commit 15e03c6baf

@ -17,7 +17,7 @@ def movies_to_tmdb_dict(radarr_movies):
return None return None
def remove_existing_movies(radarr_movies, trakt_movies): def remove_existing_movies(radarr_movies, trakt_movies, callback=None):
new_movies_list = [] new_movies_list = []
if not radarr_movies or not trakt_movies: if not radarr_movies or not trakt_movies:
@ -34,10 +34,14 @@ def remove_existing_movies(radarr_movies, trakt_movies):
for tmp in trakt_movies: for tmp in trakt_movies:
if 'movie' not in tmp or 'ids' not in tmp['movie'] or 'tmdb' not in tmp['movie']['ids']: 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) log.debug("Skipping movie because it did not have required fields: %s", tmp)
if callback:
callback('movie', tmp)
continue continue
# check if movie exists in processed_movies # check if movie exists in processed_movies
if tmp['movie']['ids']['tmdb'] in processed_movies: if tmp['movie']['ids']['tmdb'] in processed_movies:
log.debug("Removing existing movie: %s", tmp['movie']['title']) log.debug("Removing existing movie: %s", tmp['movie']['title'])
if callback:
callback('movie', tmp)
continue continue
new_movies_list.append(tmp) new_movies_list.append(tmp)

@ -48,7 +48,7 @@ def series_to_tvdb_dict(sonarr_series):
return None return None
def remove_existing_series(sonarr_series, trakt_series): def remove_existing_series(sonarr_series, trakt_series, callback=None):
new_series_list = [] new_series_list = []
if not sonarr_series or not trakt_series: if not sonarr_series or not trakt_series:
@ -65,10 +65,14 @@ def remove_existing_series(sonarr_series, trakt_series):
for tmp in trakt_series: for tmp in trakt_series:
if 'show' not in tmp or 'ids' not in tmp['show'] or 'tvdb' not in tmp['show']['ids']: 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) log.debug("Skipping show because it did not have required fields: %s", tmp)
if callback:
callback('show', tmp)
continue continue
# check if show exists in processed_series # check if show exists in processed_series
if tmp['show']['ids']['tvdb'] in processed_series: if tmp['show']['ids']['tvdb'] in processed_series:
log.debug("Removing existing show: %s", tmp['show']['title']) log.debug("Removing existing show: %s", tmp['show']['title'])
if callback:
callback('show', tmp)
continue continue
new_series_list.append(tmp) new_series_list.append(tmp)

@ -106,7 +106,7 @@ def blacklisted_show_id(show, blacklisted_ids):
return blacklisted return blacklisted
def is_show_blacklisted(show, blacklist_settings, ignore_blacklist): def is_show_blacklisted(show, blacklist_settings, ignore_blacklist, callback=None):
if ignore_blacklist: if ignore_blacklist:
return False return False
@ -125,6 +125,10 @@ def is_show_blacklisted(show, blacklist_settings, ignore_blacklist):
blacklisted = True blacklisted = True
if blacklisted_show_id(show, blacklist_settings.blacklisted_tvdb_ids): if blacklisted_show_id(show, blacklist_settings.blacklisted_tvdb_ids):
blacklisted = True blacklisted = True
if blacklisted and callback:
callback('show', show)
except Exception: except Exception:
log.exception("Exception determining if show was blacklisted %s: ", show) log.exception("Exception determining if show was blacklisted %s: ", show)
return blacklisted return blacklisted
@ -231,7 +235,7 @@ def blacklisted_movie_id(movie, blacklisted_ids):
return blacklisted return blacklisted
def is_movie_blacklisted(movie, blacklist_settings, ignore_blacklist): def is_movie_blacklisted(movie, blacklist_settings, ignore_blacklist, callback=None):
if ignore_blacklist: if ignore_blacklist:
return False return False
@ -250,6 +254,10 @@ def is_movie_blacklisted(movie, blacklist_settings, ignore_blacklist):
blacklisted = True blacklisted = True
if blacklisted_movie_id(movie, blacklist_settings.blacklisted_tmdb_ids): if blacklisted_movie_id(movie, blacklist_settings.blacklisted_tmdb_ids):
blacklisted = True blacklisted = True
if blacklisted and callback:
callback('movie', movie)
except Exception: except Exception:
log.exception("Exception determining if movie was blacklisted %s: ", movie) log.exception("Exception determining if movie was blacklisted %s: ", movie)
return blacklisted return blacklisted

@ -20,14 +20,17 @@ class Trakt:
# Requests # Requests
############################################################ ############################################################
def _make_request(self, url, payload={}, authenticate_user=None): def _make_request(self, url, payload={}, authenticate_user=None, request_type='get'):
headers, authenticate_user = self._headers(authenticate_user) headers, authenticate_user = self._headers(authenticate_user)
if authenticate_user: if authenticate_user:
url = url.replace('{authenticate_user}', authenticate_user) url = url.replace('{authenticate_user}', authenticate_user)
# make request # make request
req = requests.get(url, headers=headers, params=payload, timeout=30) if request_type == 'delete':
req = requests.delete(url, headers=headers, params=payload, timeout=30)
else:
req = requests.get(url, headers=headers, params=payload, timeout=30)
log.debug("Request URL: %s", req.url) log.debug("Request URL: %s", req.url)
log.debug("Request Payload: %s", payload) log.debug("Request Payload: %s", payload)
log.debug("Request User: %s", authenticate_user) log.debug("Request User: %s", authenticate_user)
@ -130,6 +133,16 @@ class Trakt:
log.exception("Exception validating client_id: ") log.exception("Exception validating client_id: ")
return False return False
def remove_recommended_item(self, item_type, trakt_id, authenticate_user=None):
ret = self._make_request(
url='https://api.trakt.tv/recommendations/%ss/%s' % (item_type, str(trakt_id)),
authenticate_user=authenticate_user,
request_type='delete'
)
if ret.status_code == 204:
return True
return False
############################################################ ############################################################
# OAuth Authentication # OAuth Authentication
############################################################ ############################################################
@ -363,6 +376,17 @@ class Trakt:
genres=genres genres=genres
) )
def get_recommended_shows(self, authenticate_user=None, limit=1000, languages=None, genres=None):
return self._make_items_request(
url='https://api.trakt.tv/recommendations/shows',
authenticate_user=authenticate_user,
limit=limit,
languages=languages,
object_name='shows',
type_name='recommended from {authenticate_user}',
genres=genres
)
def get_watchlist_shows(self, authenticate_user=None, limit=1000, languages=None): def get_watchlist_shows(self, authenticate_user=None, limit=1000, languages=None):
return self._make_items_request( return self._make_items_request(
url='https://api.trakt.tv/users/{authenticate_user}/watchlist/shows', url='https://api.trakt.tv/users/{authenticate_user}/watchlist/shows',
@ -456,6 +480,17 @@ class Trakt:
type_name='anticipated', type_name='anticipated',
) )
def get_recommended_movies(self, authenticate_user=None, limit=1000, languages=None, genres=None):
return self._make_items_request(
url='https://api.trakt.tv/recommendations/movies',
authenticate_user=authenticate_user,
limit=limit,
languages=languages,
object_name='movies',
type_name='recommended from {authenticate_user}',
genres=genres
)
def get_watchlist_movies(self, authenticate_user=None, limit=1000, languages=None): def get_watchlist_movies(self, authenticate_user=None, limit=1000, languages=None):
return self._make_items_request( return self._make_items_request(
url='https://api.trakt.tv/users/{authenticate_user}/watchlist/movies', url='https://api.trakt.tv/users/{authenticate_user}/watchlist/movies',

@ -185,8 +185,9 @@ def show(show_id, folder=None, no_search=False):
@click.option('--authenticate-user', @click.option('--authenticate-user',
help='Specify which user to authenticate with to retrieve Trakt lists. Default: first user in the config') help='Specify which user to authenticate with to retrieve Trakt lists. Default: first user in the config')
@click.option('--ignore-blacklist', is_flag=True, help='Ignores the blacklist when running the command.') @click.option('--ignore-blacklist', is_flag=True, help='Ignores the blacklist when running the command.')
@click.option('--remove-rejected-recommended', is_flag=True, help='Removes rejected/existing movies from recommended.')
def shows(list_type, add_limit=0, add_delay=2.5, sort='votes', genre=None, folder=None, no_search=False, def shows(list_type, add_limit=0, add_delay=2.5, sort='votes', genre=None, folder=None, no_search=False,
notifications=False, authenticate_user=None, ignore_blacklist=False): notifications=False, authenticate_user=None, ignore_blacklist=False, remove_rejected_recommended=False):
from media.sonarr import Sonarr from media.sonarr import Sonarr
from media.trakt import Trakt from media.trakt import Trakt
from helpers import misc as misc_helper from helpers import misc as misc_helper
@ -222,6 +223,9 @@ def shows(list_type, add_limit=0, add_delay=2.5, sort='votes', genre=None, folde
trakt_objects_list = trakt.get_trending_shows(genres=genre, languages=cfg.filters.shows.allowed_languages) trakt_objects_list = trakt.get_trending_shows(genres=genre, languages=cfg.filters.shows.allowed_languages)
elif list_type.lower() == 'popular': elif list_type.lower() == 'popular':
trakt_objects_list = trakt.get_popular_shows(genres=genre, languages=cfg.filters.shows.allowed_languages) trakt_objects_list = trakt.get_popular_shows(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'): elif list_type.lower().startswith('played'):
most_type = misc_helper.substring_after(list_type.lower(), "_") 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, trakt_objects_list = trakt.get_most_played_shows(genres=genre, languages=cfg.filters.shows.allowed_languages,
@ -245,8 +249,14 @@ def shows(list_type, add_limit=0, add_delay=2.5, sort='votes', genre=None, folde
else: else:
log.info("Retrieved Trakt %s shows list, shows found: %d", list_type, len(trakt_objects_list)) 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_recommended = False
# build filtered series list without series that exist in sonarr # build filtered series list without series that exist in sonarr
processed_series_list = sonarr_helper.remove_existing_series(pvr_objects_list, trakt_objects_list) processed_series_list = sonarr_helper.remove_existing_series(pvr_objects_list, trakt_objects_list,
callback_remove_recommended
if remove_rejected_recommended else None)
if processed_series_list is None: if processed_series_list is None:
log.error("Aborting due to failure to remove existing Sonarr shows from retrieved Trakt shows list") log.error("Aborting due to failure to remove existing Sonarr shows from retrieved Trakt shows list")
if notifications: if notifications:
@ -279,7 +289,9 @@ def shows(list_type, add_limit=0, add_delay=2.5, sort='votes', genre=None, folde
continue continue
# check if series passes out blacklist criteria inspection # check if series passes out blacklist criteria inspection
if not trakt_helper.is_show_blacklisted(series, cfg.filters.shows, ignore_blacklist): if not trakt_helper.is_show_blacklisted(series, cfg.filters.shows, ignore_blacklist,
callback_remove_recommended
if remove_rejected_recommended else None):
log.info("Adding: %s | Genres: %s | Network: %s | Country: %s", series['show']['title'], log.info("Adding: %s | Genres: %s | Network: %s | Country: %s", series['show']['title'],
', '.join(series['show']['genres']), series['show']['network'], ', '.join(series['show']['genres']), series['show']['network'],
series['show']['country'].upper()) series['show']['country'].upper())
@ -380,8 +392,9 @@ def movie(movie_id, folder=None, no_search=False):
@click.option('--authenticate-user', @click.option('--authenticate-user',
help='Specify which user to authenticate with to retrieve Trakt lists. Default: first user in the config.') help='Specify which user to authenticate with to retrieve Trakt lists. Default: first user in the config.')
@click.option('--ignore-blacklist', is_flag=True, help='Ignores the blacklist when running the command.') @click.option('--ignore-blacklist', is_flag=True, help='Ignores the blacklist when running the command.')
@click.option('--remove-rejected-recommended', is_flag=True, help='Removes rejected/existing movies from recommended.')
def movies(list_type, add_limit=0, add_delay=2.5, sort='votes', genre=None, folder=None, no_search=False, def movies(list_type, add_limit=0, add_delay=2.5, sort='votes', genre=None, folder=None, no_search=False,
notifications=False, authenticate_user=None, ignore_blacklist=False): notifications=False, authenticate_user=None, ignore_blacklist=False, remove_rejected_recommended=False):
from media.radarr import Radarr from media.radarr import Radarr
from media.trakt import Trakt from media.trakt import Trakt
from helpers import misc as misc_helper from helpers import misc as misc_helper
@ -418,6 +431,9 @@ def movies(list_type, add_limit=0, add_delay=2.5, sort='votes', genre=None, fold
trakt_objects_list = trakt.get_popular_movies(genres=genre, languages=cfg.filters.movies.allowed_languages) trakt_objects_list = trakt.get_popular_movies(genres=genre, languages=cfg.filters.movies.allowed_languages)
elif list_type.lower() == 'boxoffice': elif list_type.lower() == 'boxoffice':
trakt_objects_list = trakt.get_boxoffice_movies() trakt_objects_list = trakt.get_boxoffice_movies()
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'): elif list_type.lower().startswith('played'):
most_type = misc_helper.substring_after(list_type.lower(), "_") 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, trakt_objects_list = trakt.get_most_played_movies(genres=genre, languages=cfg.filters.movies.allowed_languages,
@ -441,8 +457,14 @@ def movies(list_type, add_limit=0, add_delay=2.5, sort='votes', genre=None, fold
else: else:
log.info("Retrieved Trakt %s movies list, movies found: %d", list_type, len(trakt_objects_list)) 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_recommended = False
# build filtered movie list without movies that exist in radarr # build filtered movie list without movies that exist in radarr
processed_movies_list = radarr_helper.remove_existing_movies(pvr_objects_list, trakt_objects_list) processed_movies_list = radarr_helper.remove_existing_movies(pvr_objects_list, trakt_objects_list,
callback_remove_recommended
if remove_rejected_recommended else None)
if processed_movies_list is None: if processed_movies_list is None:
log.error("Aborting due to failure to remove existing Radarr movies from retrieved Trakt movies list") log.error("Aborting due to failure to remove existing Radarr movies from retrieved Trakt movies list")
if notifications: if notifications:
@ -475,7 +497,9 @@ def movies(list_type, add_limit=0, add_delay=2.5, sort='votes', genre=None, fold
continue continue
# check if movie passes out blacklist criteria inspection # check if movie passes out blacklist criteria inspection
if not trakt_helper.is_movie_blacklisted(movie, cfg.filters.movies, ignore_blacklist): if not trakt_helper.is_movie_blacklisted(movie, cfg.filters.movies, ignore_blacklist,
callback_remove_recommended if remove_rejected_recommended
else None):
log.info("Adding: %s (%d) | Genres: %s | Country: %s", movie['movie']['title'], movie['movie']['year'], log.info("Adding: %s (%d) | Genres: %s | Country: %s", movie['movie']['title'], movie['movie']['year'],
', '.join(movie['movie']['genres']), movie['movie']['country'].upper()) ', '.join(movie['movie']['genres']), movie['movie']['country'].upper())
# add movie to radarr # add movie to radarr
@ -508,9 +532,28 @@ def movies(list_type, add_limit=0, add_delay=2.5, sort='votes', genre=None, fold
############################################################ ############################################################
# AUTOMATIC # CALLBACKS
############################################################ ############################################################
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 callback_notify(data): def callback_notify(data):
log.debug("Received callback data: %s", data) log.debug("Received callback data: %s", data)
@ -536,6 +579,11 @@ def callback_notify(data):
return return
############################################################
# AUTOMATIC
############################################################
def automatic_shows(add_delay=2.5, sort='votes', no_search=False, notifications=False, ignore_blacklist=False): def automatic_shows(add_delay=2.5, sort='votes', no_search=False, notifications=False, ignore_blacklist=False):
from media.trakt import Trakt from media.trakt import Trakt

Loading…
Cancel
Save