Logs: More details / cleaner look / wording

pull/93/head
desimaniac 6 years ago
parent c0f34f60c2
commit eeb51b0c74

@ -10,34 +10,39 @@ def get_rating(apikey, movie):
ratings_exist = False ratings_exist = False
imdb_id = movie['movie']['ids']['imdb'] imdb_id = movie['movie']['ids']['imdb']
if imdb_id: if imdb_id:
log.debug("Requesting info from OMDB for \'%s (%d)\' | Genres: %s | Country: %s | IMDB ID: %s", log.debug("Requesting info from OMDb for: \'%s (%s)\' | IMDb ID: %s",
movie['movie']['title'], movie['movie']['year'], ', '.join(movie['movie']['genres']), movie['movie']['title'],
(movie['movie']['country'] or 'N/A').upper(), imdb_id) str(movie['movie']['year']) if movie['movie']['year'] else '????',
imdb_id)
r = requests.get('http://www.omdbapi.com/?i=' + imdb_id + '&apikey=' + apikey) r = requests.get('http://www.omdbapi.com/?i=' + imdb_id + '&apikey=' + apikey)
if r.status_code == 200 and json.loads(r.text)["Response"] == 'True': if r.status_code == 200 and json.loads(r.text)["Response"] == 'True':
log.debug("Successfully requested ratings from OMDB for \'%s (%d)\' | Genres: %s | Country: %s" + log.debug("Successfully requested ratings from OMDB for \'%s (%s)\' | IMDb ID: %s",
" | IMDB ID: %s", movie['movie']['title'], movie['movie']['year'], movie['movie']['title'],
', '.join(movie['movie']['genres']), (movie['movie']['country'] or 'N/A').upper(), imdb_id) str(movie['movie']['year']) if movie['movie']['year'] else '????',
imdb_id)
for source in json.loads(r.text)["Ratings"]: for source in json.loads(r.text)["Ratings"]:
if source['Source'] == 'Rotten Tomatoes': if source['Source'] == 'Rotten Tomatoes':
# noinspection PyUnusedLocal # noinspection PyUnusedLocal
ratings_exist = True ratings_exist = True
log.debug("Rotten Tomatoes score of %s for \'%s (%d)\' | Genres: %s | Country: %s | IMDB ID: %s ", log.debug("Rotten Tomatoes score of %s for: \'%s (%s)\' | IMDb ID: %s ",
source['Value'], movie['movie']['title'], movie['movie']['year'], source['Value'],
', '.join(movie['movie']['genres']), (movie['movie']['country'] or 'N/A').upper(), movie['movie']['title'],
str(movie['movie']['year']) if movie['movie']['year'] else '????',
imdb_id) imdb_id)
return int(source['Value'].split('%')[0]) return int(source['Value'].split('%')[0])
if not ratings_exist: if not ratings_exist:
log.debug("No Rotten Tomatoes score found for \'%s (%d)\' | Genres: %s | Country: %s | IMDB ID: %s ", log.debug("No Rotten Tomatoes score found for: \'%s (%s)\' | IMDb ID: %s",
movie['movie']['title'], movie['movie']['year'], ', '.join(movie['movie']['genres']), movie['movie']['title'],
(movie['movie']['country'] or 'N/A').upper(), imdb_id) str(movie['movie']['year']) if movie['movie']['year'] else '????',
imdb_id)
else: else:
log.debug("Error encountered when requesting ratings from OMDB for \'%s (%d)\' | Genres: %s | Country: %s" + log.debug("Error encountered when requesting ratings from OMDb for: \'%s (%s)\' | IMDb ID: %s",
" | IMDB ID: %s", movie['movie']['title'], movie['movie']['year'], movie['movie']['title'],
', '.join(movie['movie']['genres']), (movie['movie']['country'] or 'N/A').upper(), imdb_id) str(movie['movie']['year']) if movie['movie']['year'] else '????',
imdb_id)
else: else:
log.debug("Skipping \'%s (%d)\' | Genres: %s | Country: %s as it does not have an IMDB ID", log.debug("Skipping OMDb ratings lookup because no IMDb ID was found for: \'%s (%s)\'",
movie['movie']['title'], movie['movie']['year'], ', '.join(movie['movie']['genres']), movie['movie']['title'],
(movie['movie']['country'] or 'N/A').upper()) str(movie['movie']['year']) if movie['movie']['year'] else '????')
return -1 return -1

