Merge pull request #146 from l3uddz/develop

Develop
pull/143/head^2
salty 4 years ago committed by GitHub
commit 0a49f0566e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -23,7 +23,13 @@ If applicable, add screenshots to help explain your problem.
**Logs** **Logs**
Link to debug or trace log files. 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** **System Information**

@ -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

@ -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) [![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) [![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) [![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) - [Slack](#slack)
- [Radarr](#radarr) - [Radarr](#radarr)
- [Sonarr](#sonarr) - [Sonarr](#sonarr)
- [Tags](#tags)
- [Trakt](#trakt) - [Trakt](#trakt)
- [OMDb](#omdb) - [OMDb](#omdb)
- [Usage](#usage) - [Usage](#usage)
@ -335,7 +334,7 @@ You can repeat this process for as many users as you like.
"language": "English", "language": "English",
"quality": "HD-1080p", "quality": "HD-1080p",
"root_folder": "/tv/", "root_folder": "/tv/",
"tags": {}, "tags": [],
"url": "http://localhost:8989/" "url": "http://localhost:8989/"
}, },
"trakt": { "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. - 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. `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: - 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. `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. - 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 `-<number of years to go back>` 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 `+<number of years to go forward>` 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. `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. - 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. `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: - 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. `blacklisted_genres` - Blacklist certain genres.
- [List of available TV show genres](assets/list_of_tv_show_genres.md). - [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. - 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 `-<number of years to go back>` 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 `+<number of years to go forward>` 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. `blacklisted_title_keywords` - Blacklist certain words in titles.
@ -962,7 +981,7 @@ Sonarr configuration.
"language": "English", "language": "English",
"quality": "HD-1080p", "quality": "HD-1080p",
"root_folder": "/tv/", "root_folder": "/tv/",
"tags": {}, "tags": [],
"url": "http://localhost:8989" "url": "http://localhost:8989"
}, },
``` ```
@ -975,55 +994,29 @@ Sonarr configuration.
`root_folder` - Root folder for TV shows. `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. `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. - 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
Trakt Authentication info: Trakt Authentication info:
@ -1214,6 +1207,8 @@ Options:
-s, --sort [rating|release|votes] -s, --sort [rating|release|votes]
Sort list to process. [default: votes] Sort list to process. [default: votes]
-rt, --rotten_tomatoes INTEGER Set a minimum Rotten Tomatoes score. -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 -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 specified as a comma-separated list. Use 'ignore' to add movies
from any genre, including ones with no genre specified. from any genre, including ones with no genre specified.
@ -1221,10 +1216,11 @@ Options:
-ma, --minimum-availability [announced|in_cinemas|released|predb] -ma, --minimum-availability [announced|in_cinemas|released|predb]
Add movies with this minimum availability to Radarr. Default is Add movies with this minimum availability to Radarr. Default is
'released'. 'released'.
-a, --actor TEXT Only add movies from this actor to Radarr.Only one actor can be -p, --person TEXT Only add movies from this person (e.g. actor) to Radarr. Only
specified.Requires the 'person' list. one person can be specified. Requires the 'person' list type.
--include-non-acting-roles Include non-acting roles such as 'As Himself', 'Narrator', etc. --include-non-acting-roles Include non-acting roles such as 'Director', 'As Himself',
Requires the 'person' list option with the 'actor' argument. 'Narrator', etc. Requires the 'person' list type with the
'person' argument.
--no-search Disable search when adding movies to Radarr. --no-search Disable search when adding movies to Radarr.
--notifications Send notifications. --notifications Send notifications.
--authenticate-user TEXT Specify which user to authenticate with to retrieve Trakt lists. --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` - 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. `-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). - 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). - 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`. - 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. `--no-search` - Tells Radarr to not automatically search for added movies.
@ -1347,24 +1347,24 @@ Usage: traktarr shows [OPTIONS]
Add multiple shows to Sonarr. Add multiple shows to Sonarr.
Options: Options:
-t, --list-type TEXT Trakt list to process. -t, --list-type TEXT Trakt list to process. For example, 'anticipated', 'trending',
For example, 'anticipated', 'trending',
'popular', 'person', 'watched', 'played', 'recommended', 'popular', 'person', 'watched', 'played', 'recommended',
'watchlist', or any URL to a list. [required] 'watchlist', or any URL to a list. [required]
-l, --add-limit INTEGER Limit number of shows added to Sonarr. -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] -d, --add-delay FLOAT Seconds between each add request to Sonarr. [default: 2.5]
-s, --sort [rating|release|votes] -s, --sort [rating|release|votes]
Sort list to process. [default: 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 -g, --genres TEXT Only add shows from this genre to Sonarr. Multiple genres are
specified as a comma-separated list. specified as a comma-separated list. Use 'ignore' to add shows
Use 'ignore' to add shows
from any genre, including ones with no genre specified. from any genre, including ones with no genre specified.
-f, --folder TEXT Add shows with this root folder to Sonarr. -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 -p, --person TEXT Only add shows from this person (e.g. actor) to Sonarr. Only one
specified. person can be specified. Requires the 'person' list type.
Requires the 'person' list option. --include-non-acting-roles Include non-acting roles such as 'Director', 'As Himself',
--include-non-acting-roles Include non-acting roles such as 'As Himself', 'Narrator', etc. 'Narrator', etc. Requires the 'person' list type with the
Requires the 'person' list option with the 'actor' argument. 'person' argument.
--no-search Disable search when adding shows to Sonarr. --no-search Disable search when adding shows to Sonarr.
--notifications Send notifications. --notifications Send notifications.
--authenticate-user TEXT Specify which user to authenticate with to retrieve Trakt lists. --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` - 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. `-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). - 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/` - 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`. - 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. `--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 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. - 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 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

@ -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

@ -35,7 +35,7 @@ def movies_to_tmdb_dict(radarr_movies):
return None 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 = [] new_movies_list = []
try: try:
@ -49,7 +49,7 @@ def remove_existing_movies(radarr_movies, trakt_movies, callback=None):
# check if movie exists in processed_movies # check if movie exists in processed_movies
if tmp['movie']['ids']['tmdb'] in processed_movies: if tmp['movie']['ids']['tmdb'] in processed_movies:
movie_year = str(tmp['movie']['year']) if tmp['movie']['year'] else '????' 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: if callback:
callback('movie', tmp) callback('movie', tmp)
continue continue
@ -81,7 +81,7 @@ def exclusions_to_tmdb_dict(radarr_exclusions):
return None 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 = [] new_movies_list = []
try: try:
@ -95,7 +95,7 @@ def remove_existing_exclusions(radarr_exclusions, trakt_movies, callback=None):
# check if movie exists in processed_movies # check if movie exists in processed_movies
if tmp['movie']['ids']['tmdb'] in processed_movies: if tmp['movie']['ids']['tmdb'] in processed_movies:
movie_year = str(tmp['movie']['year']) if tmp['movie']['year'] else '????' 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: if callback:
callback('movie', tmp) callback('movie', tmp)
continue continue
@ -110,7 +110,7 @@ def remove_existing_exclusions(radarr_exclusions, trakt_movies, callback=None):
return 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: if not radarr_movies or not trakt_movies:
log.error("Inappropriate parameters were supplied.") log.error("Inappropriate parameters were supplied.")
return None, False return None, False
@ -122,13 +122,15 @@ def remove_existing_and_excluded_movies(radarr_movies, radarr_exclusions, trakt_
return None, False return None, False
# filter out existing movies in radarr from new trakt list # 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: if not processed_movies_list:
return None, removal_successful return None, removal_successful
# filter out radarr exclusions from the list above # filter out radarr exclusions from the list above
if radarr_exclusions: 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) 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) log.debug("Filtered a total of %d movies from the Trakt movies list.", movies_removed_count)

@ -3,22 +3,21 @@ from misc.log import logger
log = logger.get_logger(__name__) 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: try:
tags = [] tag_ids = []
for tag_name, tag_networks in network_tags.items(): for tag_name in config_tags:
for tag_network in tag_networks: if tag_name.lower() in profile_tags:
if tag_network.lower() in network.lower() and tag_name.lower() in profile_tags: log.debug("Validated Tag: %s", tag_name)
log.debug("Using %s tag for network: %s", tag_name, network) tag_ids.append(profile_tags[tag_name.lower()])
tags.append(profile_tags[tag_name.lower()]) if tag_ids:
if tags: return tag_ids
return tags
except Exception: except Exception:
log.exception("Exception determining tag to use for network %s: ", network) log.exception("Exception building Tags IDs list")
return None 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: try:
if not chosen_tag_ids: if not chosen_tag_ids:
return None return None
@ -30,7 +29,7 @@ def readable_tag_from_ids(profile_tag_ids, chosen_tag_ids):
if tags: if tags:
return tags return tags
except Exception: 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 return None
@ -65,7 +64,7 @@ def series_to_tvdb_dict(sonarr_series):
return None 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 = [] new_series_list = []
if not sonarr_series or not trakt_series: 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 # check if show exists in processed_series
if tmp['show']['ids']['tvdb'] in processed_series: if tmp['show']['ids']['tvdb'] in processed_series:
show_year = str(tmp['show']['year']) if tmp['show']['year'] else '????' 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: if callback:
callback('show', tmp) callback('show', tmp)
continue continue

@ -122,9 +122,6 @@ def blacklisted_show_country(show, allowed_countries):
def blacklisted_show_language(show, allowed_languages): def blacklisted_show_language(show, allowed_languages):
blacklisted = False blacklisted = False
# [] - add show items with 'en' language
if not allowed_languages:
allowed_languages = ['en']
try: try:
# ["ignore"] - add show item even if it is missing a language # ["ignore"] - add show item even if it is missing a language
if any('ignore' in s.lower() for s in allowed_languages): 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.", log.debug("\'%s\' | Blacklisted Languages Check | Blacklisted because it had no language specified.",
show['show']['title']) show['show']['title'])
blacklisted = True 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 # 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): 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", 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): def blacklisted_movie_language(movie, allowed_languages):
blacklisted = False blacklisted = False
# [] - add movie items with 'en' language
if not allowed_languages:
allowed_languages = ['en']
try: try:
# ["ignore"] - add movie item even if it is missing a language # ["ignore"] - add movie item even if it is missing a language
if any('ignore' in s.lower() for s in allowed_languages): 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.", log.debug("\'%s\' | Blacklisted Languages Check | Blacklisted because it had no language specified.",
movie['movie']['title']) movie['movie']['title'])
blacklisted = True 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 # 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): 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", log.debug("\'%s\' | Blacklisted Languages Check | Blacklisted because it's in the language: %s",

@ -31,7 +31,7 @@ class Radarr(PVR):
payload = dict_merge(payload, { payload = dict_merge(payload, {
'tmdbId': movie_tmdb_id, 'tmdbId': movie_tmdb_id,
'year': movie_year, 'year': int(movie_year),
'minimumAvailability': minimum_availability, 'minimumAvailability': minimum_availability,
'addOptions': { 'addOptions': {
'searchForMovie': search_missing 'searchForMovie': search_missing

@ -100,18 +100,16 @@ class Trakt:
if payload is None: if payload is None:
payload = {} payload = {}
# languages list
if not languages:
languages = ['en']
languages = ','.join(languages).lower()
payload = dict_merge(payload, { payload = dict_merge(payload, {
'extended': 'full', 'extended': 'full',
'limit': limit, 'limit': limit,
'page': 1, 'page': 1,
'languages': languages,
}) })
# languages list
if languages:
payload['languages'] = ','.join(languages).lower()
# years range # years range
if years: if years:
payload['years'] = years payload['years'] = years

@ -95,8 +95,7 @@ class Config(object, metaclass=Singleton):
'language': 'English', 'language': 'English',
'quality': 'HD-1080p', 'quality': 'HD-1080p',
'root_folder': '/tv/', 'root_folder': '/tv/',
'tags': { 'tags': [],
},
'url': 'http://localhost:8989/' 'url': 'http://localhost:8989/'
}, },
'omdb': { 'omdb': {

@ -3,7 +3,6 @@ import os.path
import signal import signal
import sys import sys
import time import time
import re
import click import click
import schedule import schedule
@ -151,7 +150,7 @@ def get_objects(pvr, pvr_type, notifications):
return objects_list return objects_list
def get_exclusions(pvr, pvr_type, notifications): def get_exclusions(pvr, pvr_type):
objects_list = pvr.get_exclusions() objects_list = pvr.get_exclusions()
objects_type = 'movie' if pvr_type.lower() == 'radarr' else 'show' objects_type = 'movie' if pvr_type.lower() == 'radarr' else 'show'
if not objects_list: if not objects_list:
@ -226,14 +225,21 @@ def show(
# profile tags # profile tags
profile_tags = None profile_tags = None
use_tags = None tag_ids = None
readable_tags = None tag_names = None
if cfg.sonarr.tags: if cfg.sonarr.tags is not None:
profile_tags = get_profile_tags(sonarr) profile_tags = get_profile_tags(sonarr)
# determine which tags to use when adding this series if profile_tags is not None:
use_tags = sonarr_helper.series_tag_id_from_network(profile_tags, cfg.sonarr.tags, trakt_show['network']) # determine which tags to use when adding this series
readable_tags = sonarr_helper.readable_tag_from_ids(profile_tags, use_tags) 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 # series type
if any('anime' in s.lower() for s in trakt_show['genres']): if any('anime' in s.lower() for s in trakt_show['genres']):
@ -251,20 +257,20 @@ def show(
quality_profile_id, quality_profile_id,
language_profile_id, language_profile_id,
cfg.sonarr.root_folder, cfg.sonarr.root_folder,
use_tags, tag_ids,
not no_search, not no_search,
series_type, 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, log.info("ADDED: \'%s (%s)\' with Sonarr Tags: %s", series_title, series_year,
readable_tags) tag_names)
else: else:
log.info("ADDED: \'%s (%s)\'", series_title, series_year) log.info("ADDED: \'%s (%s)\'", series_title, series_year)
else: else:
if profile_tags is not None: if profile_tags is not None:
log.error("FAILED ADDING: \'%s (%s)\' with Sonarr Tags: %s", series_title, series_year, log.error("FAILED ADDING: \'%s (%s)\' with Sonarr Tags: %s", series_title, series_year,
readable_tags) tag_names)
else: else:
log.info("FAILED ADDING: \'%s (%s)\'", series_title, series_year) log.info("FAILED ADDING: \'%s (%s)\'", series_title, series_year)
@ -294,9 +300,9 @@ def show(
help='Sort list to process.', help='Sort list to process.',
show_default=True) show_default=True)
@click.option( @click.option(
'--years', '-y', '--year', '--years', '-y',
default=None, 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( @click.option(
'--genres', '-g', '--genres', '-g',
default=None, default=None,
@ -308,16 +314,16 @@ def show(
default=None, default=None,
help='Add shows with this root folder to Sonarr.') help='Add shows with this root folder to Sonarr.')
@click.option( @click.option(
'--actor', '-a', '--person', '-p',
default=None, default=None,
help='Only add movies from this actor to Radarr. ' help='Only add shows from this person (e.g. actor) to Sonarr. '
'Only one actor can be specified. ' 'Only one person can be specified. '
'Requires the \'person\' list option.') 'Requires the \'person\' list type.')
@click.option( @click.option(
'--include-non-acting-roles', '--include-non-acting-roles',
is_flag=True, is_flag=True,
help='Include non-acting roles such as \'As Himself\', \'Narrator\', etc. \n' help='Include non-acting roles such as \'Director\', \'As Himself\', \'Narrator\', etc. '
'Requires the \'person\' list option with the \'actor\' argument.') 'Requires the \'person\' list type with the \'person\' argument.')
@click.option( @click.option(
'--no-search', '--no-search',
is_flag=True, is_flag=True,
@ -328,7 +334,7 @@ def show(
help='Send notifications.') help='Send notifications.')
@click.option( @click.option(
'--authenticate-user', '--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') 'Defaults to first user in the config')
@click.option( @click.option(
'--ignore-blacklist', '--ignore-blacklist',
@ -346,7 +352,7 @@ def shows(
years=None, years=None,
genres=None, genres=None,
folder=None, folder=None,
actor=None, person=None,
no_search=False, no_search=False,
include_non_acting_roles=False, include_non_acting_roles=False,
notifications=False, notifications=False,
@ -362,6 +368,7 @@ def shows(
from helpers import sonarr as sonarr_helper from helpers import sonarr as sonarr_helper
from helpers import trakt as trakt_helper from helpers import trakt as trakt_helper
from helpers import tvdb as tvdb_helper from helpers import tvdb as tvdb_helper
from helpers import parameter as parameter_helper
added_shows = 0 added_shows = 0
@ -392,16 +399,15 @@ def shows(
misc_helper.unblacklist_genres(genres, cfg['filters']['shows']['blacklisted_genres']) 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))) log.debug("Filter Trakt results with genre(s): %s", ', '.join(map(lambda x: x.title(), genres)))
# set years range # process years parameter
r = re.compile('[0-9]{4}-[0-9]{4}') 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'] = new_min_year
cfg['filters']['shows']['blacklisted_min_year'] = int(years.split('-')[0]) cfg['filters']['shows']['blacklisted_max_year'] = new_max_year
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
# runtimes range # runtimes range
if cfg.filters.shows.blacklisted_min_runtime: if cfg.filters.shows.blacklisted_min_runtime:
@ -436,7 +442,23 @@ def shows(
# language profile id # language profile id
language_profile_id = get_language_profile_id(sonarr, cfg.sonarr.language) 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) pvr_objects_list = get_objects(sonarr, 'Sonarr', notifications)
@ -469,13 +491,13 @@ def shows(
) )
elif list_type.lower() == 'person': elif list_type.lower() == 'person':
if not actor: if not person:
log.error("You must specify an actor with the \'--actor\' / \'-a\' parameter when using the \'person\'" + log.error("You must specify an person with the \'--person\' / \'-p\' parameter when using the \'person\'" +
" list type!") " list type!")
return None return None
trakt_objects_list = trakt.get_person_shows( trakt_objects_list = trakt.get_person_shows(
years=years, years=years,
person=actor, person=person,
countries=countries, countries=countries,
languages=languages, languages=languages,
genres=genres, genres=genres,
@ -535,7 +557,7 @@ def shows(
remove_rejected_from_recommended = False remove_rejected_from_recommended = False
# build filtered series list without series that exist in sonarr # build filtered series list without series that exist in sonarr
processed_series_list = sonarr_helper.remove_existing_series( processed_series_list = sonarr_helper.remove_existing_series_from_trakt_list(
pvr_objects_list, pvr_objects_list,
trakt_objects_list, trakt_objects_list,
callback_remove_recommended if remove_rejected_from_recommended else None callback_remove_recommended if remove_rejected_from_recommended else None
@ -619,22 +641,6 @@ def shows(
(series['show']['network'] or 'N/A').upper(), (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 # add show to sonarr
if sonarr.add_series( if sonarr.add_series(
series['show']['ids']['tvdb'], series['show']['ids']['tvdb'],
@ -643,14 +649,14 @@ def shows(
quality_profile_id, quality_profile_id,
language_profile_id, language_profile_id,
cfg.sonarr.root_folder, cfg.sonarr.root_folder,
use_tags, tag_ids,
not no_search, not no_search,
series_type, 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, log.info("ADDED: \'%s (%s)\' with Sonarr Tags: %s", series_title, series_year,
readable_tags) tag_names)
else: else:
log.info("ADDED: \'%s (%s)\'", series_title, series_year) log.info("ADDED: \'%s (%s)\'", series_title, series_year)
if notifications: if notifications:
@ -659,7 +665,7 @@ def shows(
else: else:
if profile_tags is not None: if profile_tags is not None:
log.error("FAILED ADDING: \'%s (%s)\' with Sonarr Tags: %s", series_title, series_year, log.error("FAILED ADDING: \'%s (%s)\' with Sonarr Tags: %s", series_title, series_year,
readable_tags) tag_names)
else: else:
log.info("FAILED ADDING: \'%s (%s)\'", series_title, series_year) log.info("FAILED ADDING: \'%s (%s)\'", series_title, series_year)
continue continue
@ -801,9 +807,9 @@ def movie(
type=int, type=int,
help='Set a minimum Rotten Tomatoes score.') help='Set a minimum Rotten Tomatoes score.')
@click.option( @click.option(
'--years', '-y', '--year', '--years', '-y',
default=None, 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( @click.option(
'--genres', '-g', '--genres', '-g',
default=None, default=None,
@ -819,16 +825,16 @@ def movie(
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. Default is \'released\'.') help='Add movies with this minimum availability to Radarr. Default is \'released\'.')
@click.option( @click.option(
'--actor', '-a', '--person', '-p',
default=None, default=None,
help='Only add movies from this actor to Radarr.' help='Only add movies from this person (e.g. actor) to Radarr. '
'Only one actor can be specified.' 'Only one person can be specified. '
'Requires the \'person\' list.') 'Requires the \'person\' list type.')
@click.option( @click.option(
'--include-non-acting-roles', '--include-non-acting-roles',
is_flag=True, is_flag=True,
help='Include non-acting roles such as \'As Himself\', \'Narrator\', etc. \n' help='Include non-acting roles such as \'Director\', \'As Himself\', \'Narrator\', etc. '
'Requires the \'person\' list option with the \'actor\' argument.') 'Requires the \'person\' list type with the \'person\' argument.')
@click.option( @click.option(
'--no-search', '--no-search',
is_flag=True, is_flag=True,
@ -839,7 +845,7 @@ def movie(
help='Send notifications.') help='Send notifications.')
@click.option( @click.option(
'--authenticate-user', '--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.') 'Defaults to first user in the config.')
@click.option( @click.option(
'--ignore-blacklist', '--ignore-blacklist',
@ -859,7 +865,7 @@ def movies(
genres=None, genres=None,
folder=None, folder=None,
minimum_availability=None, minimum_availability=None,
actor=None, person=None,
include_non_acting_roles=False, include_non_acting_roles=False,
no_search=False, no_search=False,
notifications=False, notifications=False,
@ -875,6 +881,7 @@ def movies(
from helpers import trakt as trakt_helper from helpers import trakt as trakt_helper
from helpers import omdb as omdb_helper from helpers import omdb as omdb_helper
from helpers import tmdb as tmdb_helper from helpers import tmdb as tmdb_helper
from helpers import parameter as parameter_helper
added_movies = 0 added_movies = 0
@ -906,16 +913,15 @@ def movies(
misc_helper.unblacklist_genres(genres, cfg['filters']['movies']['blacklisted_genres']) 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))) log.debug("Filter Trakt results with genre(s): %s", ', '.join(map(lambda x: x.title(), genres)))
# set years range # process years parameter
r = re.compile('[0-9]{4}-[0-9]{4}') 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'] = new_min_year
cfg['filters']['movies']['blacklisted_min_year'] = int(years.split('-')[0]) cfg['filters']['movies']['blacklisted_max_year'] = new_max_year
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
# runtimes range # runtimes range
if cfg.filters.movies.blacklisted_min_runtime: if cfg.filters.movies.blacklisted_min_runtime:
@ -959,7 +965,7 @@ def movies(
quality_profile_id = get_quality_profile_id(radarr, cfg.radarr.quality) quality_profile_id = get_quality_profile_id(radarr, cfg.radarr.quality)
pvr_objects_list = get_objects(radarr, 'Radarr', notifications) 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 # get trakt movies list
if list_type.lower() == 'anticipated': if list_type.lower() == 'anticipated':
@ -993,13 +999,13 @@ def movies(
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 person:
log.error("You must specify an actor with the \'--actor\' / \'-a\' parameter when using the \'person\'" + log.error("You must specify an person with the \'--person\' / \'-p\' parameter when using the \'person\'" +
" list type!") " list type!")
return None return None
trakt_objects_list = trakt.get_person_movies( trakt_objects_list = trakt.get_person_movies(
years=years, years=years,
person=actor, person=person,
countries=countries, countries=countries,
languages=languages, languages=languages,
genres=genres, genres=genres,
@ -1060,7 +1066,7 @@ def movies(
remove_rejected_from_recommended = False remove_rejected_from_recommended = False
# build filtered movie list without movies that exist in radarr # build filtered movie list without movies that exist in radarr
processed_movies_list, 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_objects_list,
pvr_exclusions_list, pvr_exclusions_list,
trakt_objects_list, trakt_objects_list,

Loading…
Cancel
Save