diff --git a/.github/ISSUE_TEMPLATE/BUG_REPORT.md b/.github/ISSUE_TEMPLATE/BUG_REPORT.md index 6ebe39b..08617db 100644 --- a/.github/ISSUE_TEMPLATE/BUG_REPORT.md +++ b/.github/ISSUE_TEMPLATE/BUG_REPORT.md @@ -23,7 +23,13 @@ If applicable, add screenshots to help explain your problem. **Logs** Link to debug or trace log files. -You can enable debug mode with `core.debug` in the `config.json` file. +You can enable debug mode with `core.debug` in the `config.json` file: + +```json + "core": { + "debug": true + }, +``` **System Information** diff --git a/DONATIONS.md b/DONATIONS.md new file mode 100644 index 0000000..a285aff --- /dev/null +++ b/DONATIONS.md @@ -0,0 +1,11 @@ +# Donations + +If you find this project helpful, feel free to make a small donation to the developer. + + - [GitHub Sponsor](https://github.com/sponsors/l3uddz) + + - [Monzo](https://monzo.me/jamesbayliss9): Credit Cards, Apple Pay, Google Pay + + - [Paypal: l3uddz@gmail.com](https://www.paypal.me/l3uddz) + + - BTC: 3CiHME1HZQsNNcDL6BArG7PbZLa8zUUgjL diff --git a/README.md b/README.md index ba02e1a..464f5ac 100644 --- a/README.md +++ b/README.md @@ -5,7 +5,7 @@ [![last commit (develop)](https://img.shields.io/github/last-commit/l3uddz/traktarr/develop.svg?colorB=177DC1&label=Last%20Commit&style=flat-square)](https://github.com/l3uddz/traktarr/commits/develop) [![Discord](https://img.shields.io/discord/381077432285003776.svg?colorB=177DC1&label=Discord&style=flat-square)](https://discord.io/cloudbox) [![Contributing](https://img.shields.io/badge/Contributing-gray.svg?style=flat-square)](CONTRIBUTING.md) -[![Donate](https://img.shields.io/badge/Donate-gray.svg?style=flat-square)](#donate) +[![Donate](https://img.shields.io/badge/Donate-gray.svg?style=flat-square)](DONATIONS.md) --- @@ -36,7 +36,6 @@ - [Slack](#slack) - [Radarr](#radarr) - [Sonarr](#sonarr) - - [Tags](#tags) - [Trakt](#trakt) - [OMDb](#omdb) - [Usage](#usage) @@ -335,7 +334,7 @@ You can repeat this process for as many users as you like. "language": "English", "quality": "HD-1080p", "root_folder": "/tv/", - "tags": {}, + "tags": [], "url": "http://localhost:8989/" }, "trakt": { @@ -603,7 +602,7 @@ Use filters to specify the movie/shows's country of origin or blacklist (i.e. fi - Blank list (i.e. `[]`) - Add movies from any country. - - `ignore` (i.e. `["ignore"]`) Add movies from any country, including ones with no country specified. + - `ignore` (i.e. `["ignore"]`) - Add movies from any country, including ones with no country specified. `allowed_languages` - Only add movies with these languages. Listed as two-letter language codes. @@ -613,7 +612,9 @@ Use filters to specify the movie/shows's country of origin or blacklist (i.e. fi - Special keywords: - - Blank list (i.e. `[]`) - Only add shows that are in English (`en`). + - Blank list (i.e. `[]`) - Add movies with any language. + + - `ignore` (i.e. `["ignore"]`) - Add movies with any language, including ones with no language specified. `blacklisted_genres` - Blacklist certain genres. @@ -633,9 +634,17 @@ Use filters to specify the movie/shows's country of origin or blacklist (i.e. fi - Has to be longer than `blacklisted_min_runtime` or else it will be ignored. -`blacklisted_min_year` - Blacklist release dates before specified year. +`blacklisted_min_year` - Blacklist release dates before specified year. This can be a 4 digit year, `0`, or `-` format. + +- If `0`, blacklist movies that came out before the current year. + +- If `-10`, blacklist movies that came out 10 years before the current year. -`blacklisted_max_year` - Blacklist release dates after specified year. +`blacklisted_max_year` - Blacklist release dates after specified year. This can be a 4 digit year, `0`, or `+` format. + +- If `0`, blacklist movies that are coming out after the current year. + +- If `+1`, blacklist movies that are coming out after 1 year from current year. `blacklisted_title_keywords` - Blacklist certain words in titles. @@ -721,7 +730,7 @@ Use filters to specify the movie/shows's country of origin or blacklist (i.e. fi - Blank list (i.e. `[]`) - Add shows from any country. - - `ignore` (i.e. `["ignore"]`) Add shows from any country, including ones with no country specified. + - `ignore` (i.e. `["ignore"]`) - Add shows from any country, including ones with no country specified. `allowed_languages` - Only add shows with these languages. @@ -731,8 +740,10 @@ Use filters to specify the movie/shows's country of origin or blacklist (i.e. fi - Special keywords: - - Blank list (i.e. `[]`) - Only add shows that are in English (`en`). + - Blank list (i.e. `[]`) - Add shows with any language. + - `ignore` (i.e. `["ignore"]`) - Add shows with any language, including ones with no language specified. + `blacklisted_genres` - Blacklist certain genres. - [List of available TV show genres](assets/list_of_tv_show_genres.md). @@ -753,9 +764,17 @@ Use filters to specify the movie/shows's country of origin or blacklist (i.e. fi - Has to be longer than `blacklisted_min_runtime` or else it will be ignored. -`blacklisted_min_year` - Blacklist release dates before specified year. +`blacklisted_min_year` - Blacklist release dates before specified year. This can be a 4 digit year, `0`, or `-` format. + +- If `0`, blacklist shows that came out before the current year. -`blacklisted_max_year` - Blacklist release dates after specified year. +- If `-10`, blacklist shows that came out 10 years before the current year. + +`blacklisted_max_year` - Blacklist release dates after specified year. This can be a 4 digit year, `0`, or `+` format. + +- If `0`, blacklist shows that are coming out after the current year. + +- If `+1`, blacklist shows that are coming out after 1 year from current year. `blacklisted_title_keywords` - Blacklist certain words in titles. @@ -962,7 +981,7 @@ Sonarr configuration. "language": "English", "quality": "HD-1080p", "root_folder": "/tv/", - "tags": {}, + "tags": [], "url": "http://localhost:8989" }, ``` @@ -975,55 +994,29 @@ Sonarr configuration. `root_folder` - Root folder for TV shows. -`tags` - Assign tags to shows based the network it airs on. More details on this below. +`tags` - Assign tags to shows. Tags need to be created in Sonarr first. + - Examples: + + ```json + "tags": ["anime"] + ``` + + ```json + "tags": ["anime", "jap"] + ``` + + ```json + "tags": [ + "anime", + "jap" + ] + ``` + `url` - Sonarr's URL. - Note: If you have URL Base enabled in Sonarr's settings, you will need to add that into the URL as well. -### Tags - -The `tags` option allows Sonarr to assign tags to shows from specific television networks, so that Sonarr can filter in/out certain keywords from releases. - -**Example:** - -To show how tags work, we will create a tag `AMZN` and assign it to certain television networks that usually have AMZN releases. - -1. First, we will create a tag in Sonarr (Settings > Indexers > Restrictions). - - ``` - Must contain: BluRay, Amazon, AMZN - Must not contain: - Tags: AMZN - ``` - -2. And, finally, we will edit the Traktarr config and assign the `AMZN` tag to some networks. - - ```json - "tags": { - "amzn": [ - "hbo", - "amc", - "usa network", - "tnt", - "starz", - "the cw", - "fx", - "fox", - "abc", - "nbc", - "cbs", - "tbs", - "amazon", - "syfy", - "cinemax", - "bravo", - "showtime", - "paramount network" - ] - } - ``` - ## Trakt Trakt Authentication info: @@ -1214,6 +1207,8 @@ Options: -s, --sort [rating|release|votes] Sort list to process. [default: votes] -rt, --rotten_tomatoes INTEGER Set a minimum Rotten Tomatoes score. + -y, --year, --years TEXT Can be a specific year or a range of years to search. For + example, '2000' or '2000-2010'. -g, --genres TEXT Only add movies from this genre to Radarr. Multiple genres are specified as a comma-separated list. Use 'ignore' to add movies from any genre, including ones with no genre specified. @@ -1221,10 +1216,11 @@ Options: -ma, --minimum-availability [announced|in_cinemas|released|predb] Add movies with this minimum availability to Radarr. Default is 'released'. - -a, --actor TEXT Only add movies from this actor to Radarr.Only one actor can be - specified.Requires the 'person' list. - --include-non-acting-roles Include non-acting roles such as 'As Himself', 'Narrator', etc. - Requires the 'person' list option with the 'actor' argument. + -p, --person TEXT Only add movies from this person (e.g. actor) to Radarr. Only + one person can be specified. Requires the 'person' list type. + --include-non-acting-roles Include non-acting roles such as 'Director', 'As Himself', + 'Narrator', etc. Requires the 'person' list type with the + 'person' argument. --no-search Disable search when adding movies to Radarr. --notifications Send notifications. --authenticate-user TEXT Specify which user to authenticate with to retrieve Trakt lists. @@ -1275,6 +1271,10 @@ Choices are: `anticipated`, `trending`, `popular`, `boxoffice`, `watched`, `play - Example: `-rt 75` +`-y`, `--year`, `--years` - Only add movies from from a specific year or range of years. + + - Examples: `-y 2010`, `--years 2010-2020` + `-g`, `--genres` - Only add movies from these genre(s) to Radarr. - Multiple genres are passed as comma-separated lists. The effect of this is equivalent of boolean OR. (ie. include items from any of these genres). @@ -1291,13 +1291,13 @@ Choices are: `anticipated`, `trending`, `popular`, `boxoffice`, `watched`, `play - Default is `released` (Physical/Web). -`-a`, `--actor` - Only add movies with a specific actor to Radarr. +`-p`, `--person` - Only add movies with a specific person to Radarr. - Requires the list type `person`. -`--include-non-acting-roles` - Include non-acting roles of the specified actor. +`--include-non-acting-roles` - Include non-acting roles of the specified person. - - Requires the list type `person` used with the `-a`/`--actor` option. + - Requires the list type `person` used with the `-p`/`--person` option. `--no-search` - Tells Radarr to not automatically search for added movies. @@ -1347,24 +1347,24 @@ Usage: traktarr shows [OPTIONS] Add multiple shows to Sonarr. Options: - -t, --list-type TEXT Trakt list to process. - For example, 'anticipated', 'trending', + -t, --list-type TEXT Trakt list to process. For example, 'anticipated', 'trending', 'popular', 'person', 'watched', 'played', 'recommended', 'watchlist', or any URL to a list. [required] -l, --add-limit INTEGER Limit number of shows added to Sonarr. -d, --add-delay FLOAT Seconds between each add request to Sonarr. [default: 2.5] -s, --sort [rating|release|votes] Sort list to process. [default: votes] + -y, --year, --years TEXT Can be a specific year or a range of years to search. For + example, '2000' or '2000-2010'. -g, --genres TEXT Only add shows from this genre to Sonarr. Multiple genres are - specified as a comma-separated list. - Use 'ignore' to add shows + specified as a comma-separated list. Use 'ignore' to add shows from any genre, including ones with no genre specified. -f, --folder TEXT Add shows with this root folder to Sonarr. - -a, --actor TEXT Only add movies from this actor to Radarr. Only one actor can be - specified. - Requires the 'person' list option. - --include-non-acting-roles Include non-acting roles such as 'As Himself', 'Narrator', etc. - Requires the 'person' list option with the 'actor' argument. + -p, --person TEXT Only add shows from this person (e.g. actor) to Sonarr. Only one + person can be specified. Requires the 'person' list type. + --include-non-acting-roles Include non-acting roles such as 'Director', 'As Himself', + 'Narrator', etc. Requires the 'person' list type with the + 'person' argument. --no-search Disable search when adding shows to Sonarr. --notifications Send notifications. --authenticate-user TEXT Specify which user to authenticate with to retrieve Trakt lists. @@ -1412,6 +1412,10 @@ Choices are: `anticipated`, `trending`, `popular`, `watched`, `played`, `URL` (T - Example: `-s release` +`-y`, `--year`, `--years` - Only add shows from from a specific year or range of years. + + - Examples: `-y 2010`, `--years 2010-2020` + `-g`, `--genres` - Only add shows from this genre(s) to Sonarr. - Multiple genres are passed as comma-separated lists. The effect of this is equivalent of boolean OR. (ie. include items from any of these genres). @@ -1422,13 +1426,13 @@ Choices are: `anticipated`, `trending`, `popular`, `watched`, `played`, `URL` (T - Example: `-f /mnt/unionfs/Media/Shows/Shows-Kids/` -`-a`, `--actor` - Only add shows with a specific actor to Sonarr. +`-p`, `--person` - Only add shows with a specific person to Sonarr. - Requires the list type `person`. -`--include-non-acting-roles` - Include non-acting roles of the specified actor. +`--include-non-acting-roles` - Include non-acting roles of the specified person. - - Requires the list type `person` used with the `-a`/`--actor` option. + - Requires the list type `person` used with the `-p`/`--person` option. `--no-search` - Tells Sonarr to not automatically search for added shows. @@ -1493,6 +1497,12 @@ Choices are: `anticipated`, `trending`, `popular`, `watched`, `played`, `URL` (T traktarr movies -t trending -rt 80 ``` +- Add movies, from the trending list, from the year 2020. + + ``` + traktarr movies -t trending -y 2020 + ``` + - Add movies, with actor 'Keanu Reeves', limited to 10 items. ``` @@ -1547,18 +1557,4 @@ Choices are: `anticipated`, `trending`, `popular`, `watched`, `played`, `URL` (T ``` traktarr shows -t watchlist --authenticate-user user1 - ``` - -*** - -# Donate - -If you find this project helpful, feel free to make a small donation to the developer: - - - [Monzo](https://monzo.me/jamesbayliss9): Credit Cards, Apple Pay, Google Pay - - - [Beerpay](https://beerpay.io/l3uddz/traktarr): Credit Cards - - - [Paypal: l3uddz@gmail.com](https://www.paypal.me/l3uddz) - - - BTC: 3CiHME1HZQsNNcDL6BArG7PbZLa8zUUgjL + ``` \ No newline at end of file diff --git a/helpers/parameter.py b/helpers/parameter.py new file mode 100644 index 0000000..ae0679e --- /dev/null +++ b/helpers/parameter.py @@ -0,0 +1,55 @@ +import time +import re +import operator + + +def years(param_years: str, config_min_year: int, config_max_year: int): + + def operations(_year): + _year = str(_year) + current_year = time.localtime().tm_year + ops = {"+": operator.add, "-": operator.sub} # https://stackoverflow.com/a/1740759 + + if r1.match(_year): + return int(_year) + elif _year == '0': + return current_year + # add/subtract value from year + elif r3.match(_year): + _year_op = _year[0:1] + _year_value = int(_year[1:]) + return ops[_year_op](current_year, _year_value) + else: + return None + + r1 = re.compile('^[0-9]{4}$') + r2 = re.compile('^[0-9]{4}-[0-9]{4}$') + r3 = re.compile('^[+|-][0-9]+$') + + # return param_years if it is in proper format + if param_years: + if r1.match(param_years): + return str(param_years), int(param_years), int(param_years) + elif r2.match(param_years): + return str(param_years), int(param_years.split('-')[0]), int(param_years.split('-')[1]) + + if config_min_year is not None: + new_min_year = operations(config_min_year) + else: + new_min_year = None + + if config_max_year is not None: + new_max_year = operations(config_max_year) + else: + new_max_year = None + + if new_min_year and new_max_year: + new_years = str(new_min_year) + '-' + str(new_max_year) + elif new_min_year: + new_years = str(new_min_year) + elif new_max_year: + new_years = str(new_max_year) + else: + new_years = None + + return new_years, new_min_year, new_max_year diff --git a/helpers/radarr.py b/helpers/radarr.py index efa57f4..51c753f 100644 --- a/helpers/radarr.py +++ b/helpers/radarr.py @@ -35,7 +35,7 @@ def movies_to_tmdb_dict(radarr_movies): return None -def remove_existing_movies(radarr_movies, trakt_movies, callback=None): +def remove_existing_movies_from_trakt_list(radarr_movies, trakt_movies, callback=None): new_movies_list = [] try: @@ -49,7 +49,7 @@ def remove_existing_movies(radarr_movies, trakt_movies, callback=None): # check if movie exists in processed_movies if tmp['movie']['ids']['tmdb'] in processed_movies: movie_year = str(tmp['movie']['year']) if tmp['movie']['year'] else '????' - log.debug("Removing existing movie: \'%s (%s)\'", tmp['movie']['title'], movie_year) + log.debug("Removing existing movie from Trakt list: \'%s (%s)\'", tmp['movie']['title'], movie_year) if callback: callback('movie', tmp) continue @@ -81,7 +81,7 @@ def exclusions_to_tmdb_dict(radarr_exclusions): return None -def remove_existing_exclusions(radarr_exclusions, trakt_movies, callback=None): +def remove_excluded_movies_from_trakt_list(radarr_exclusions, trakt_movies, callback=None): new_movies_list = [] try: @@ -95,7 +95,7 @@ def remove_existing_exclusions(radarr_exclusions, trakt_movies, callback=None): # check if movie exists in processed_movies if tmp['movie']['ids']['tmdb'] in processed_movies: movie_year = str(tmp['movie']['year']) if tmp['movie']['year'] else '????' - log.debug("Removing excluded movie: \'%s (%s)\'", tmp['movie']['title'], movie_year) + log.debug("Removing excluded movie from Trakt list: \'%s (%s)\'", tmp['movie']['title'], movie_year) if callback: callback('movie', tmp) continue @@ -110,7 +110,7 @@ def remove_existing_exclusions(radarr_exclusions, trakt_movies, callback=None): return None -def remove_existing_and_excluded_movies(radarr_movies, radarr_exclusions, trakt_movies, callback=None): +def remove_existing_and_excluded_movies_from_trakt_list(radarr_movies, radarr_exclusions, trakt_movies, callback=None): if not radarr_movies or not trakt_movies: log.error("Inappropriate parameters were supplied.") return None, False @@ -122,13 +122,15 @@ def remove_existing_and_excluded_movies(radarr_movies, radarr_exclusions, trakt_ return None, False # filter out existing movies in radarr from new trakt list - processed_movies_list, removal_successful = remove_existing_movies(radarr_movies, trakt_movies, callback) + processed_movies_list, removal_successful = remove_existing_movies_from_trakt_list(radarr_movies, trakt_movies, + callback) if not processed_movies_list: return None, removal_successful # filter out radarr exclusions from the list above if radarr_exclusions: - processed_movies_list = remove_existing_exclusions(radarr_exclusions, processed_movies_list, callback) + processed_movies_list = remove_excluded_movies_from_trakt_list(radarr_exclusions, processed_movies_list, + callback) movies_removed_count = len(trakt_movies) - len(processed_movies_list) log.debug("Filtered a total of %d movies from the Trakt movies list.", movies_removed_count) diff --git a/helpers/sonarr.py b/helpers/sonarr.py index bfe56c8..d8c2506 100644 --- a/helpers/sonarr.py +++ b/helpers/sonarr.py @@ -3,22 +3,21 @@ from misc.log import logger log = logger.get_logger(__name__) -def series_tag_id_from_network(profile_tags, network_tags, network): +def series_tag_ids_list_builder(profile_tags, config_tags): try: - tags = [] - for tag_name, tag_networks in network_tags.items(): - for tag_network in tag_networks: - if tag_network.lower() in network.lower() and tag_name.lower() in profile_tags: - log.debug("Using %s tag for network: %s", tag_name, network) - tags.append(profile_tags[tag_name.lower()]) - if tags: - return tags + tag_ids = [] + for tag_name in config_tags: + if tag_name.lower() in profile_tags: + log.debug("Validated Tag: %s", tag_name) + tag_ids.append(profile_tags[tag_name.lower()]) + if tag_ids: + return tag_ids except Exception: - log.exception("Exception determining tag to use for network %s: ", network) + log.exception("Exception building Tags IDs list") return None -def readable_tag_from_ids(profile_tag_ids, chosen_tag_ids): +def series_tag_names_list_builder(profile_tag_ids, chosen_tag_ids): try: if not chosen_tag_ids: return None @@ -30,7 +29,7 @@ def readable_tag_from_ids(profile_tag_ids, chosen_tag_ids): if tags: return tags except Exception: - log.exception("Exception building readable tag name list from ids %s: ", chosen_tag_ids) + log.exception("Exception building Tag Names list from Tag IDs %s: ", chosen_tag_ids) return None @@ -65,7 +64,7 @@ def series_to_tvdb_dict(sonarr_series): return None -def remove_existing_series(sonarr_series, trakt_series, callback=None): +def remove_existing_series_from_trakt_list(sonarr_series, trakt_series, callback=None): new_series_list = [] if not sonarr_series or not trakt_series: @@ -88,7 +87,7 @@ def remove_existing_series(sonarr_series, trakt_series, callback=None): # check if show exists in processed_series if tmp['show']['ids']['tvdb'] in processed_series: show_year = str(tmp['show']['year']) if tmp['show']['year'] else '????' - log.debug("Removing existing show: \'%s (%s)\'", tmp['show']['title'], show_year) + log.debug("Removing existing show from Trakt list: \'%s (%s)\'", tmp['show']['title'], show_year) if callback: callback('show', tmp) continue diff --git a/helpers/trakt.py b/helpers/trakt.py index 1e88011..f4b9d31 100644 --- a/helpers/trakt.py +++ b/helpers/trakt.py @@ -122,9 +122,6 @@ def blacklisted_show_country(show, allowed_countries): def blacklisted_show_language(show, allowed_languages): blacklisted = False - # [] - add show items with 'en' language - if not allowed_languages: - allowed_languages = ['en'] try: # ["ignore"] - add show item even if it is missing a language if any('ignore' in s.lower() for s in allowed_languages): @@ -134,6 +131,10 @@ def blacklisted_show_language(show, allowed_languages): log.debug("\'%s\' | Blacklisted Languages Check | Blacklisted because it had no language specified.", show['show']['title']) blacklisted = True + # [] - add show item from any valid language + elif not allowed_languages: + log.debug("\'%s\' | Blacklisted Languages Check | Skipped.", + show['show']['title']) # List provided - skip adding show item if the language is blacklisted elif not any(show['show']['language'].lower() in c.lower() for c in allowed_languages): log.debug("\'%s\' | Blacklisted Languages Check | Blacklisted because it's in the language: %s", @@ -308,9 +309,6 @@ def blacklisted_movie_country(movie, allowed_countries): def blacklisted_movie_language(movie, allowed_languages): blacklisted = False - # [] - add movie items with 'en' language - if not allowed_languages: - allowed_languages = ['en'] try: # ["ignore"] - add movie item even if it is missing a language if any('ignore' in s.lower() for s in allowed_languages): @@ -321,6 +319,10 @@ def blacklisted_movie_language(movie, allowed_languages): log.debug("\'%s\' | Blacklisted Languages Check | Blacklisted because it had no language specified.", movie['movie']['title']) blacklisted = True + # [] - add movie item from any valid language + elif not allowed_languages: + log.debug("\'%s\' | Blacklisted Languages Check | Skipped.", + movie['movie']['title']) # List provided - skip adding movie item if the language is blacklisted elif not any(movie['movie']['language'].lower() in s.lower() for s in allowed_languages): log.debug("\'%s\' | Blacklisted Languages Check | Blacklisted because it's in the language: %s", diff --git a/media/radarr.py b/media/radarr.py index ffc62b4..85dc740 100644 --- a/media/radarr.py +++ b/media/radarr.py @@ -31,7 +31,7 @@ class Radarr(PVR): payload = dict_merge(payload, { 'tmdbId': movie_tmdb_id, - 'year': movie_year, + 'year': int(movie_year), 'minimumAvailability': minimum_availability, 'addOptions': { 'searchForMovie': search_missing diff --git a/media/trakt.py b/media/trakt.py index 578ede5..c8cf7e7 100644 --- a/media/trakt.py +++ b/media/trakt.py @@ -100,18 +100,16 @@ class Trakt: if payload is None: payload = {} - # languages list - if not languages: - languages = ['en'] - languages = ','.join(languages).lower() - payload = dict_merge(payload, { 'extended': 'full', 'limit': limit, 'page': 1, - 'languages': languages, }) + # languages list + if languages: + payload['languages'] = ','.join(languages).lower() + # years range if years: payload['years'] = years diff --git a/misc/config.py b/misc/config.py index bc9376f..9b5a111 100644 --- a/misc/config.py +++ b/misc/config.py @@ -95,8 +95,7 @@ class Config(object, metaclass=Singleton): 'language': 'English', 'quality': 'HD-1080p', 'root_folder': '/tv/', - 'tags': { - }, + 'tags': [], 'url': 'http://localhost:8989/' }, 'omdb': { diff --git a/traktarr.py b/traktarr.py index eb485ca..13392d4 100755 --- a/traktarr.py +++ b/traktarr.py @@ -3,7 +3,6 @@ import os.path import signal import sys import time -import re import click import schedule @@ -151,7 +150,7 @@ def get_objects(pvr, pvr_type, notifications): return objects_list -def get_exclusions(pvr, pvr_type, notifications): +def get_exclusions(pvr, pvr_type): objects_list = pvr.get_exclusions() objects_type = 'movie' if pvr_type.lower() == 'radarr' else 'show' if not objects_list: @@ -226,14 +225,21 @@ def show( # profile tags profile_tags = None - use_tags = None - readable_tags = None + tag_ids = None + tag_names = None - if cfg.sonarr.tags: + if cfg.sonarr.tags is not None: profile_tags = get_profile_tags(sonarr) - # 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']) - readable_tags = sonarr_helper.readable_tag_from_ids(profile_tags, use_tags) + if profile_tags is not None: + # determine which tags to use when adding this series + tag_ids = sonarr_helper.series_tag_ids_list_builder( + profile_tags, + cfg.sonarr.tags, + ) + tag_names = sonarr_helper.series_tag_names_list_builder( + profile_tags, + tag_ids, + ) # series type if any('anime' in s.lower() for s in trakt_show['genres']): @@ -251,20 +257,20 @@ def show( quality_profile_id, language_profile_id, cfg.sonarr.root_folder, - use_tags, + tag_ids, not no_search, series_type, ): - if profile_tags is not None and readable_tags is not None: + if profile_tags is not None and tag_names is not None: log.info("ADDED: \'%s (%s)\' with Sonarr Tags: %s", series_title, series_year, - readable_tags) + tag_names) else: log.info("ADDED: \'%s (%s)\'", series_title, series_year) else: if profile_tags is not None: log.error("FAILED ADDING: \'%s (%s)\' with Sonarr Tags: %s", series_title, series_year, - readable_tags) + tag_names) else: log.info("FAILED ADDING: \'%s (%s)\'", series_title, series_year) @@ -294,9 +300,9 @@ def show( help='Sort list to process.', show_default=True) @click.option( - '--years', '-y', + '--year', '--years', '-y', default=None, - help='Range of years to search. For example, \'2000-2010\'.') + help='Can be a specific year or a range of years to search. For example, \'2000\' or \'2000-2010\'.') @click.option( '--genres', '-g', default=None, @@ -308,16 +314,16 @@ def show( default=None, help='Add shows with this root folder to Sonarr.') @click.option( - '--actor', '-a', + '--person', '-p', default=None, - help='Only add movies from this actor to Radarr. ' - 'Only one actor can be specified. ' - 'Requires the \'person\' list option.') + help='Only add shows from this person (e.g. actor) to Sonarr. ' + 'Only one person can be specified. ' + 'Requires the \'person\' list type.') @click.option( '--include-non-acting-roles', is_flag=True, - help='Include non-acting roles such as \'As Himself\', \'Narrator\', etc. \n' - 'Requires the \'person\' list option with the \'actor\' argument.') + help='Include non-acting roles such as \'Director\', \'As Himself\', \'Narrator\', etc. ' + 'Requires the \'person\' list type with the \'person\' argument.') @click.option( '--no-search', is_flag=True, @@ -328,7 +334,7 @@ def show( help='Send notifications.') @click.option( '--authenticate-user', - help='Specify which user to authenticate with to retrieve Trakt lists. \n' + help='Specify which user to authenticate with to retrieve Trakt lists. ' 'Defaults to first user in the config') @click.option( '--ignore-blacklist', @@ -346,7 +352,7 @@ def shows( years=None, genres=None, folder=None, - actor=None, + person=None, no_search=False, include_non_acting_roles=False, notifications=False, @@ -362,6 +368,7 @@ def shows( from helpers import sonarr as sonarr_helper from helpers import trakt as trakt_helper from helpers import tvdb as tvdb_helper + from helpers import parameter as parameter_helper added_shows = 0 @@ -392,16 +399,15 @@ def shows( misc_helper.unblacklist_genres(genres, cfg['filters']['shows']['blacklisted_genres']) log.debug("Filter Trakt results with genre(s): %s", ', '.join(map(lambda x: x.title(), genres))) - # set years range - r = re.compile('[0-9]{4}-[0-9]{4}') + # process years parameter + years, new_min_year, new_max_year = parameter_helper.years( + years, + cfg.filters.shows.blacklisted_min_year, + cfg.filters.shows.blacklisted_max_year, + ) - if years and r.match(years): - cfg['filters']['shows']['blacklisted_min_year'] = int(years.split('-')[0]) - cfg['filters']['shows']['blacklisted_max_year'] = int(years.split('-')[1]) - elif cfg.filters.shows.blacklisted_min_year and cfg.filters.shows.blacklisted_max_year: - years = str(cfg.filters.shows.blacklisted_min_year) + '-' + str(cfg.filters.shows.blacklisted_max_year) - else: - years = None + cfg['filters']['shows']['blacklisted_min_year'] = new_min_year + cfg['filters']['shows']['blacklisted_max_year'] = new_max_year # runtimes range if cfg.filters.shows.blacklisted_min_runtime: @@ -436,7 +442,23 @@ def shows( # language profile id language_profile_id = get_language_profile_id(sonarr, cfg.sonarr.language) - profile_tags = get_profile_tags(sonarr) if cfg.sonarr.tags else None + # profile tags + profile_tags = None + tag_ids = None + tag_names = None + + if cfg.sonarr.tags is not None: + profile_tags = get_profile_tags(sonarr) + if profile_tags is not None: + # determine which tags to use when adding this series + tag_ids = sonarr_helper.series_tag_ids_list_builder( + profile_tags, + cfg.sonarr.tags, + ) + tag_names = sonarr_helper.series_tag_names_list_builder( + profile_tags, + tag_ids, + ) pvr_objects_list = get_objects(sonarr, 'Sonarr', notifications) @@ -469,13 +491,13 @@ def shows( ) elif list_type.lower() == 'person': - if not actor: - log.error("You must specify an actor with the \'--actor\' / \'-a\' parameter when using the \'person\'" + + if not person: + log.error("You must specify an person with the \'--person\' / \'-p\' parameter when using the \'person\'" + " list type!") return None trakt_objects_list = trakt.get_person_shows( years=years, - person=actor, + person=person, countries=countries, languages=languages, genres=genres, @@ -535,7 +557,7 @@ def shows( remove_rejected_from_recommended = False # build filtered series list without series that exist in sonarr - processed_series_list = sonarr_helper.remove_existing_series( + processed_series_list = sonarr_helper.remove_existing_series_from_trakt_list( pvr_objects_list, trakt_objects_list, callback_remove_recommended if remove_rejected_from_recommended else None @@ -619,22 +641,6 @@ def shows( (series['show']['network'] or 'N/A').upper(), ) - # profile tags - use_tags = None - readable_tags = None - - if profile_tags is not None: - # 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'], - ) - readable_tags = sonarr_helper.readable_tag_from_ids( - profile_tags, - use_tags, - ) - # add show to sonarr if sonarr.add_series( series['show']['ids']['tvdb'], @@ -643,14 +649,14 @@ def shows( quality_profile_id, language_profile_id, cfg.sonarr.root_folder, - use_tags, + tag_ids, not no_search, series_type, ): - if profile_tags is not None and readable_tags is not None: + if profile_tags is not None and tag_names is not None: log.info("ADDED: \'%s (%s)\' with Sonarr Tags: %s", series_title, series_year, - readable_tags) + tag_names) else: log.info("ADDED: \'%s (%s)\'", series_title, series_year) if notifications: @@ -659,7 +665,7 @@ def shows( else: if profile_tags is not None: log.error("FAILED ADDING: \'%s (%s)\' with Sonarr Tags: %s", series_title, series_year, - readable_tags) + tag_names) else: log.info("FAILED ADDING: \'%s (%s)\'", series_title, series_year) continue @@ -801,9 +807,9 @@ def movie( type=int, help='Set a minimum Rotten Tomatoes score.') @click.option( - '--years', '-y', + '--year', '--years', '-y', default=None, - help='Range of years to search. For example, \'2000-2010\'.') + help='Can be a specific year or a range of years to search. For example, \'2000\' or \'2000-2010\'.') @click.option( '--genres', '-g', default=None, @@ -819,16 +825,16 @@ def movie( type=click.Choice(['announced', 'in_cinemas', 'released', 'predb']), help='Add movies with this minimum availability to Radarr. Default is \'released\'.') @click.option( - '--actor', '-a', + '--person', '-p', default=None, - help='Only add movies from this actor to Radarr.' - 'Only one actor can be specified.' - 'Requires the \'person\' list.') + help='Only add movies from this person (e.g. actor) to Radarr. ' + 'Only one person can be specified. ' + 'Requires the \'person\' list type.') @click.option( '--include-non-acting-roles', is_flag=True, - help='Include non-acting roles such as \'As Himself\', \'Narrator\', etc. \n' - 'Requires the \'person\' list option with the \'actor\' argument.') + help='Include non-acting roles such as \'Director\', \'As Himself\', \'Narrator\', etc. ' + 'Requires the \'person\' list type with the \'person\' argument.') @click.option( '--no-search', is_flag=True, @@ -839,7 +845,7 @@ def movie( help='Send notifications.') @click.option( '--authenticate-user', - help='Specify which user to authenticate with to retrieve Trakt lists. \n' + help='Specify which user to authenticate with to retrieve Trakt lists. ' 'Defaults to first user in the config.') @click.option( '--ignore-blacklist', @@ -859,7 +865,7 @@ def movies( genres=None, folder=None, minimum_availability=None, - actor=None, + person=None, include_non_acting_roles=False, no_search=False, notifications=False, @@ -875,6 +881,7 @@ def movies( from helpers import trakt as trakt_helper from helpers import omdb as omdb_helper from helpers import tmdb as tmdb_helper + from helpers import parameter as parameter_helper added_movies = 0 @@ -906,16 +913,15 @@ def movies( misc_helper.unblacklist_genres(genres, cfg['filters']['movies']['blacklisted_genres']) log.debug("Filter Trakt results with genre(s): %s", ', '.join(map(lambda x: x.title(), genres))) - # set years range - r = re.compile('[0-9]{4}-[0-9]{4}') + # process years parameter + years, new_min_year, new_max_year = parameter_helper.years( + years, + cfg.filters.movies.blacklisted_min_year, + cfg.filters.movies.blacklisted_max_year, + ) - if years and r.match(years): - cfg['filters']['movies']['blacklisted_min_year'] = int(years.split('-')[0]) - cfg['filters']['movies']['blacklisted_max_year'] = int(years.split('-')[1]) - elif cfg.filters.movies.blacklisted_min_year and cfg.filters.movies.blacklisted_max_year: - years = str(cfg.filters.movies.blacklisted_min_year) + '-' + str(cfg.filters.movies.blacklisted_max_year) - else: - years = None + cfg['filters']['movies']['blacklisted_min_year'] = new_min_year + cfg['filters']['movies']['blacklisted_max_year'] = new_max_year # runtimes range if cfg.filters.movies.blacklisted_min_runtime: @@ -959,7 +965,7 @@ def movies( quality_profile_id = get_quality_profile_id(radarr, cfg.radarr.quality) pvr_objects_list = get_objects(radarr, 'Radarr', notifications) - pvr_exclusions_list = get_exclusions(radarr, 'Radarr', notifications) + pvr_exclusions_list = get_exclusions(radarr, 'Radarr') # get trakt movies list if list_type.lower() == 'anticipated': @@ -993,13 +999,13 @@ def movies( 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\'" + + if not person: + log.error("You must specify an person with the \'--person\' / \'-p\' parameter when using the \'person\'" + " list type!") return None trakt_objects_list = trakt.get_person_movies( years=years, - person=actor, + person=person, countries=countries, languages=languages, genres=genres, @@ -1060,7 +1066,7 @@ def movies( remove_rejected_from_recommended = False # build filtered movie list without movies that exist in radarr - processed_movies_list, removal_successful = radarr_helper.remove_existing_and_excluded_movies( + processed_movies_list, removal_successful = radarr_helper.remove_existing_and_excluded_movies_from_trakt_list( pvr_objects_list, pvr_exclusions_list, trakt_objects_list,