@ -9,16 +9,17 @@ def blacklisted_show_genre(show, genres):
try: try:
# ["ignore"] - add show item even if it is missing a genre # ["ignore"] - add show item even if it is missing a genre
if len(genres) == 1 and genres[0].lower() == 'ignore': if len(genres) == 1 and genres[0].lower() == 'ignore':
log.debug("Skipping valid genres check for %s.", show['show']['title']) log.debug("Skipping valid genre check for: \'%s\'", show['show']['title'])
# [] - add show item with any valid genre # [] - add show item with any valid genre
elif not show['show']['genres']: elif not show['show']['genres']:
log.debug("%s was blacklisted because it had no genres", show['show']['title']) log.debug("\'%s\' was blacklisted because it had no genre", show['show']['title'])
blacklisted = True blacklisted = True
# List provided - skip adding show item if the genre is blacklisted # List provided - skip adding show item if the genre is blacklisted
else: else:
for genre in genres: for genre in genres:
if genre.lower() in show['show']['genres']: if genre.lower() in show['show']['genres']:
log.debug("%s was blacklisted because it has genre: %s", show['show']['title'], genre) log.debug("\'%s\' was blacklisted because it was from the genre: %s", show['show']['title'],
genre.title())
blacklisted = True blacklisted = True
break break
@ -32,11 +33,11 @@ def blacklisted_show_year(show, earliest_year, latest_year):
try: try:
year = misc_str.get_year_from_timestamp(show['show']['first_aired']) year = misc_str.get_year_from_timestamp(show['show']['first_aired'])
if not year: if not year:
log.debug("%s was blacklisted due to having an unknown first_aired date", show['show']['title']) log.debug("\'%s\' was blacklisted because it had an unknown first_aired date", show['show']['title'])
blacklisted = True blacklisted = True
else: else:
if year < earliest_year or year > latest_year: if year < earliest_year or year > latest_year:
log.debug("%s was blacklisted because it first aired in: %d", show['show']['title'], year) log.debug("\'%s\' was blacklisted because it first aired in: %d", show['show']['title'], year)
blacklisted = True blacklisted = True
except Exception: except Exception:
log.exception("Exception determining if show is within min_year and max_year range %s:", show) log.exception("Exception determining if show is within min_year and max_year range %s:", show)
@ -48,18 +49,18 @@ def blacklisted_show_country(show, allowed_countries):
try: try:
# [] or ["ignore"] - add show item even if it is missing a country # [] or ["ignore"] - add show item even if it is missing a country
if (not allowed_countries) or (len(allowed_countries) == 1 and allowed_countries[0].lower() == 'ignore'): if (not allowed_countries) or (len(allowed_countries) == 1 and allowed_countries[0].lower() == 'ignore'):
log.debug("Skipping valid countries check for %s.", show['show']['title']) log.debug("Skipping valid countries check for: \'%s\'", show['show']['title'])
# List provided - skip adding show item because it is missing a country # List provided - skip adding show item because it is missing a country
elif not show['show']['country']: elif not show['show']['country']:
log.debug("%s was blacklisted because it had no country", show['show']['title']) log.debug("\'%s\' was blacklisted because it had no country", show['show']['title'])
blacklisted = True blacklisted = True
# ["any"] - add show item with any valid country # ["any"] - add show item with any valid country
elif len(allowed_countries) == 1 and allowed_countries[0].lower() == 'any': elif len(allowed_countries) == 1 and allowed_countries[0].lower() == 'any':
log.debug("Skipping allowed countries check.") log.debug("Skipping allowed countries check for: \'%s\'")
# List provided - skip adding show item if the country is blacklisted # List provided - skip adding show item if the country is blacklisted
elif show['show']['country'].lower() not in allowed_countries: elif show['show']['country'].lower() not in allowed_countries:
log.debug("%s was blacklisted because it's from country: %s", show['show']['title'], log.debug("\'%s\' was blacklisted because it's from the country: %s", show['show']['title'],
show['show']['country']) show['show']['country'].upper())
blacklisted = True blacklisted = True
except Exception: except Exception:
@ -71,12 +72,12 @@ def blacklisted_show_network(show, networks):
blacklisted = False blacklisted = False
try: try:
if not show['show']['network']: if not show['show']['network']:
log.debug("%s was blacklisted because it had no network", show['show']['title']) log.debug("\'%s\' was blacklisted because it had no network", show['show']['title'])
blacklisted = True blacklisted = True
else: else:
for network in networks: for network in networks:
if network.lower() in show['show']['network'].lower(): if network.lower() in show['show']['network'].lower():
log.debug("%s was blacklisted because it's from network: %s", show['show']['title'], log.debug("\'%s\' was blacklisted because it's from the network: %s", show['show']['title'],
show['show']['network']) show['show']['network'])
blacklisted = True blacklisted = True
break break
@ -90,10 +91,10 @@ def blacklisted_show_runtime(show, lowest_runtime):
blacklisted = False blacklisted = False
try: try:
if not show['show']['runtime'] or not isinstance(show['show']['runtime'], int): if not show['show']['runtime'] or not isinstance(show['show']['runtime'], int):
log.debug("%s was blacklisted because it had no runtime", show['show']['title']) log.debug("\'%s\' was blacklisted because it had no runtime", show['show']['title'])
blacklisted = True blacklisted = True
elif int(show['show']['runtime']) < lowest_runtime: elif int(show['show']['runtime']) < lowest_runtime:
log.debug("%s was blacklisted because it had a runtime of: %d", show['show']['title'], log.debug("\'%s\' was blacklisted because it had a runtime of: %d", show['show']['title'],
show['show']['runtime']) show['show']['runtime'])
blacklisted = True blacklisted = True
@ -107,10 +108,10 @@ def blacklisted_show_id(show, blacklisted_ids):
blacklisted_ids = sorted(map(int, blacklisted_ids)) blacklisted_ids = sorted(map(int, blacklisted_ids))
try: try:
if not show['show']['ids']['tvdb'] or not isinstance(show['show']['ids']['tvdb'], int): if not show['show']['ids']['tvdb'] or not isinstance(show['show']['ids']['tvdb'], int):
log.debug("%s was blacklisted because it had an invalid TVDB ID", show['show']['title']) log.debug("\'%s\' was blacklisted because it had an invalid TVDB ID", show['show']['title'])
blacklisted = True blacklisted = True
elif show['show']['ids']['tvdb'] in blacklisted_ids: elif show['show']['ids']['tvdb'] in blacklisted_ids:
log.debug("%s was blacklisted because it had a blacklisted TVDB ID of: %d", show['show']['title'], log.debug("\'%s\' was blacklisted because it had a blacklisted TVDB ID of: %d", show['show']['title'],
show['show']['ids']['tvdb']) show['show']['ids']['tvdb'])
blacklisted = True blacklisted = True
@ -152,16 +153,17 @@ def blacklisted_movie_genre(movie, genres):
try: try:
# ["ignore"] - add movie item even if it is missing a genre # ["ignore"] - add movie item even if it is missing a genre
if len(genres) == 1 and genres[0].lower() == 'ignore': if len(genres) == 1 and genres[0].lower() == 'ignore':
log.debug("Skipping valid genres check for %s.", movie['movie']['title']) log.debug("Skipping valid genre check for: \'%s\'", movie['movie']['title'])
# [] - add movie item with any valid genre # [] - add movie item with any valid genre
elif not movie['movie']['genres']: elif not movie['movie']['genres']:
log.debug("%s was blacklisted because it had no genres", movie['movie']['title']) log.debug("\'%s\' was blacklisted because it had no genre", movie['movie']['title'])
blacklisted = True blacklisted = True
# List provided - skip adding movie item if the genre is blacklisted # List provided - skip adding movie item if the genre is blacklisted
else: else:
for genre in genres: for genre in genres:
if genre.lower() in movie['movie']['genres']: if genre.lower() in movie['movie']['genres']:
log.debug("%s was blacklisted because it has genre: %s", movie['movie']['title'], genre) log.debug("%s was blacklisted because it was from the genre: %s", movie['movie']['title'],
genre.title())
blacklisted = True blacklisted = True
break break
@ -175,11 +177,11 @@ def blacklisted_movie_year(movie, earliest_year, latest_year):
try: try:
year = movie['movie']['year'] year = movie['movie']['year']
if year is None or not isinstance(year, int): if year is None or not isinstance(year, int):
log.debug("%s was blacklisted due to having an unknown year", movie['movie']['title']) log.debug("\'%s\' was blacklisted because it had an unknown year", movie['movie']['title'])
blacklisted = True blacklisted = True
else: else:
if int(year) < earliest_year or int(year) > latest_year: if int(year) < earliest_year or int(year) > latest_year:
log.debug("%s was blacklisted because its year is: %d", movie['movie']['title'], int(year)) log.debug("\'%s\' was blacklisted because its year is: %d", movie['movie']['title'], int(year))
blacklisted = True blacklisted = True
except Exception: except Exception:
log.exception("Exception determining if movie is within min_year and max_year ranger %s:", movie) log.exception("Exception determining if movie is within min_year and max_year ranger %s:", movie)
@ -191,18 +193,18 @@ def blacklisted_movie_country(movie, allowed_countries):
try: try:
# [] or ["ignore"] - add movie item even if it is missing a country # [] or ["ignore"] - add movie item even if it is missing a country
if (not allowed_countries) or (len(allowed_countries) == 1 and allowed_countries[0].lower() == 'ignore'): if (not allowed_countries) or (len(allowed_countries) == 1 and allowed_countries[0].lower() == 'ignore'):
log.debug("Skipping valid countries check for %s.", movie['movie']['title']) log.debug("Skipping valid countries check for: \'%s\'", movie['movie']['title'])
# List provided - skip adding movie item because it is missing a country # List provided - skip adding movie item because it is missing a country
elif not movie['movie']['country']: elif not movie['movie']['country']:
log.debug("%s was blacklisted because it had no country", movie['movie']['title']) log.debug("\'%s\' was blacklisted because it had no country", movie['movie']['title'])
blacklisted = True blacklisted = True
# ["any"] - add movie item with any valid country # ["any"] - add movie item with any valid country
elif len(allowed_countries) == 1 and allowed_countries[0].lower() == 'any': elif len(allowed_countries) == 1 and allowed_countries[0].lower() == 'any':
log.debug("Skipping allowed countries check.") log.debug("Skipping allowed countries check.")
# List provided - skip adding movie item if the country is blacklisted # List provided - skip adding movie item if the country is blacklisted
elif movie['movie']['country'].lower() not in allowed_countries: elif movie['movie']['country'].lower() not in allowed_countries:
log.debug("%s was blacklisted because it's from country: %s", movie['movie']['title'], log.debug("\'%s\' was blacklisted because it's from the country: %s", movie['movie']['title'],
movie['movie']['country']) movie['movie']['country'].upper())
blacklisted = True blacklisted = True
except Exception: except Exception:
log.exception("Exception determining if movie was from an allowed country %s: ", movie) log.exception("Exception determining if movie was from an allowed country %s: ", movie)
@ -218,7 +220,8 @@ def blacklisted_movie_title(movie, blacklisted_keywords):
else: else:
for keyword in blacklisted_keywords: for keyword in blacklisted_keywords:
if keyword.lower() in movie['movie']['title'].lower(): if keyword.lower() in movie['movie']['title'].lower():
log.debug("%s was blacklisted because it had title keyword: %s", movie['movie']['title'], keyword) log.debug("\'%s\' was blacklisted because it had title keyword: %s", movie['movie']['title'],
keyword)
blacklisted = True blacklisted = True
break break
@ -231,10 +234,10 @@ def blacklisted_movie_runtime(movie, lowest_runtime):
blacklisted = False blacklisted = False
try: try:
if not movie['movie']['runtime'] or not isinstance(movie['movie']['runtime'], int): if not movie['movie']['runtime'] or not isinstance(movie['movie']['runtime'], int):
log.debug("%s was blacklisted because it had no runtime", movie['movie']['title']) log.debug("\'%s\' was blacklisted because it had no runtime", movie['movie']['title'])
blacklisted = True blacklisted = True
elif int(movie['movie']['runtime']) < lowest_runtime: elif int(movie['movie']['runtime']) < lowest_runtime:
log.debug("%s was blacklisted because it had a runtime of: %d", movie['movie']['title'], log.debug("\'%s\' was blacklisted because it had a runtime of: %d", movie['movie']['title'],
movie['movie']['runtime']) movie['movie']['runtime'])
blacklisted = True blacklisted = True
@ -248,15 +251,15 @@ def blacklisted_movie_id(movie, blacklisted_ids):
blacklisted_ids = sorted(map(int, blacklisted_ids)) blacklisted_ids = sorted(map(int, blacklisted_ids))
try: try:
if not movie['movie']['ids']['tmdb'] or not isinstance(movie['movie']['ids']['tmdb'], int): if not movie['movie']['ids']['tmdb'] or not isinstance(movie['movie']['ids']['tmdb'], int):
log.debug("%s was blacklisted because it had an invalid TMDB ID", movie['movie']['title']) log.debug("\'%s\' was blacklisted because it had an invalid TMDb ID", movie['movie']['title'])
blacklisted = True blacklisted = True
elif movie['movie']['ids']['tmdb'] in blacklisted_ids: elif movie['movie']['ids']['tmdb'] in blacklisted_ids:
log.debug("%s was blacklisted because it had a blacklisted TMDB ID of: %d", movie['movie']['title'], log.debug("\'%s\' was blacklisted because it had a blacklisted TMDb ID of: %d", movie['movie']['title'],
movie['movie']['ids']['tmdb']) movie['movie']['ids']['tmdb'])
blacklisted = True blacklisted = True
except Exception: except Exception:
log.exception("Exception determining if show had a blacklisted TMDB ID %s: ", movie) log.exception("Exception determining if show had a blacklisted TMDb ID %s: ", movie)
return blacklisted return blacklisted

@ -83,9 +83,10 @@ class PVR(ABC):
resp_json = req.json() resp_json = req.json()
for profile in resp_json: for profile in resp_json:
if profile['name'].lower() == profile_name.lower(): if profile['name'].lower() == profile_name.lower():
log.debug("Found ID of %s profile: %d", profile_name, profile['id']) log.debug("Found Profile ID for \'%s\': %d", profile_name, profile['id'])
return profile['id'] return profile['id']
log.debug("Profile %s with ID %d did not match %s", profile['name'], profile['id'], profile_name) log.debug("Profile \'%s\' with ID \'%d\' did not match Profile \'%s\'", profile['name'],
profile['id'], profile_name)
else: else:
log.error("Failed to retrieve all quality profiles, request response: %d", req.status_code) log.error("Failed to retrieve all quality profiles, request response: %d", req.status_code)
except Exception: except Exception:
@ -129,17 +130,17 @@ class PVR(ABC):
if (req.status_code == 201 or req.status_code == 200) \ if (req.status_code == 201 or req.status_code == 200) \
and (response_json and identifier_field in response_json) \ and (response_json and identifier_field in response_json) \
and response_json[identifier_field] == identifier: and response_json[identifier_field] == identifier:
log.debug("Successfully added \'%s (%d)\'", payload['title'], identifier) log.debug("Successfully added: \'%s [%d]\'", payload['title'], identifier)
return True return True
elif response_json and ('errorMessage' in response_json or 'message' in response_json): elif response_json and ('errorMessage' in response_json or 'message' in response_json):
message = response_json['errorMessage'] if 'errorMessage' in response_json else response_json['message'] message = response_json['errorMessage'] if 'errorMessage' in response_json else response_json['message']
log.error("Failed to add \'%s (%d)\' - status_code: %d, reason: %s", payload['title'], identifier, log.error("Failed to add \'%s [%d]\' - status_code: %d, reason: %s", payload['title'], identifier,
req.status_code, message) req.status_code, message)
return False return False
else: else:
log.error("Failed to add \'%s (%d)\', unexpected response:\n%s", payload['title'], identifier, req.text) log.error("Failed to add \'%s [%d]\', unexpected response:\n%s", payload['title'], identifier, req.text)
return False return False
except Exception: except Exception:
log.exception("Exception adding \'%s (%d)\': ", payload['title'], identifier) log.exception("Exception adding \'%s [%d]\': ", payload['title'], identifier)
return None return None

@ -31,7 +31,7 @@ class Sonarr(PVR):
if req.status_code == 200: if req.status_code == 200:
resp_json = req.json() resp_json = req.json()
log.debug("Found %d tags", len(resp_json)) log.debug("Found Sonarr Tags: %d", len(resp_json))
for tag in resp_json: for tag in resp_json:
tags[tag['label']] = tag['id'] tags[tag['label']] = tag['id']
return tags return tags

@ -145,13 +145,13 @@ class Trakt:
# check if we have fetched the last page, break if so # check if we have fetched the last page, break if so
if total_pages == 0: if total_pages == 0:
log.debug("There were no more pages to retrieve") log.debug("There were no more pages left to retrieve")
break break
elif current_page >= total_pages: elif current_page >= total_pages:
log.debug("There are no more pages to retrieve results from") log.debug("There are no more pages left to retrieve results from")
break break
else: else:
log.info("There are %d pages left to retrieve results from", total_pages - current_page) log.info("There are %d page(s) left to retrieve results from", total_pages - current_page)
payload['page'] += 1 payload['page'] += 1
time.sleep(sleep_between) time.sleep(sleep_between)

@ -95,25 +95,25 @@ def get_profile_id(pvr, profile):
if not profile_id or not profile_id > 0: if not profile_id or not profile_id > 0:
log.error("Aborting due to failure to retrieve Profile ID for: %s", profile) log.error("Aborting due to failure to retrieve Profile ID for: %s", profile)
exit() exit()
log.info("Retrieved Profile ID for %s: %d", profile, profile_id) log.info("Retrieved Profile ID for \'%s\': %d", profile, profile_id)
return profile_id return profile_id
def get_profile_tags(pvr): def get_profile_tags(pvr):
profile_tags = pvr.get_tags() profile_tags = pvr.get_tags()
if profile_tags is None: if profile_tags is None:
log.error("Aborting due to failure to retrieve Tag ID's") log.error("Aborting due to failure to retrieve Tag IDs")
exit() exit()
log.info("Retrieved %d Tag ID's", len(profile_tags)) log.info("Retrieved Sonarr Tag IDs: %d", len(profile_tags))
return profile_tags return profile_tags
def get_objects(pvr, pvr_type, notifications): def get_objects(pvr, pvr_type, notifications):
objects_list = pvr.get_objects() objects_list = pvr.get_objects()
if not objects_list: if not objects_list:
log.error("Aborting due to failure to retrieve %s shows list", pvr_type) log.error("Aborting due to failure to retrieve shows list from %s", pvr_type)
if notifications: if notifications:
callback_notify({'event': 'error', 'reason': 'Failure to retrieve %s shows list' % pvr_type}) callback_notify({'event': 'error', 'reason': 'Failure to retrieve shows list from %s' % pvr_type})
exit() exit()
objects_type = 'movies' if pvr_type.lower() == 'radarr' else 'shows' 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)) log.info("Retrieved %s %s list, %s found: %d", pvr_type, objects_type, objects_type, len(objects_list))
@ -125,9 +125,18 @@ def get_objects(pvr, pvr_type, notifications):
############################################################ ############################################################
@app.command(help='Add a single show to Sonarr.', context_settings=dict(max_content_width=100)) @app.command(help='Add a single show to Sonarr.', context_settings=dict(max_content_width=100))
@click.option('--show-id', '-id', help='Trakt Show ID.', required=True) @click.option(
@click.option('--folder', '-f', default=None, help='Add show with this root folder to Sonarr.') '--show-id', '-id',
@click.option('--no-search', is_flag=True, help='Disable search when adding show to Sonarr.') help='Trakt Show ID.',
required=True)
@click.option(
'--folder', '-f',
default=None,
help='Add show with this root folder to Sonarr.')
@click.option(
'--no-search',
is_flag=True,
help='Disable search when adding show to Sonarr.')
def show(show_id, folder=None, no_search=False): def show(show_id, folder=None, no_search=False):
from media.sonarr import Sonarr from media.sonarr import Sonarr
from media.trakt import Trakt from media.trakt import Trakt
@ -153,8 +162,8 @@ def show(show_id, folder=None, no_search=False):
log.error("Aborting due to failure to retrieve Trakt show") log.error("Aborting due to failure to retrieve Trakt show")
return None return None
else: else:
log.info("Retrieved Trakt show information for %s: \'%s (%d)\'", show_id, trakt_show['title'], log.info("Retrieved Trakt show information for \'%s\': \'%s (%s)\'", show_id, trakt_show['title'],
trakt_show['year']) str(trakt_show['year']) if trakt_show['year'] else '????')
# determine which tags to use when adding this series # 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']) use_tags = sonarr_helper.series_tag_id_from_network(profile_tags, cfg.sonarr.tags, trakt_show['network'])
@ -162,35 +171,71 @@ def show(show_id, folder=None, no_search=False):
# add show to sonarr # add show to sonarr
if sonarr.add_series(trakt_show['ids']['tvdb'], trakt_show['title'], trakt_show['ids']['slug'], profile_id, 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): cfg.sonarr.root_folder, use_tags, not no_search):
log.info("ADDED \'%s (%d)\' with tags: %s", trakt_show['title'], trakt_show['year'], log.info("ADDED: \'%s (%s)\' with Sonarr Tags: %s", trakt_show['title'],
str(trakt_show['year']) if trakt_show['year'] else '????',
sonarr_helper.readable_tag_from_ids(profile_tags, use_tags)) sonarr_helper.readable_tag_from_ids(profile_tags, use_tags))
else: else:
log.error("FAILED adding \'%s (%d)\' with tags: %s", trakt_show['title'], trakt_show['year'], log.error("FAILED ADDING: \'%s (%s)\' with Sonarr Tags: %s", trakt_show['title'],
str(trakt_show['year']) if trakt_show['year'] else '????',
sonarr_helper.readable_tag_from_ids(profile_tags, use_tags)) sonarr_helper.readable_tag_from_ids(profile_tags, use_tags))
return return
@app.command(help='Add multiple shows to Sonarr.', context_settings=dict(max_content_width=100)) @app.command(help='Add multiple shows to Sonarr.', context_settings=dict(max_content_width=100))
@click.option('--list-type', '-t', @click.option(
help='Trakt list to process. For example, anticipated, trending, popular, person, watched, played, ' '--list-type', '-t',
'recommended, watchlist or any URL to a list', required=True) help='Trakt list to process. '
@click.option('--add-limit', '-l', default=0, help='Limit number of shows added to Sonarr.') 'For example, \'anticipated\', \'trending\', \'popular\', \'person\', \'watched\', \'played\', '
@click.option('--add-delay', '-d', default=2.5, help='Seconds between each add request to Sonarr.', show_default=True) '\'recommended\', \'watchlist\', or any URL to a list',
@click.option('--sort', '-s', default='votes', type=click.Choice(['rating', 'release', 'votes']), required=True)
help='Sort list to process.', show_default=True) @click.option(
@click.option('--genre', '-g', default=None, help='Only add shows from this genre to Sonarr. ' '--add-limit', '-l',
'Use \'ignore\' to add shows from any genre, ' default=0,
'including ones with no genre specified.') help='Limit number of shows added to Sonarr.')
@click.option('--folder', '-f', default=None, help='Add shows with this root folder to Sonarr.') @click.option(
@click.option('--actor', '-a', default=None, help='Only add movies from this actor to Radarr.') '--add-delay', '-d',
@click.option('--no-search', is_flag=True, help='Disable search when adding shows to Sonarr.') default=2.5,
@click.option('--notifications', is_flag=True, help='Send notifications.') help='Seconds between each add request to Sonarr.',
@click.option('--authenticate-user', show_default=True)
@click.option(
'--sort', '-s',
default='votes',
type=click.Choice(['rating', 'release', 'votes']),
help='Sort list to process.',
show_default=True)
@click.option(
'--genre', '-g',
default=None,
help='Only add shows from this genre to Sonarr. '
'Use \'ignore\' to add shows from any genre, including ones with no genre specified.')
@click.option(
'--folder', '-f',
default=None,
help='Add shows with this root folder to Sonarr.')
@click.option(
'--actor', '-a',
default=None,
help='Only add movies from this actor to Radarr.')
@click.option(
'--no-search',
is_flag=True,
help='Disable search when adding shows to Sonarr.')
@click.option(
'--notifications',
is_flag=True,
help='Send notifications.')
@click.option(
'--authenticate-user',
help='Specify which user to authenticate with to retrieve Trakt lists. ' help='Specify which user to authenticate with to retrieve Trakt lists. '
'Default: first user in the config') 'Defaults to first user in the config')
@click.option('--ignore-blacklist', is_flag=True, help='Ignores the blacklist when running the command.') @click.option(
@click.option('--remove-rejected-from-recommended', is_flag=True, '--ignore-blacklist',
is_flag=True,
help='Ignores the blacklist when running the command.')
@click.option(
'--remove-rejected-from-recommended',
is_flag=True,
help='Removes rejected/existing shows from recommended.') help='Removes rejected/existing shows from recommended.')
def shows(list_type, add_limit=0, add_delay=2.5, sort='votes', genre=None, folder=None, actor=None, no_search=False, 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): notifications=False, authenticate_user=None, ignore_blacklist=False, remove_rejected_from_recommended=False):
@ -227,33 +272,41 @@ def shows(list_type, add_limit=0, add_delay=2.5, sort='votes', genre=None, folde
# get trakt series list # get trakt series list
if list_type.lower() == 'anticipated': if list_type.lower() == 'anticipated':
trakt_objects_list = trakt.get_anticipated_shows(genres=genre if 'ignore' not in genre.lower() else None, trakt_objects_list = trakt.get_anticipated_shows(genres=genre if genre and
'ignore' not in genre.lower() else None,
languages=cfg.filters.shows.allowed_languages) languages=cfg.filters.shows.allowed_languages)
elif list_type.lower() == 'trending': elif list_type.lower() == 'trending':
trakt_objects_list = trakt.get_trending_shows(genres=genre if 'ignore' not in genre.lower() else None, trakt_objects_list = trakt.get_trending_shows(genres=genre if genre and
'ignore' not in genre.lower() else None,
languages=cfg.filters.shows.allowed_languages) 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 if 'ignore' not in genre.lower() else None, trakt_objects_list = trakt.get_popular_shows(genres=genre if genre and
'ignore' not in genre.lower() else None,
languages=cfg.filters.shows.allowed_languages) languages=cfg.filters.shows.allowed_languages)
elif list_type.lower() == 'person': elif list_type.lower() == 'person':
if not actor: if not actor:
log.error("You must specify an actor with the --actor / -a parameter when using the person list type!") log.error("You must specify an actor with the \'--actor\' / \'-a\' parameter when using the \'person\'" +
" list type!")
return None return None
trakt_objects_list = trakt.get_person_shows(person=actor, trakt_objects_list = trakt.get_person_shows(person=actor,
genres=genre if 'ignore' not in genre.lower() else None, genres=genre if genre and
'ignore' not in genre.lower() else None,
languages=cfg.filters.shows.allowed_languages) languages=cfg.filters.shows.allowed_languages)
elif list_type.lower() == 'recommended': elif list_type.lower() == 'recommended':
trakt_objects_list = trakt.get_recommended_shows(authenticate_user, trakt_objects_list = trakt.get_recommended_shows(authenticate_user,
genres=genre if 'ignore' not in genre else None, genres=genre if genre
and 'ignore' not in genre.lower() else None,
languages=cfg.filters.shows.allowed_languages) 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 if 'ignore' not in genre.lower() else None, trakt_objects_list = trakt.get_most_played_shows(genres=genre if genre
and 'ignore' not in genre.lower() else None,
languages=cfg.filters.shows.allowed_languages, languages=cfg.filters.shows.allowed_languages,
most_type=most_type if most_type else None) most_type=most_type if most_type else None)
elif list_type.lower().startswith('watched'): elif list_type.lower().startswith('watched'):
most_type = misc_helper.substring_after(list_type.lower(), "_") most_type = misc_helper.substring_after(list_type.lower(), "_")
trakt_objects_list = trakt.get_most_watched_shows(genres=genre if 'ignore' not in genre.lower() else None, trakt_objects_list = trakt.get_most_watched_shows(genres=genre if genre
and 'ignore' not in genre.lower() else None,
languages=cfg.filters.shows.allowed_languages, languages=cfg.filters.shows.allowed_languages,
most_type=most_type if most_type else None) most_type=most_type if most_type else None)
elif list_type.lower() == 'watchlist': elif list_type.lower() == 'watchlist':
@ -262,14 +315,14 @@ def shows(list_type, add_limit=0, add_delay=2.5, sort='votes', genre=None, folde
trakt_objects_list = trakt.get_user_list_shows(list_type, authenticate_user) trakt_objects_list = trakt.get_user_list_shows(list_type, authenticate_user)
if not trakt_objects_list: if not trakt_objects_list:
log.error("Aborting due to failure to retrieve Trakt %s shows list", list_type) log.error("Aborting due to failure to retrieve Trakt \'%s\' shows list", list_type.capitalize())
if notifications: if notifications:
callback_notify( callback_notify(
{'event': 'abort', 'type': 'shows', 'list_type': list_type, {'event': 'abort', 'type': 'shows', 'list_type': list_type,
'reason': 'Failure to retrieve Trakt %s shows list' % list_type}) 'reason': 'Failure to retrieve Trakt %s shows list' % list_type.capitalize()})
return None return None
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.capitalize(), len(trakt_objects_list))
# set remove_rejected_recommended to False if this is not the recommended list # set remove_rejected_recommended to False if this is not the recommended list
if list_type.lower() != 'recommended': if list_type.lower() != 'recommended':
@ -284,7 +337,7 @@ def shows(list_type, add_limit=0, add_delay=2.5, sort='votes', genre=None, folde
if notifications: if notifications:
callback_notify({'event': 'abort', 'type': 'shows', 'list_type': list_type, callback_notify({'event': 'abort', 'type': 'shows', 'list_type': list_type,
'reason': 'Failure to remove existing Sonarr shows from retrieved Trakt %s shows list' 'reason': 'Failure to remove existing Sonarr shows from retrieved Trakt %s shows list'
% list_type}) % list_type.capitalize()})
return None return None
else: else:
log.info("Removed existing Sonarr shows from Trakt shows list, shows left to process: %d", log.info("Removed existing Sonarr shows from Trakt shows list, shows left to process: %d",
@ -293,13 +346,13 @@ def shows(list_type, add_limit=0, add_delay=2.5, sort='votes', genre=None, folde
# sort filtered series list # sort filtered series list
if sort == 'release': if sort == 'release':
sorted_series_list = misc_helper.sorted_list(processed_series_list, 'show', 'first_aired') sorted_series_list = misc_helper.sorted_list(processed_series_list, 'show', 'first_aired')
log.info("Sorted shows list to process by release date") log.info("Sorted shows list to process by recent 'release' date")
elif sort == 'rating': elif sort == 'rating':
sorted_series_list = misc_helper.sorted_list(processed_series_list, 'show', 'rating') sorted_series_list = misc_helper.sorted_list(processed_series_list, 'show', 'rating')
log.info("Sorted shows list to process by highest rating") log.info("Sorted shows list to process by highest 'rating'")
else: else:
sorted_series_list = misc_helper.sorted_list(processed_series_list, 'show', 'votes') sorted_series_list = misc_helper.sorted_list(processed_series_list, 'show', 'votes')
log.info("Sorted shows list to process by highest votes") log.info("Sorted shows list to process by highest 'votes'")
# loop series_list # loop series_list
log.info("Processing list now...") log.info("Processing list now...")
@ -308,17 +361,21 @@ def shows(list_type, add_limit=0, add_delay=2.5, sort='votes', genre=None, folde
try: try:
# check if genre matches genre supplied via argument # check if genre matches genre supplied via argument
if genre and not misc_helper.allowed_genres(genre, 'show', series): 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()) log.debug("Skipping: \'%s\' because it was not from genre: %s", series['show']['title'],
genre.title())
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 callback_remove_recommended
if remove_rejected_from_recommended else None): if remove_rejected_from_recommended else None):
log.info("Adding: %s | Genres: %s | Network: %s | Country: %s", series['show']['title'], log.info("Adding: %s (%s) | Country: %s | Language: %s | Genre: %s | Network: %s",
(', '.join(series['show']['genres'])) if series['show']['genres'] else 'N/A', series['show']['title'],
series['show']['network'], str(series['show']['year']) if series['show']['year'] else '????',
(series['show']['country'] or 'N/A').upper()) (series['show']['country'] or 'N/A').upper(),
(series['show']['language'] or 'N/A').upper(),
(', '.join(series['show']['genres'])).title() if series['show']['genres'] else 'N/A',
series['show']['network'])
# determine which tags to use when adding this series # determine which tags to use when adding this series
use_tags = sonarr_helper.series_tag_id_from_network(profile_tags, cfg.sonarr.tags, use_tags = sonarr_helper.series_tag_id_from_network(profile_tags, cfg.sonarr.tags,
@ -327,14 +384,15 @@ def shows(list_type, add_limit=0, add_delay=2.5, sort='votes', genre=None, folde
if sonarr.add_series(series['show']['ids']['tvdb'], series['show']['title'], if sonarr.add_series(series['show']['ids']['tvdb'], series['show']['title'],
series['show']['ids']['slug'], profile_id, cfg.sonarr.root_folder, use_tags, series['show']['ids']['slug'], profile_id, cfg.sonarr.root_folder, use_tags,
not no_search): not no_search):
log.info("ADDED \'%s (%d)\' with tags: %s", series['show']['title'], series['show']['year'], log.info("ADDED: \'%s (%s)\' with tags: %s", series['show']['title'],
str(series['show']['year']) if series['show']['year'] else '????',
sonarr_helper.readable_tag_from_ids(profile_tags, use_tags)) sonarr_helper.readable_tag_from_ids(profile_tags, use_tags))
if notifications: if notifications:
callback_notify({'event': 'add_show', 'list_type': list_type, 'show': series['show']}) callback_notify({'event': 'add_show', 'list_type': list_type, 'show': series['show']})
added_shows += 1 added_shows += 1
else: else:
log.error("FAILED adding \'%s (%d)\' with tags: %s", series['show']['title'], log.error("FAILED ADDING: \'%s (%s)\' with tags: %s", series['show']['title'],
series['show']['year'], str(series['show']['year']) if series['show']['year'] else '????',
sonarr_helper.readable_tag_from_ids(profile_tags, use_tags)) sonarr_helper.readable_tag_from_ids(profile_tags, use_tags))
# stop adding shows, if added_shows >= add_limit # stop adding shows, if added_shows >= add_limit
@ -345,13 +403,13 @@ def shows(list_type, add_limit=0, add_delay=2.5, sort='votes', genre=None, folde
time.sleep(add_delay) time.sleep(add_delay)
except Exception: except Exception:
log.exception("Exception while processing show %s: ", series['show']['title']) log.exception("Exception while processing show \'%s\': ", series['show']['title'])
log.info("Added %d new show(s) to Sonarr", added_shows) log.info("Added %d new show(s) to Sonarr", added_shows)
# send notification # send notification
if notifications and (cfg.notifications.verbose or added_shows > 0): 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)) notify.send(message="Added %d shows from Trakt's \'%s\' list" % (added_shows, list_type))
return added_shows return added_shows
@ -361,12 +419,23 @@ def shows(list_type, add_limit=0, add_delay=2.5, sort='votes', genre=None, folde
############################################################ ############################################################
@app.command(help='Add a single movie to Radarr.', context_settings=dict(max_content_width=100)) @app.command(help='Add a single movie to Radarr.', context_settings=dict(max_content_width=100))
@click.option('--movie-id', '-id', help='Trakt Movie ID.', required=True) @click.option(
@click.option('--folder', '-f', default=None, help='Add movie with this root folder to Radarr.') '--movie-id', '-id',
@click.option('--minimum-availability', '-ma', default='released', help='Trakt Movie ID.',
required=True)
@click.option(
'--folder', '-f',
default=None,
help='Add movie with this root folder to Radarr.')
@click.option(
'--minimum-availability', '-ma',
default='released',
type=click.Choice(['announced', 'in_cinemas', 'released', 'predb']), type=click.Choice(['announced', 'in_cinemas', 'released', 'predb']),
help='Add movies with this minimum availability to Radarr.', show_default=True) help='Add movies with this minimum availability to Radarr.', show_default=True)
@click.option('--no-search', is_flag=True, help='Disable search when adding movie to Radarr.') @click.option(
'--no-search',
is_flag=True,
help='Disable search when adding movie to Radarr.')
def movie(movie_id, folder=None, minimum_availability='released', no_search=False): def movie(movie_id, folder=None, minimum_availability='released', no_search=False):
from media.radarr import Radarr from media.radarr import Radarr
from media.trakt import Trakt from media.trakt import Trakt
@ -397,45 +466,86 @@ def movie(movie_id, folder=None, minimum_availability='released', no_search=Fals
log.error("Aborting due to failure to retrieve Trakt movie") log.error("Aborting due to failure to retrieve Trakt movie")
return None return None
else: else:
log.info("Retrieved Trakt movie information for %s: \'%s (%d)\'", movie_id, trakt_movie['title'], log.info("Retrieved Trakt movie information for \'%s\': \'%s (%s)\'", movie_id, trakt_movie['title'],
trakt_movie['year']) str(trakt_movie['year']) if trakt_movie['year'] else '????')
# add movie to radarr # add movie to radarr
if radarr.add_movie(trakt_movie['ids']['tmdb'], trakt_movie['title'], trakt_movie['year'], if radarr.add_movie(trakt_movie['ids']['tmdb'], trakt_movie['title'], trakt_movie['year'],
trakt_movie['ids']['slug'], profile_id, cfg.radarr.root_folder, trakt_movie['ids']['slug'], profile_id, cfg.radarr.root_folder,
cfg.radarr.minimum_availability, not no_search): cfg.radarr.minimum_availability, not no_search):
log.info("ADDED \'%s (%d)\'", trakt_movie['title'], trakt_movie['year']) log.info("ADDED \'%s (%s)\'", trakt_movie['title'],
str(trakt_movie['year']) if trakt_movie['year'] else '????')
else: else:
log.error("FAILED adding \'%s (%d)\'", trakt_movie['title'], trakt_movie['year']) log.error("FAILED adding \'%s (%s)\'", trakt_movie['title'],
str(trakt_movie['year']) if trakt_movie['year'] else '????')
return return
@app.command(help='Add multiple movies to Radarr.', context_settings=dict(max_content_width=100)) @app.command(help='Add multiple movies to Radarr.', context_settings=dict(max_content_width=100))
@click.option('--list-type', '-t', @click.option(
help='Trakt list to process. For example, anticipated, trending, popular, boxoffice, person, watched, ' '--list-type', '-t',
'recommended, played, watchlist or any URL to a list', required=True) help='Trakt list to process. '
@click.option('--add-limit', '-l', default=0, help='Limit number of movies added to Radarr.') 'For example, \'anticipated\', \'trending\', \'popular\', \'person\', \'watched\', \'played\', '
@click.option('--add-delay', '-d', default=2.5, help='Seconds between each add request to Radarr.', show_default=True) '\'recommended\', \'watchlist\', or any URL to a list',
@click.option('--sort', '-s', default='votes', type=click.Choice(['rating', 'release', 'votes']), required=True)
@click.option(
'--add-limit', '-l',
default=0,
help='Limit number of movies added to Radarr.')
@click.option(
'--add-delay', '-d',
default=2.5,
help='Seconds between each add request to Radarr.',
show_default=True)
@click.option(
'--sort', '-s',
default='votes',
type=click.Choice(['rating', 'release', 'votes']),
help='Sort list to process.', show_default=True) help='Sort list to process.', show_default=True)
@click.option('--rating', '-r', default=None, type=int, @click.option(
help='Set a minimum rating threshold (according to Rotten Tomatoes)') '--rating', '-r',
@click.option('--genre', '-g', default=None, help='Only add movies from this genre to Radarr.' default=None,
'Use \'ignore\' to add movies from any genre, ' type=int,
'including ones with no genre specified.') help='Set a minimum Rotten Tomatoes score.')
@click.option('--folder', '-f', default=None, help='Add movies with this root folder to Radarr.') @click.option(
@click.option('--minimum-availability', '-ma', default='released', '--genre', '-g',
default=None,
help='Only add movies from this genre to Radarr. '
'Use \'ignore\' to add movies from any genre, including ones with no genre specified.')
@click.option(
'--folder', '-f',
default=None,
help='Add movies with this root folder to Radarr.')
@click.option(
'--minimum-availability', '-ma',
default='released',
type=click.Choice(['announced', 'in_cinemas', 'released', 'predb']), type=click.Choice(['announced', 'in_cinemas', 'released', 'predb']),
help='Add movies with this minimum availability to Radarr.', show_default=True) help='Add movies with this minimum availability to Radarr.',
@click.option('--actor', '-a', default=None, help='Only add movies from this actor to Radarr.') show_default=True)
@click.option('--no-search', is_flag=True, help='Disable search when adding movies to Radarr.') @click.option(
@click.option('--notifications', is_flag=True, help='Send notifications.') '--actor', '-a',
@click.option('--authenticate-user', default=None,
help='Only add movies from this actor to Radarr.')
@click.option(
'--no-search',
is_flag=True,
help='Disable search when adding movies to Radarr.')
@click.option(
'--notifications',
is_flag=True,
help='Send notifications.')
@click.option(
'--authenticate-user',
help='Specify which user to authenticate with to retrieve Trakt lists. ' help='Specify which user to authenticate with to retrieve Trakt lists. '
'Default: first user in the config.') 'Default: first user in the config.')
@click.option('--ignore-blacklist', is_flag=True, help='Ignores the blacklist when running the command.') @click.option(
@click.option('--remove-rejected-from-recommended', is_flag=True, '--ignore-blacklist',
is_flag=True,
help='Ignores the blacklist when running the command.')
@click.option(
'--remove-rejected-from-recommended',
is_flag=True,
help='Removes rejected/existing movies from recommended.') help='Removes rejected/existing movies from recommended.')
def movies(list_type, add_limit=0, add_delay=2.5, sort='votes', rating=None, genre=None, folder=None, def movies(list_type, add_limit=0, add_delay=2.5, sort='votes', rating=None, genre=None, folder=None,
minimum_availability='released', actor=None, no_search=False, notifications=False, authenticate_user=None, minimum_availability='released', actor=None, no_search=False, notifications=False, authenticate_user=None,
@ -479,36 +589,44 @@ def movies(list_type, add_limit=0, add_delay=2.5, sort='votes', rating=None, gen
# get trakt movies list # get trakt movies list
if list_type.lower() == 'anticipated': if list_type.lower() == 'anticipated':
trakt_objects_list = trakt.get_anticipated_movies(genres=genre if 'ignore' not in genre else None, trakt_objects_list = trakt.get_anticipated_movies(genres=genre if genre
and 'ignore' not in genre.lower() else None,
languages=cfg.filters.movies.allowed_languages) languages=cfg.filters.movies.allowed_languages)
elif list_type.lower() == 'trending': elif list_type.lower() == 'trending':
trakt_objects_list = trakt.get_trending_movies(genres=genre if 'ignore' not in genre else None, trakt_objects_list = trakt.get_trending_movies(genres=genre if genre
and 'ignore' not in genre.lower() else None,
languages=cfg.filters.movies.allowed_languages) languages=cfg.filters.movies.allowed_languages)
elif list_type.lower() == 'popular': elif list_type.lower() == 'popular':
trakt_objects_list = trakt.get_popular_movies(genres=genre if 'ignore' not in genre else None, trakt_objects_list = trakt.get_popular_movies(genres=genre if genre
and 'ignore' not in genre.lower() else None,
languages=cfg.filters.movies.allowed_languages) 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() == 'person': elif list_type.lower() == 'person':
if not actor: if not actor:
log.error("You must specify an actor with the --actor / -a parameter when using the person list type!") log.error("You must specify an actor with the \'--actor\' / \'-a\' parameter when using the \'person\'" +
" list type!")
return None return None
trakt_objects_list = trakt.get_person_movies(person=actor, trakt_objects_list = trakt.get_person_movies(person=actor,
genres=genre if 'ignore' not in genre.lower() else None, genres=genre if genre
and 'ignore' not in genre.lower() else None,
languages=cfg.filters.movies.allowed_languages) languages=cfg.filters.movies.allowed_languages)
elif list_type.lower() == 'recommended': elif list_type.lower() == 'recommended':
trakt_objects_list = trakt.get_recommended_movies(authenticate_user, trakt_objects_list = trakt.get_recommended_movies(authenticate_user,
genres=genre if 'ignore' not in genre.lower() else None, genres=genre if genre
and 'ignore' not in genre.lower() else None,
languages=cfg.filters.movies.allowed_languages) 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 if 'ignore' not in genre.lower() else None, trakt_objects_list = trakt.get_most_played_movies(genres=genre if genre
and 'ignore' not in genre.lower() else None,
languages=cfg.filters.movies.allowed_languages, languages=cfg.filters.movies.allowed_languages,
most_type=most_type if most_type else None) most_type=most_type if most_type else None)
elif list_type.lower().startswith('watched'): elif list_type.lower().startswith('watched'):
most_type = misc_helper.substring_after(list_type.lower(), "_") most_type = misc_helper.substring_after(list_type.lower(), "_")
trakt_objects_list = trakt.get_most_watched_movies(genres=genre if 'ignore' not in genre.lower() else None, trakt_objects_list = trakt.get_most_watched_movies(genres=genre if genre
and 'ignore' not in genre.lower() else None,
languages=cfg.filters.movies.allowed_languages, languages=cfg.filters.movies.allowed_languages,
most_type=most_type if most_type else None) most_type=most_type if most_type else None)
elif list_type.lower() == 'watchlist': elif list_type.lower() == 'watchlist':
@ -517,14 +635,15 @@ def movies(list_type, add_limit=0, add_delay=2.5, sort='votes', rating=None, gen
trakt_objects_list = trakt.get_user_list_movies(list_type, authenticate_user) trakt_objects_list = trakt.get_user_list_movies(list_type, authenticate_user)
if not trakt_objects_list: if not trakt_objects_list:
log.error("Aborting due to failure to retrieve Trakt %s movies list", list_type) log.error("Aborting due to failure to retrieve Trakt \'%s\' movies list", list_type.capitalize())
if notifications: if notifications:
callback_notify( callback_notify(
{'event': 'abort', 'type': 'movies', 'list_type': list_type, {'event': 'abort', 'type': 'movies', 'list_type': list_type,
'reason': 'Failure to retrieve Trakt %s movies list' % list_type}) 'reason': 'Failure to retrieve Trakt \'%s\' movies list' % list_type.capitalize()})
return None return None
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.capitalize(),
len(trakt_objects_list))
# set remove_rejected_recommended to False if this is not the recommended list # set remove_rejected_recommended to False if this is not the recommended list
if list_type.lower() != 'recommended': if list_type.lower() != 'recommended':
@ -539,7 +658,7 @@ def movies(list_type, add_limit=0, add_delay=2.5, sort='votes', rating=None, gen
if notifications: if notifications:
callback_notify({'event': 'abort', 'type': 'movies', 'list_type': list_type, callback_notify({'event': 'abort', 'type': 'movies', 'list_type': list_type,
'reason': 'Failure to remove existing Radarr movies from retrieved ' 'reason': 'Failure to remove existing Radarr movies from retrieved '
'Trakt %s movies list' % list_type}) 'Trakt %s movies list' % list_type.capitalize()})
return None return None
else: else:
log.info("Removed existing Radarr movies from Trakt movies list, movies left to process: %d", log.info("Removed existing Radarr movies from Trakt movies list, movies left to process: %d",
@ -548,13 +667,13 @@ def movies(list_type, add_limit=0, add_delay=2.5, sort='votes', rating=None, gen
# sort filtered movie list # sort filtered movie list
if sort == 'release': if sort == 'release':
sorted_movies_list = misc_helper.sorted_list(processed_movies_list, 'movie', 'released') sorted_movies_list = misc_helper.sorted_list(processed_movies_list, 'movie', 'released')
log.info("Sorted movies list to process by release date") log.info("Sorted movies list to process by recent 'release' date")
elif sort == 'rating': elif sort == 'rating':
sorted_movies_list = misc_helper.sorted_list(processed_movies_list, 'movie', 'rating') sorted_movies_list = misc_helper.sorted_list(processed_movies_list, 'movie', 'rating')
log.info("Sorted movies list to process by highest rating") log.info("Sorted movies list to process by highest 'rating'")
else: else:
sorted_movies_list = misc_helper.sorted_list(processed_movies_list, 'movie', 'votes') sorted_movies_list = misc_helper.sorted_list(processed_movies_list, 'movie', 'votes')
log.info("Sorted movies list to process by highest votes") log.info("Sorted movies list to process by highest 'votes'")
# display specified RT score # display specified RT score
if rating is not None and 'omdb' in cfg and 'api_key' in cfg['omdb'] and cfg['omdb']['api_key']: if rating is not None and 'omdb' in cfg and 'api_key' in cfg['omdb'] and cfg['omdb']['api_key']:
@ -567,8 +686,8 @@ def movies(list_type, add_limit=0, add_delay=2.5, sort='votes', rating=None, gen
try: try:
# check if genre matches genre supplied via argument # check if genre matches genre supplied via argument
if genre and not misc_helper.allowed_genres(genre, 'movie', sorted_movie): if genre and not misc_helper.allowed_genres(genre, 'movie', sorted_movie):
log.debug("Skipping: %s because it was not from %s genre(s)", sorted_movie['movie']['title'], log.debug("Skipping: \'%s\' because it was not from genre: %s", sorted_movie['movie']['title'],
genre.lower()) genre.title())
continue continue
# check if movie passes out blacklist criteria inspection # check if movie passes out blacklist criteria inspection
@ -580,28 +699,35 @@ def movies(list_type, add_limit=0, add_delay=2.5, sort='votes', rating=None, gen
if rating is not None and 'omdb' in cfg and 'api_key' in cfg['omdb'] and cfg['omdb']['api_key']: if rating is not None and 'omdb' in cfg and 'api_key' in cfg['omdb'] and cfg['omdb']['api_key']:
movie_rating = rating_helper.get_rating(cfg['omdb']['api_key'], sorted_movie) movie_rating = rating_helper.get_rating(cfg['omdb']['api_key'], sorted_movie)
if movie_rating == -1: if movie_rating == -1:
log.info("SKIPPED \'%s (%d)\'", sorted_movie['movie']['title'], sorted_movie['movie']['year']) log.info("SKIPPED: \'%s (%s)\'", sorted_movie['movie']['title'],
str(sorted_movie['movie']['year']) if sorted_movie['movie']['year'] else '????')
continue continue
if (rating is None or movie_rating is None) or movie_rating >= rating: if (rating is None or movie_rating is None) or movie_rating >= rating:
log.info("Adding: \'%s (%d)\' | Genres: %s | Country: %s", sorted_movie['movie']['title'], log.info("Adding: \'%s (%s)\' | Country: %s | Language: %s | Genre: %s ",
sorted_movie['movie']['year'], sorted_movie['movie']['title'],
(', '.join(sorted_movie['movie']['genres']) if sorted_movie['movie']['genres'] else 'N/A'), str(sorted_movie['movie']['year']) if sorted_movie['movie']['year'] else '????',
(sorted_movie['movie']['country'] or 'N/A').upper()) (sorted_movie['movie']['country'] or 'N/A').upper(),
(sorted_movie['movie']['language'] or 'N/A').upper(),
(', '.join(sorted_movie['movie']['genres'])).title()
if sorted_movie['movie']['genres'] else 'N/A')
# add movie to radarr # add movie to radarr
if radarr.add_movie(sorted_movie['movie']['ids']['tmdb'], sorted_movie['movie']['title'], if radarr.add_movie(sorted_movie['movie']['ids']['tmdb'], sorted_movie['movie']['title'],
sorted_movie['movie']['year'], sorted_movie['movie']['ids']['slug'], profile_id, str(sorted_movie['movie']['year']) if sorted_movie['movie']['year'] else '????',
sorted_movie['movie']['ids']['slug'], profile_id,
cfg.radarr.root_folder, cfg.radarr.minimum_availability, not no_search): cfg.radarr.root_folder, cfg.radarr.minimum_availability, not no_search):
log.info("ADDED \'%s (%d)\'", sorted_movie['movie']['title'], sorted_movie['movie']['year']) log.info("ADDED: \'%s (%s)\'", sorted_movie['movie']['title'],
str(sorted_movie['movie']['year']) if sorted_movie['movie']['year'] else '????')
if notifications: if notifications:
callback_notify({'event': 'add_movie', 'list_type': list_type, callback_notify({'event': 'add_movie', 'list_type': list_type,
'movie': sorted_movie['movie']}) 'movie': sorted_movie['movie']})
added_movies += 1 added_movies += 1
else: else:
log.error("FAILED adding \'%s (%d)\'", sorted_movie['movie']['title'], log.error("FAILED ADDING: \'%s (%s)\'", sorted_movie['movie']['title'],
sorted_movie['movie']['year']) str(sorted_movie['movie']['year']) if sorted_movie['movie']['year'] else '????')
else: else:
log.debug("Minimum Rotten Tomatoes score of %d%% was not met.", rating) log.debug("Minimum Rotten Tomatoes score of %d%% was not met.", rating)
log.info("SKIPPED \'%s (%d)\'", sorted_movie['movie']['title'], sorted_movie['movie']['year']) log.info("SKIPPED: \'%s (%s)\'", sorted_movie['movie']['title'],
str(sorted_movie['movie']['year']) if sorted_movie['movie']['year'] else '????')
# stop adding movies, if added_movies >= add_limit # stop adding movies, if added_movies >= add_limit
if add_limit and added_movies >= add_limit: if add_limit and added_movies >= add_limit:
break break
@ -610,13 +736,13 @@ def movies(list_type, add_limit=0, add_delay=2.5, sort='votes', rating=None, gen
time.sleep(add_delay) time.sleep(add_delay)
except Exception: except Exception:
log.exception("Exception while processing movie %s: ", sorted_movie['movie']['title']) log.exception("Exception while processing movie \'%s\': ", sorted_movie['movie']['title'])
log.info("Added %d new movie(s) to Radarr", added_movies) log.info("Added %d new movie(s) to Radarr", added_movies)
# send notification # send notification
if notifications and (cfg.notifications.verbose or added_movies > 0): 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)) notify.send(message="Added %d movie(s) from Trakt's \'%s\' list" % (added_movies, list_type.capitalize()))
return added_movies return added_movies
@ -636,12 +762,13 @@ def callback_remove_recommended(media_type, media_info):
media_info) media_info)
return return
media_name = '\'%s (%d)\'' % (media_info[media_type]['title'], media_info[media_type]['year']) media_name = '\'%s (%s)\'' % (media_info[media_type]['title'],
str(media_info[media_type]['year']) if media_info[media_type]['year'] else '????')
if trakt.remove_recommended_item(media_type, media_info[media_type]['ids']['trakt']): if trakt.remove_recommended_item(media_type, media_info[media_type]['ids']['trakt']):
log.info("Removed rejected recommended %s: %s", media_type, media_name) log.info("Removed rejected recommended %s: \'%s\'", media_type, media_name)
else: else:
log.info("FAILED removing rejected recommended %s: %s", media_type, media_name) log.info("FAILED removing rejected recommended %s: \'%s\'", media_type, media_name)
def callback_notify(data): def callback_notify(data):
@ -651,15 +778,20 @@ def callback_notify(data):
if data['event'] == 'add_movie': if data['event'] == 'add_movie':
if cfg.notifications.verbose: if cfg.notifications.verbose:
notify.send( notify.send(
message="Added %s movie: \'%s (%d)\'" % (data['list_type'], data['movie']['title'], data['movie']['year'])) message="Added \'%s\' movie: \'%s (%s)\'" % (data['list_type'].capitalize(), data['movie']['title'],
str(data['movie']['year'])
if data['movie']['year'] else '????'))
return return
elif data['event'] == 'add_show': elif data['event'] == 'add_show':
if cfg.notifications.verbose: if cfg.notifications.verbose:
notify.send( notify.send(
message="Added %s show: \'%s (%d)\'" % (data['list_type'], data['show']['title'], data['show']['year'])) message="Added \'%s\' show: \'%s (%s)\'" % (data['list_type'].capitalize(), data['show']['title'],
str(data['movie']['year'])
if data['movie']['year'] else '????'))
return return
elif data['event'] == 'abort': elif data['event'] == 'abort':
notify.send(message="Aborted adding Trakt %s %s due to: %s" % (data['list_type'], data['type'], data['reason'])) notify.send(message="Aborted adding Trakt \'%s\' %s due to: %s" % (data['list_type'].capitalize(), data['type'],
data['reason']))
return return
elif data['event'] == 'error': elif data['event'] == 'error':
notify.send(message="Error: %s" % data['reason']) notify.send(message="Error: %s" % data['reason'])
@ -697,10 +829,10 @@ def automatic_shows(add_delay=2.5, sort='votes', no_search=False, notifications=
limit = value limit = value
if limit <= 0: if limit <= 0:
log.info("Skipped Trakt's %s shows list", list_type) log.info("Skipped Trakt's \'%s\' shows list", list_type.capitalize())
continue continue
else: else:
log.info("Adding %d shows from Trakt's %s list", limit, list_type) log.info("Adding %d show(s) from Trakt's \'%s\' list", limit, list_type.capitalize())
local_ignore_blacklist = ignore_blacklist local_ignore_blacklist = ignore_blacklist
@ -714,10 +846,11 @@ def automatic_shows(add_delay=2.5, sort='votes', no_search=False, notifications=
elif list_type.lower() == 'watchlist': elif list_type.lower() == 'watchlist':
for authenticate_user, limit in value.items(): for authenticate_user, limit in value.items():
if limit <= 0: if limit <= 0:
log.info("Skipped Trakt's %s for %s", list_type, authenticate_user) log.info("Skipped Trakt user \'%s\''s \'%s\'", authenticate_user, list_type.capitalize)
continue continue
else: else:
log.info("Adding %d shows from the %s from %s", limit, list_type, authenticate_user) log.info("Adding %d show(s) from Trakt user \'%s\''s \'%s\'", limit, authenticate_user,
list_type.capitalize)
local_ignore_blacklist = ignore_blacklist local_ignore_blacklist = ignore_blacklist
@ -750,7 +883,7 @@ def automatic_shows(add_delay=2.5, sort='votes', no_search=False, notifications=
ignore_blacklist=local_ignore_blacklist) ignore_blacklist=local_ignore_blacklist)
if added_shows is None: if added_shows is None:
log.error("Failed adding shows from Trakt's %s list", list_type) log.error("Failed adding shows from Trakt's \'%s\' list", list_type)
time.sleep(10) time.sleep(10)
continue continue
total_shows_added += added_shows total_shows_added += added_shows
@ -758,10 +891,10 @@ def automatic_shows(add_delay=2.5, sort='votes', no_search=False, notifications=
# sleep # sleep
time.sleep(10) time.sleep(10)
log.info("Finished, added %d shows total to Sonarr!", total_shows_added) log.info("Finished, added %d show(s) total to Sonarr!", total_shows_added)
# send notification # send notification
if notifications and (cfg.notifications.verbose or total_shows_added > 0): if notifications and (cfg.notifications.verbose or total_shows_added > 0):
notify.send(message="Added %d shows total to Sonarr!" % total_shows_added) notify.send(message="Added %d show(s) total to Sonarr!" % total_shows_added)
except Exception: except Exception:
log.exception("Exception while automatically adding shows: ") log.exception("Exception while automatically adding shows: ")
@ -792,10 +925,10 @@ def automatic_movies(add_delay=2.5, sort='votes', no_search=False, notifications
limit = value limit = value
if limit <= 0: if limit <= 0:
log.info("Skipped Trakt's %s movies list", list_type) log.info("Skipped Trakt's \'%s\' movies list", list_type.capitalize())
continue continue
else: else:
log.info("Adding %d movies from Trakt's %s list", limit, list_type) log.info("Adding %d movie(s) from Trakt's \'%s\' list", limit, list_type.capitalize())
local_ignore_blacklist = ignore_blacklist local_ignore_blacklist = ignore_blacklist
@ -810,10 +943,11 @@ def automatic_movies(add_delay=2.5, sort='votes', no_search=False, notifications
elif list_type.lower() == 'watchlist': elif list_type.lower() == 'watchlist':
for authenticate_user, limit in value.items(): for authenticate_user, limit in value.items():
if limit <= 0: if limit <= 0:
log.info("Skipped Trakt's %s for %s", list_type, authenticate_user) log.info("Skipped Trakt user \'%s\''s \'%s\'", authenticate_user, list_type.capitalize)
continue continue
else: else:
log.info("Adding %d movies from the %s from %s", limit, list_type, authenticate_user) log.info("Adding %d movie(s) from Trakt user \'%s\''s \'%s\'", limit,
authenticate_user, list_type.capitalize())
local_ignore_blacklist = ignore_blacklist local_ignore_blacklist = ignore_blacklist
@ -846,7 +980,7 @@ def automatic_movies(add_delay=2.5, sort='votes', no_search=False, notifications
ignore_blacklist=local_ignore_blacklist, rating=rating_limit) ignore_blacklist=local_ignore_blacklist, rating=rating_limit)
if added_movies is None: if added_movies is None:
log.error("Failed adding movies from Trakt's %s list", list_type) log.error("Failed adding movies from Trakt's \'%s\' list", list_type.capitalize())
time.sleep(10) time.sleep(10)
continue continue
total_movies_added += added_movies total_movies_added += added_movies
@ -854,10 +988,10 @@ def automatic_movies(add_delay=2.5, sort='votes', no_search=False, notifications
# sleep # sleep
time.sleep(10) time.sleep(10)
log.info("Finished, added %d movies total to Radarr!", total_movies_added) log.info("Finished, added %d movie(s) total to Radarr!", total_movies_added)
# send notification # send notification
if notifications and (cfg.notifications.verbose or total_movies_added > 0): if notifications and (cfg.notifications.verbose or total_movies_added > 0):
notify.send(message="Added %d movies total to Radarr!" % total_movies_added) notify.send(message="Added %d movie(s) total to Radarr!" % total_movies_added)
except Exception: except Exception:
log.exception("Exception while automatically adding movies: ") log.exception("Exception while automatically adding movies: ")
@ -865,14 +999,33 @@ def automatic_movies(add_delay=2.5, sort='votes', no_search=False, notifications
@app.command(help='Run Traktarr in automatic mode.') @app.command(help='Run Traktarr in automatic mode.')
@click.option('--add-delay', '-d', default=2.5, help='Seconds between each add request to Sonarr / Radarr.', @click.option(
'--add-delay', '-d',
default=2.5,
help='Seconds between each add request to Sonarr / Radarr.',
show_default=True) show_default=True)
@click.option('--sort', '-s', default='votes', type=click.Choice(['votes', 'rating', 'release']), @click.option(
help='Sort list to process.', show_default=True) '--sort', '-s',
@click.option('--no-search', is_flag=True, help='Disable search when adding to Sonarr / Radarr.') default='votes',
@click.option('--run-now', is_flag=True, help="Do a first run immediately without waiting.") type=click.Choice(['votes', 'rating', 'release']),
@click.option('--no-notifications', is_flag=True, help="Disable notifications.") help='Sort list to process.',
@click.option('--ignore-blacklist', is_flag=True, help='Ignores the blacklist when running the command.') show_default=True)
@click.option(
'--no-search',
is_flag=True,
help='Disable search when adding to Sonarr / Radarr.')
@click.option(
'--run-now',
is_flag=True,
help="Do a first run immediately without waiting.")
@click.option(
'--no-notifications',
is_flag=True,
help="Disable notifications.")
@click.option(
'--ignore-blacklist',
is_flag=True,
help='Ignores the blacklist when running the command.')
def run(add_delay=2.5, sort='votes', no_search=False, run_now=False, no_notifications=False, ignore_blacklist=False): def run(add_delay=2.5, sort='votes', no_search=False, run_now=False, no_notifications=False, ignore_blacklist=False):
log.info("Automatic mode is now running.") log.info("Automatic mode is now running.")

Loading…
Cancel
Save