mirror of
https://github.com/mza921/Plex-Auto-Collections
synced 2024-11-14 00:07:18 +00:00
Merge pull request #113 from meisnate12/tmdb_discover
2.6.0 TMDb discover & other TMDb special lists
This commit is contained in:
commit
f8ce499534
7 changed files with 855 additions and 308 deletions
14
CHANGELOG.md
14
CHANGELOG.md
|
@ -4,6 +4,17 @@ All notable changes to this project will be documented in this file.
|
|||
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
|
||||
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
||||
|
||||
## [2.6.0] - 2020-11-12 - [#113](https://github.com/mza921/Plex-Auto-Collections/pull/113)
|
||||
### Added
|
||||
- [#107](https://github.com/mza921/Plex-Auto-Collections/issues/107) - Added `plex_collection`
|
||||
- [#86](https://github.com/mza921/Plex-Auto-Collections/issues/86) - Added `tmdb_company` and `tmdb_network`
|
||||
- [#41](https://github.com/mza921/Plex-Auto-Collections/issues/41) - Added `tmdb_discover`
|
||||
- Added `tmdb_popular`, `tmdb_top_rated`, `tmdb_now_playing`
|
||||
|
||||
### Fixed
|
||||
- [#108](https://github.com/mza921/Plex-Auto-Collections/issues/108) - Fixed TMDb error
|
||||
- [#102](https://github.com/mza921/Plex-Auto-Collections/issues/102) - If any APIs are invalid the collection switches to append
|
||||
|
||||
## [2.5.0] - 2020-11-11 - [#112](https://github.com/mza921/Plex-Auto-Collections/pull/112)
|
||||
### Added
|
||||
- [#72](https://github.com/mza921/Plex-Auto-Collections/issues/72) - `trakt_watchlist` support
|
||||
|
@ -12,6 +23,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|||
### Fixed
|
||||
- [#50](https://github.com/mza921/Plex-Auto-Collections/issues/50) - Trakt access_token refresh
|
||||
|
||||
|
||||
## [2.4.7] - 2020-11-09 - [#103](https://github.com/mza921/Plex-Auto-Collections/pull/103)
|
||||
### Fixed
|
||||
- [#92](https://github.com/mza921/Plex-Auto-Collections/issues/92) - fixed New Plex Movie Agent id lookup behind a proxy
|
||||
|
@ -25,6 +37,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|||
### Fixed
|
||||
- [#93](https://github.com/mza921/Plex-Auto-Collections/issues/93) - actually fixed `max_age`
|
||||
|
||||
|
||||
|
||||
## [2.4.5] - 2020-11-05 - [#97](https://github.com/mza921/Plex-Auto-Collections/pull/97)
|
||||
### Changed
|
||||
- `max_age` no longer takes years
|
||||
|
|
271
README.md
271
README.md
|
@ -1,5 +1,5 @@
|
|||
# Plex Auto Collections
|
||||
##### Version 2.5.0
|
||||
##### Version 2.6.0
|
||||
Plex Auto Collections is a Python 3 script that works off a configuration file to create/update Plex collections. Collection management with this tool can be automated in a varying degree of customizability. Supports IMDB, TMDb, and Trakt lists as well as built in Plex Searches using actors, genres, year, studio and more.
|
||||
|
||||
![https://i.imgur.com/iHAYFIZ.png](https://i.imgur.com/iHAYFIZ.png)
|
||||
|
@ -12,8 +12,15 @@ Plex Auto Collections is a Python 3 script that works off a configuration file t
|
|||
- [Collections](#collections)
|
||||
- [List Type](#list-type-collection-attribute)
|
||||
- [Plex Search (List Type)](#plex-search-list-type)
|
||||
- [Plex Collection (List Type)](#plex-collection-list-type)
|
||||
- [TMDb Collection (List Type)](#tmdb-collection-list-type)
|
||||
- [TMDb People (List Type)](#tmdb-people-list-type)
|
||||
- [TMDb Company (List Type)](#tmdb-company-list-type)
|
||||
- [TMDb Network (List Type)](#tmdb-network-list-type)
|
||||
- [TMDb Popular (List Type)](#tmdb-popular-list-type)
|
||||
- [TMDb Top Rated (List Type)](#tmdb-top-rated-list-type)
|
||||
- [TMDb Now Playing (List Type)](#tmdb-now-playing-list-type)
|
||||
- [TMDb Discover (List Type)](#tmdb-discover-list-type)
|
||||
- [TMDb List (List Type)](#tmdb-list-list-type)
|
||||
- [TMDb Movie (List Type)](#tmdb-movie-list-type)
|
||||
- [TMDb Show (List Type)](#tmdb-show-list-type)
|
||||
|
@ -149,8 +156,15 @@ Each collection is defined by the mapping name which becomes the name of the Ple
|
|||
|
||||
The only required attribute for each collection is the list type. There are many different list types to choose from:
|
||||
- [Plex Search](#plex-search-list-type)
|
||||
- [Plex Collection](#plex-collection-list-type)
|
||||
- [TMDb Collection](#tmdb-collection-list-type)
|
||||
- [TMDb People](#tmdb-people-list-type)
|
||||
- [TMDb Company](#tmdb-company-list-type)
|
||||
- [TMDb Network](#tmdb-network-list-type)
|
||||
- [TMDb Popular](#tmdb-popular-list-type)
|
||||
- [TMDb Top Rated](#tmdb-top-rated-list-type)
|
||||
- [TMDb Now Playing](#tmdb-now-playing-list-type)
|
||||
- [TMDb Discover](#tmdb-discover-list-type)
|
||||
- [TMDb List](#tmdb-list-list-type)
|
||||
- [TMDb Movie](#tmdb-movie-list-type)
|
||||
- [TMDb Show](#tmdb-show-list-type)
|
||||
|
@ -252,6 +266,28 @@ Notes:
|
|||
- You can only use each search option once per `plex_search` but you can give the search multiple values.
|
||||
- If you want to restrict the search by multiples of the same attribute (i.e. You want every movie that is a Romance and Comedy) try using [filters](#collection-filters-collection-attribute).
|
||||
|
||||
#### Plex Collection (List Type)
|
||||
|
||||
###### Works with Movie and TV Show Libraries
|
||||
|
||||
You can create Collections based on collections already in Plex
|
||||
|
||||
```yaml
|
||||
collections:
|
||||
Dinosaurs:
|
||||
plex_collection: Jurassic Park
|
||||
```
|
||||
|
||||
Note if you want to add multiple collections you have to use a list. Comma separated values will not work.
|
||||
|
||||
```yaml
|
||||
collections:
|
||||
Dinosaurs:
|
||||
plex_collection:
|
||||
- Jurassic Park
|
||||
- The Land Before Time
|
||||
```
|
||||
|
||||
#### TMDb Collection (List Type)
|
||||
|
||||
###### Works with Movie Libraries
|
||||
|
@ -355,6 +391,237 @@ Notes:
|
|||
- Local posters are loaded over `tmdb_profile` if they exist unless `tmdb_profile` is also specified
|
||||
- `tmdb_biography` will load unless `summary`,`tmdb_summary`, or `tmdb_biography` is also specified
|
||||
|
||||
#### TMDb Company (List Type)
|
||||
|
||||
###### Works with Movie and TV Show Libraries
|
||||
|
||||
You can use a TMDb Company to build a collection based on all it's movies/shows by using `tmdb_company`. You can use the full url or just type in the TMDb ID for the collection:
|
||||
|
||||
```yaml
|
||||
collections:
|
||||
Studio Ghibli:
|
||||
tmdb_company: 10342
|
||||
```
|
||||
|
||||
```yaml
|
||||
collections:
|
||||
Studio Ghibli:
|
||||
tmdb_company: https://www.themoviedb.org/company/10342
|
||||
```
|
||||
|
||||
#### TMDb Network (List Type)
|
||||
|
||||
###### Works with Show Libraries
|
||||
|
||||
Similarly to using a TMDb Company, you can also use a TMDb Network to build a collection based on all it's shows by using `tmdb_network`. You can use the full url or just type in the TMDb ID for the collection:
|
||||
|
||||
```yaml
|
||||
collections:
|
||||
CBS:
|
||||
tmdb_network: 16
|
||||
```
|
||||
|
||||
```yaml
|
||||
collections:
|
||||
CBS:
|
||||
tmdb_network: https://www.themoviedb.org/network/16
|
||||
```
|
||||
|
||||
#### TMDb Popular (List Type)
|
||||
|
||||
###### Works with Movie and TV Show Libraries
|
||||
|
||||
You can build a collection using TMDb's most popular movies/shows by using `tmdb_popular`. The `tmdb_popular` attribute only supports a single integer value. The `sync_mode: sync` option is recommended since the list is continuously updated.
|
||||
|
||||
```yaml
|
||||
collections:
|
||||
TMDb Trending:
|
||||
tmdb_popular: 30
|
||||
sync_mode: sync
|
||||
```
|
||||
|
||||
#### TMDb Top Rated (List Type)
|
||||
|
||||
###### Works with Movie and TV Show Libraries
|
||||
|
||||
You can build a collection using TMDb's top rated movies/shows by using `tmdb_top_rated`. The `tmdb_top_rated` attribute only supports a single integer value. The `sync_mode: sync` option is recommended since the list is continuously updated.
|
||||
|
||||
```yaml
|
||||
collections:
|
||||
TMDb Top Rated:
|
||||
tmdb_top_rated: 30
|
||||
sync_mode: sync
|
||||
```
|
||||
|
||||
#### TMDb Now Playing (List Type)
|
||||
|
||||
###### Works with Movie Libraries
|
||||
|
||||
You can build a collection using TMDb's release_type to get movies that are now in theaters by using `tmdb_now_playing`. The `tmdb_now_playing` attribute only supports a single integer value. The `sync_mode: sync` option is recommended since the list is continuously updated.
|
||||
|
||||
```yaml
|
||||
collections:
|
||||
TMDb Now Playing:
|
||||
tmdb_now_playing: 30
|
||||
sync_mode: sync
|
||||
```
|
||||
|
||||
#### TMDb Discover (List Type)
|
||||
|
||||
###### Works with Movie and TV Show Libraries
|
||||
|
||||
You can use [TMDb's discover engine](https://www.themoviedb.org/documentation/api/discover) to create a collection based on the search for movies/shows using all different sorts of parameters shown below. The parameters are directly from [TMDb Movie Discover](https://developers.themoviedb.org/3/discover/movie-discover) and [TMDb TV Discover](https://developers.themoviedb.org/3/discover/tv-discover)
|
||||
|
||||
##### TMDb Discover Parameters For Movies
|
||||
- `limit` (Specify how many movies you want returned by the query. Value must be an integer greater then 0. default: 100)
|
||||
- `language` (Specify a language to query translatable fields with. pattern: `([a-z]{2})-([A-Z]{2})` default: en-US)
|
||||
- `region` (Specify a [ISO 3166-1 code](https://en.wikipedia.org/wiki/List_of_ISO_3166_country_codes) to filter release dates. Must be uppercase. pattern: `^[A-Z]{2}$`)
|
||||
- `sort_by` (Choose from one of the many available sort options. Allowed Values: `popularity.asc`, `popularity.desc`, `release_date.asc`, `release_date.desc`, `revenue.asc`, `revenue.desc`, `primary_release_date.asc`, `primary_release_date.desc`, `original_title.asc`, `original_title.desc`, `vote_average.asc`, `vote_average.desc`, `vote_count.asc`, `vote_count.desc` default: `popularity.desc`)
|
||||
- `certification_country` (Used in conjunction with the certification parameter, use this to specify a country with a valid certification.)
|
||||
- `certification` (Filter results with a valid certification from the `certification_country` parameter.)
|
||||
- `certification.lte` (Filter and only include movies that have a certification that is less than or equal to the specified value.)
|
||||
- `certification.gte` (Filter and only include movies that have a certification that is greater than or equal to the specified value.)
|
||||
- `include_adult` (A filter and include or exclude adult movies. Must be `true` or `false`)
|
||||
- `primary_release_year` (A filter to limit the results to a specific primary release year. Year must be a 4 digit integer i.e. 1990.)
|
||||
- `primary_release_date.gte` (Filter and only include movies that have a primary release date that is greater or equal to the specified value. Date must be in the MM/DD/YYYY Format.)
|
||||
- `primary_release_date.lte` (Filter and only include movies that have a primary release date that is less than or equal to the specified value. Date must be in the MM/DD/YYYY Format.)
|
||||
- `release_date.gte` (Filter and only include movies that have a release date (looking at all release dates) that is greater or equal to the specified value. Date must be in the MM/DD/YYYY Format.)
|
||||
- `release_date.lte` (Filter and only include movies that have a release date (looking at all release dates) that is less than or equal to the specified value. Date must be in the MM/DD/YYYY Format.)
|
||||
- `year` (A filter to limit the results to a specific year (looking at all release dates). Year must be a 4 digit integer i.e. 1990.)
|
||||
- `vote_count.gte` (Filter and only include movies that have a vote count that is greater or equal to the specified value. Value must be an integer greater then 0.)
|
||||
- `vote_count.lte` (Filter and only include movies that have a vote count that is less than or equal to the specified value. Value must be an integer greater then 0.)
|
||||
- `vote_average.gte` (Filter and only include movies that have a rating that is greater or equal to the specified value. Value must be a number greater then 0.)
|
||||
- `vote_average.lte` (Filter and only include movies that have a rating that is less than or equal to the specified value. Value must be an number greater then 0.)
|
||||
- `with_cast` (A comma separated list of person ID's. Only include movies that have one of the ID's added as an actor.)
|
||||
- `with_crew` (A comma separated list of person ID's. Only include movies that have one of the ID's added as a crew member.)
|
||||
- `with_people` (A comma separated list of person ID's. Only include movies that have one of the ID's added as a either a actor or a crew member.)
|
||||
- `with_companies` (A comma separated list of production company ID's. Only include movies that have one of the ID's added as a production company.)
|
||||
- `with_genres` (Comma separated value of genre ids that you want to include in the results.)
|
||||
- `without_genres` (Comma separated value of genre ids that you want to exclude from the results.)
|
||||
- `with_keywords` (A comma separated list of keyword ID's. Only includes movies that have one of the ID's added as a keyword.)
|
||||
- `without_keywords` (Exclude items with certain keywords. You can comma and pipe seperate these values to create an 'AND' or 'OR' logic.)
|
||||
- `with_runtime.gte` (Filter and only include movies that have a runtime that is greater or equal to a value. Value must be an integer greater then 0.)
|
||||
- `with_runtime.lte` (Filter and only include movies that have a runtime that is less than or equal to a value. Value must be an integer greater then 0.)
|
||||
- `with_original_language` (Specify an ISO 639-1 string to filter results by their original language value.)
|
||||
|
||||
##### TMDb Discover Parameters For Shows
|
||||
- `limit` (Specify how many movies you want returned by the query. Value must be an integer greater then 0. default: 100)
|
||||
- `language` (Specify a language to query translatable fields with. pattern: `([a-z]{2})-([A-Z]{2})` default: en-US)
|
||||
- `sort_by` (Choose from one of the many available sort options. Allowed Values: `vote_average.desc`, `vote_average.asc`, `first_air_date.desc`, `first_air_date.asc`, `popularity.desc`, `popularity.asc` default: `popularity.desc`)
|
||||
- `air_date.gte` (Filter and only include TV shows that have a air date (by looking at all episodes) that is greater or equal to the specified value. Date must be in the MM/DD/YYYY Format.)
|
||||
- `air_date.lte` (Filter and only include TV shows that have a air date (by looking at all episodes) that is less than or equal to the specified value. Date must be in the MM/DD/YYYY Format.)
|
||||
- `first_air_date.gte` (Filter and only include TV shows that have a original air date that is greater or equal to the specified value. Can be used in conjunction with the `include_null_first_air_dates` filter if you want to include items with no air date. Date must be in the MM/DD/YYYY Format.)
|
||||
- `first_air_date.lte` (Filter and only include TV shows that have a original air date that is less than or equal to the specified value. Can be used in conjunction with the `include_null_first_air_dates` filter if you want to include items with no air date. Date must be in the MM/DD/YYYY Format.)
|
||||
- `first_air_date_year` (Filter and only include TV shows that have a original air date year that equal to the specified value. Can be used in conjunction with the `include_null_first_air_dates` filter if you want to include items with no air date. Year must be a 4 digit integer i.e. 1990.)
|
||||
- `include_null_first_air_dates` (Use this filter to include TV shows that don't have an air date while using any of the `first_air_date` filters. Must be `true` or `false`.)
|
||||
"- `timezone` (Used in conjunction with the `air_date.gte/lte` filter to calculate the proper UTC offset. default: America/New_York)
|
||||
- `vote_count.gte` (Filter and only include TV that have a vote count that is greater or equal to the specified value. Value must be an integer greater then 0.)
|
||||
- `vote_count.lte` (Filter and only include TV that have a vote count that is less than or equal to the specified value. Value must be an integer greater then 0.)
|
||||
- `vote_average.gte` (Filter and only include TV that have a rating that is greater or equal to the specified value. Value must be a number greater then 0.)
|
||||
- `vote_average.lte` (Filter and only include TV that have a rating that is less than or equal to the specified value. Value must be an number greater then 0.)
|
||||
- `with_networks` (Comma separated value of network ids that you want to include in the results.)
|
||||
- `with_companies` (A comma separated list of production company ID's. Only include movies that have one of the ID's added as a production company.)
|
||||
- `with_genres` (Comma separated value of genre ids that you want to include in the results.)
|
||||
- `without_genres` (Comma separated value of genre ids that you want to exclude from the results.)
|
||||
- `with_keywords` (A comma separated list of keyword ID's. Only includes TV shows that have one of the ID's added as a keyword.)
|
||||
- `without_keywords` (Exclude items with certain keywords. You can comma and pipe seperate these values to create an 'AND' or 'OR' logic.)
|
||||
- `with_runtime.gte` (Filter and only include TV shows with an episode runtime that is greater than or equal to a value.)
|
||||
- `with_runtime.lte` (Filter and only include TV shows with an episode runtime that is less than or equal to a value.)
|
||||
- `with_original_language` (Specify an ISO 639-1 string to filter results by their original language value.)
|
||||
- `screened_theatrically` (Filter results to include items that have been screened theatrically. Must be `true` or `false`.)
|
||||
|
||||
```yaml
|
||||
collections:
|
||||
Movies Released in October 2020:
|
||||
tmdb_discover:
|
||||
primary_release_date.gte: 10/01/2020
|
||||
primary_release_date.lte: 10/31/2020
|
||||
```
|
||||
```yaml
|
||||
collections:
|
||||
Popular Movies:
|
||||
tmdb_discover:
|
||||
sort_by: popularity.desc
|
||||
```
|
||||
```yaml
|
||||
collections:
|
||||
Highest Rated R Movies:
|
||||
tmdb_discover:
|
||||
certification_country: US
|
||||
certification: R
|
||||
sort_by: vote_average.desc
|
||||
```
|
||||
```yaml
|
||||
collections:
|
||||
Most Popular Kids Movies:
|
||||
tmdb_discover:
|
||||
certification_country: US
|
||||
certification.lte: G
|
||||
sort_by: popularity.desc
|
||||
```
|
||||
```yaml
|
||||
collections:
|
||||
Highest Rated Movies From 2010:
|
||||
tmdb_discover:
|
||||
primary_release_year: 2010
|
||||
sort_by: vote_average.desc
|
||||
```
|
||||
```yaml
|
||||
collections:
|
||||
Best Dramas From 2014:
|
||||
tmdb_discover:
|
||||
with_genres: 18
|
||||
primary_release_year: 2014
|
||||
sort_by: vote_average.desc
|
||||
```
|
||||
```yaml
|
||||
collections:
|
||||
Highest Rated Science Fiction Movies with Tom Cruise:
|
||||
tmdb_discover:
|
||||
with_genres: 878
|
||||
with_cast: 500
|
||||
sort_by: vote_average.desc
|
||||
```
|
||||
```yaml
|
||||
collections:
|
||||
Highest Grossing Comedy Movies with Will Ferrell:
|
||||
tmdb_discover:
|
||||
with_genres: 35
|
||||
with_cast: 23659
|
||||
sort_by: revenue.desc
|
||||
```
|
||||
```yaml
|
||||
collections:
|
||||
Top Rated Movies with Brad Pitt and Edward Norton:
|
||||
tmdb_discover:
|
||||
with_people: 287,819
|
||||
sort_by: vote_average.desc
|
||||
```
|
||||
```yaml
|
||||
collections:
|
||||
Popular Movies with David Fincher and Rooney Mara:
|
||||
tmdb_discover:
|
||||
with_people: 108916,7467
|
||||
sort_by: popularity.desc
|
||||
```
|
||||
```yaml
|
||||
collections:
|
||||
Top Rated Dramas:
|
||||
tmdb_discover:
|
||||
with_genres: 18
|
||||
sort_by: vote_average.desc
|
||||
vote_count.gte: 10
|
||||
```
|
||||
```yaml
|
||||
collections:
|
||||
Highest Grossing R Movies with Liam Neeson:
|
||||
tmdb_discover:
|
||||
certification_country: US
|
||||
certification: R
|
||||
sort_by: revenue.desc
|
||||
with_cast: 3896
|
||||
```
|
||||
|
||||
#### TMDb List (List Type)
|
||||
|
||||
###### Works with Movie and TV Show Libraries
|
||||
|
@ -476,7 +743,7 @@ This script can pull a number of items from the Trakt Trending List for [Movies]
|
|||
|
||||
```yaml
|
||||
collections:
|
||||
Trending:
|
||||
Trakt Trending:
|
||||
trakt_trending: 30
|
||||
sync_mode: sync
|
||||
```
|
||||
|
|
|
@ -2,14 +2,19 @@ import re
|
|||
import requests
|
||||
import math
|
||||
import sys
|
||||
import os
|
||||
from urllib.parse import urlparse
|
||||
from lxml import html
|
||||
from tmdbv3api import TMDb
|
||||
from tmdbv3api import Movie
|
||||
from tmdbv3api import List
|
||||
from tmdbv3api import TV
|
||||
from tmdbv3api import Discover
|
||||
from tmdbv3api import Collection
|
||||
from tmdbv3api import Company
|
||||
#from tmdbv3api import Network #TURNON:Trending
|
||||
from tmdbv3api import Person
|
||||
#from tmdbv3api import Trending #TURNON:Trending
|
||||
import config_tools
|
||||
import plex_tools
|
||||
import trakt
|
||||
|
@ -95,7 +100,7 @@ def imdb_get_movies(config_path, plex, data):
|
|||
if not tmdb.api_key == "None":
|
||||
tmdb_id = m.guid.split('themoviedb://')[1].split('?')[0]
|
||||
tmdbapi = movie.details(tmdb_id)
|
||||
imdb_id = tmdbapi.imdb_id
|
||||
imdb_id = tmdbapi.imdb_id if hasattr(tmdbapi, 'imdb_id') else None
|
||||
else:
|
||||
imdb_id = None
|
||||
elif 'imdb://' in m.guid:
|
||||
|
@ -119,36 +124,93 @@ def imdb_get_movies(config_path, plex, data):
|
|||
|
||||
return matched_imdb_movies, missing_imdb_movies
|
||||
|
||||
|
||||
def tmdb_get_movies(config_path, plex, data, is_list=False):
|
||||
tmdb_id = int(data)
|
||||
def tmdb_get_movies(config_path, plex, data, method):
|
||||
t_movs = []
|
||||
t_movie = Movie()
|
||||
t_movie.api_key = config_tools.TMDB(config_path).apikey # Set TMDb api key for Movie
|
||||
if t_movie.api_key == "None":
|
||||
raise KeyError("Invalid TMDb API Key")
|
||||
|
||||
tmdb = List() if is_list else Collection()
|
||||
tmdb.api_key = t_movie.api_key
|
||||
t_col = tmdb.details(tmdb_id)
|
||||
|
||||
if is_list:
|
||||
try:
|
||||
for tmovie in t_col:
|
||||
if tmovie.media_type == "movie":
|
||||
t_movs.append(tmovie.id)
|
||||
except:
|
||||
raise ValueError("| Config Error: TMDb List: {} not found".format(tmdb_id))
|
||||
count = 0
|
||||
if method == "tmdb_discover":
|
||||
discover = Discover()
|
||||
discover.api_key = t_movie.api_key
|
||||
discover.discover_movies(data)
|
||||
total_pages = int(os.environ["total_pages"])
|
||||
total_results = int(os.environ["total_results"])
|
||||
limit = int(data.pop('limit'))
|
||||
amount = total_results if total_results < limit else limit
|
||||
print("| Processing {}: {} items".format(method, amount))
|
||||
for attr, value in data.items():
|
||||
print("| {}: {}".format(attr, value))
|
||||
for x in range(total_pages):
|
||||
data["page"] = x + 1
|
||||
tmdb_movies = discover.discover_movies(data)
|
||||
for tmovie in tmdb_movies:
|
||||
count += 1
|
||||
t_movs.append(tmovie.id)
|
||||
if count == amount:
|
||||
break
|
||||
if count == amount:
|
||||
break
|
||||
elif method in ["tmdb_popular", "tmdb_top_rated", "tmdb_now_playing", "tmdb_trending_daily", "tmdb_trending_weekly"]:
|
||||
#trending = Trending() #TURNON:Trending
|
||||
#trending.api_key = t_movie.api_key #TURNON:Trending
|
||||
for x in range(int(data / 20) + 1):
|
||||
if method == "tmdb_popular":
|
||||
tmdb_movies = t_movie.popular(x + 1)
|
||||
elif method == "tmdb_top_rated":
|
||||
tmdb_movies = t_movie.top_rated(x + 1)
|
||||
elif method == "tmdb_now_playing":
|
||||
tmdb_movies = t_movie.now_playing(x + 1)
|
||||
#elif method == "tmdb_trending_daily": #TURNON:Trending
|
||||
# tmdb_movies = trending.movie_day(x + 1) #TURNON:Trending
|
||||
#elif method == "tmdb_trending_weekly": #TURNON:Trending
|
||||
# tmdb_movies = trending.movie_week(x + 1) #TURNON:Trending
|
||||
for tmovie in tmdb_movies:
|
||||
count += 1
|
||||
t_movs.append(tmovie.id)
|
||||
if count == data:
|
||||
break
|
||||
if count == data:
|
||||
break
|
||||
print("| Processing {}: {} Items".format(method, data))
|
||||
else:
|
||||
try:
|
||||
for tmovie in t_col.parts:
|
||||
t_movs.append(tmovie['id'])
|
||||
except AttributeError:
|
||||
tmdb_id = int(data)
|
||||
if method == "tmdb_list":
|
||||
tmdb = List()
|
||||
tmdb.api_key = t_movie.api_key
|
||||
try:
|
||||
t_movie.details(tmdb_id).imdb_id
|
||||
t_movs.append(tmdb_id)
|
||||
t_col = tmdb.details(tmdb_id)
|
||||
tmdb_name = str(t_col)
|
||||
for tmovie in t_col:
|
||||
if tmovie.media_type == "movie":
|
||||
t_movs.append(tmovie.id)
|
||||
except:
|
||||
raise ValueError("| Config Error: TMDb ID: {} not found".format(tmdb_id))
|
||||
raise ValueError("| Config Error: TMDb List: {} not found".format(tmdb_id))
|
||||
elif method == "tmdb_company":
|
||||
tmdb = Company()
|
||||
tmdb.api_key = t_movie.api_key
|
||||
tmdb_name = str(tmdb.details(tmdb_id))
|
||||
company_movies = tmdb.movies(tmdb_id)
|
||||
for tmovie in company_movies:
|
||||
t_movs.append(tmovie.id)
|
||||
else:
|
||||
tmdb = Collection()
|
||||
tmdb.api_key = t_movie.api_key
|
||||
t_col = tmdb.details(tmdb_id)
|
||||
tmdb_name = str(t_col)
|
||||
try:
|
||||
for tmovie in t_col.parts:
|
||||
t_movs.append(tmovie['id'])
|
||||
except AttributeError:
|
||||
try:
|
||||
t_movie.details(tmdb_id).imdb_id
|
||||
tmdb_name = str(t_movie.details(tmdb_id))
|
||||
t_movs.append(tmdb_id)
|
||||
except:
|
||||
raise ValueError("| Config Error: TMDb ID: {} not found".format(tmdb_id))
|
||||
print("| Processing {}: ({}) {}".format(method, tmdb_id, tmdb_name))
|
||||
|
||||
|
||||
# Create dictionary of movies and their guid
|
||||
|
@ -250,33 +312,92 @@ def get_tvdb_id_from_tmdb_id(id):
|
|||
else:
|
||||
return None
|
||||
|
||||
def tmdb_get_shows(config_path, plex, data, is_list=False):
|
||||
def tmdb_get_shows(config_path, plex, data, method):
|
||||
config_tools.TraktClient(config_path)
|
||||
|
||||
tmdb_id = int(data)
|
||||
|
||||
t_tvs = []
|
||||
t_tv = TV()
|
||||
t_tv.api_key = config_tools.TMDB(config_path).apikey # Set TMDb api key for Movie
|
||||
if t_tv.api_key == "None":
|
||||
raise KeyError("Invalid TMDb API Key")
|
||||
discover = Discover()
|
||||
discover.api_key = t_tv.api_key
|
||||
|
||||
if is_list:
|
||||
tmdb = List()
|
||||
tmdb.api_key = t_tv.api_key
|
||||
try:
|
||||
t_col = tmdb.details(tmdb_id)
|
||||
for ttv in t_col:
|
||||
if ttv.media_type == "tv":
|
||||
t_tvs.append(ttv.id)
|
||||
except:
|
||||
raise ValueError("| Config Error: TMDb List: {} not found".format(tmdb_id))
|
||||
count = 0
|
||||
if method == "tmdb_discover":
|
||||
discover.discover_tv_shows(data)
|
||||
total_pages = int(os.environ["total_pages"])
|
||||
total_results = int(os.environ["total_results"])
|
||||
limit = int(data.pop('limit'))
|
||||
amount = total_results if total_results < limit else limit
|
||||
print("| Processing {}: {} items".format(method, amount))
|
||||
for attr, value in data.items():
|
||||
print("| {}: {}".format(attr, value))
|
||||
for x in range(total_pages):
|
||||
data["page"] = x + 1
|
||||
tmdb_shows = discover.discover_tv_shows(data)
|
||||
for tshow in tmdb_shows:
|
||||
count += 1
|
||||
t_tvs.append(tshow.id)
|
||||
if count == amount:
|
||||
break
|
||||
if count == amount:
|
||||
break
|
||||
run_discover(data)
|
||||
elif method in ["tmdb_popular", "tmdb_top_rated", "tmdb_trending_daily", "tmdb_trending_weekly"]:
|
||||
#trending = Trending() #TURNON:Trending
|
||||
#trending.api_key = t_movie.api_key #TURNON:Trending
|
||||
for x in range(int(data / 20) + 1):
|
||||
if method == "tmdb_popular":
|
||||
tmdb_shows = t_tv.popular(x + 1)
|
||||
elif method == "tmdb_top_rated":
|
||||
tmdb_shows = t_tv.top_rated(x + 1)
|
||||
#elif method == "tmdb_trending_daily": #TURNON:Trending
|
||||
# tmdb_shows = trending.tv_day(x + 1) #TURNON:Trending
|
||||
#elif method == "tmdb_trending_weekly": #TURNON:Trending
|
||||
# tmdb_shows = trending.tv_week(x + 1) #TURNON:Trending
|
||||
for tshow in tmdb_shows:
|
||||
count += 1
|
||||
t_tvs.append(tshow.id)
|
||||
if count == amount:
|
||||
break
|
||||
if count == amount:
|
||||
break
|
||||
print("| Processing {}: {} Items".format(method, data))
|
||||
else:
|
||||
try:
|
||||
t_tv.details(tmdb_id).number_of_seasons
|
||||
t_tvs.append(tmdb_id)
|
||||
except:
|
||||
raise ValueError("| Config Error: TMDb ID: {} not found".format(tmdb_id))
|
||||
tmdb_id = int(data)
|
||||
if method == "tmdb_list":
|
||||
tmdb = List()
|
||||
tmdb.api_key = t_tv.api_key
|
||||
try:
|
||||
t_col = tmdb.details(tmdb_id)
|
||||
tmdb_name = str(t_col)
|
||||
for ttv in t_col:
|
||||
if ttv.media_type == "tv":
|
||||
t_tvs.append(ttv.id)
|
||||
except:
|
||||
raise ValueError("| Config Error: TMDb List: {} not found".format(tmdb_id))
|
||||
elif method in ["tmdb_company", "tmdb_network"]:
|
||||
if method == "tmdb_company":
|
||||
tmdb = Company()
|
||||
tmdb.api_key = t_tv.api_key
|
||||
tmdb_name = str(tmdb.details(tmdb_id))
|
||||
else:
|
||||
#tmdb = Network() #TURNON:Trending
|
||||
#tmdb.api_key = t_tv.api_key #TURNON:Trending
|
||||
tmdb_name = ""#str(tmdb.details(tmdb_id)) #TURNON:Trending
|
||||
discover_method = "with_companies" if method == "tmdb_company" else "with_networks"
|
||||
tmdb_shows = discover.discover_tv_shows({discover_method: tmdb_id})
|
||||
for tshow in tmdb_shows:
|
||||
t_tvs.append(tshow.id)
|
||||
else:
|
||||
try:
|
||||
t_tv.details(tmdb_id).number_of_seasons
|
||||
tmdb_name = str(t_tv.details(tmdb_id))
|
||||
t_tvs.append(tmdb_id)
|
||||
except:
|
||||
raise ValueError("| Config Error: TMDb ID: {} not found".format(tmdb_id))
|
||||
print("| Processing {}: ({}) {}".format(method, tmdb_id, tmdb_name))
|
||||
|
||||
p_tv_map = {}
|
||||
for item in plex.Library.all():
|
||||
|
@ -310,7 +431,7 @@ def tmdb_get_shows(config_path, plex, data, is_list=False):
|
|||
|
||||
return matched, missing
|
||||
|
||||
def tvdb_get_shows(config_path, plex, data, is_list=False):
|
||||
def tvdb_get_shows(config_path, plex, data):
|
||||
config_tools.TraktClient(config_path)
|
||||
|
||||
id = int(data)
|
||||
|
|
|
@ -131,12 +131,21 @@ def update_from_config(config_path, plex, headless=False, no_meta=False, no_imag
|
|||
"collection_sort": "collection_order"
|
||||
}
|
||||
all_lists = [
|
||||
"plex_search"
|
||||
"plex_search",
|
||||
"plex_collection",
|
||||
"tmdb_collection",
|
||||
"tmdb_id",
|
||||
"tmdb_actor",
|
||||
"tmdb_director"
|
||||
"tmdb_writer"
|
||||
"tmdb_director",
|
||||
"tmdb_writer",
|
||||
"tmdb_company",
|
||||
"tmdb_network",
|
||||
"tmdb_discover",
|
||||
"tmdb_popular",
|
||||
"tmdb_top_rated",
|
||||
"tmdb_now_playing",
|
||||
#"tmdb_trending_daily", #TURNON:Trending
|
||||
#"tmdb_trending_weekly", #TURNON:Trending
|
||||
"tmdb_list",
|
||||
"tmdb_movie",
|
||||
"tmdb_show",
|
||||
|
@ -161,13 +170,16 @@ def update_from_config(config_path, plex, headless=False, no_meta=False, no_imag
|
|||
show_only_lists = [
|
||||
"tmdb_show",
|
||||
"tvdb_show"
|
||||
"tmdb_network",
|
||||
]
|
||||
movie_only_lists = [
|
||||
"tmdb_collection",
|
||||
"tmdb_id",
|
||||
"tmdb_actor",
|
||||
"tmdb_company",
|
||||
"tmdb_director",
|
||||
"tmdb_writer",
|
||||
"tmdb_now_playing",
|
||||
"tmdb_movie",
|
||||
"imdb_list",
|
||||
]
|
||||
|
@ -211,11 +223,53 @@ def update_from_config(config_path, plex, headless=False, no_meta=False, no_imag
|
|||
"background", "file_background",
|
||||
"name_mapping"
|
||||
]
|
||||
discover_movie = [
|
||||
"language", "with_original_language", "region", "sort_by",
|
||||
"certification_country", "certification", "certification.lte", "certification.gte",
|
||||
"include_adult",
|
||||
"primary_release_year", "primary_release_date.gte", "primary_release_date.lte",
|
||||
"release_date.gte", "release_date.lte", "year",
|
||||
"vote_count.gte", "vote_count.lte",
|
||||
"vote_average.gte", "vote_average.lte",
|
||||
"with_cast", "with_crew", "with_people",
|
||||
"with_companies",
|
||||
"with_genres", "without_genres",
|
||||
"with_keywords", "without_keywords",
|
||||
"with_runtime.gte", "with_runtime.lte"
|
||||
]
|
||||
discover_tv = [
|
||||
"language", "with_original_language", "timezone", "sort_by",
|
||||
"air_date.gte", "air_date.lte",
|
||||
"first_air_date.gte", "first_air_date.lte", "first_air_date_year",
|
||||
"vote_count.gte", "vote_count.lte",
|
||||
"vote_average.gte", "vote_average.lte",
|
||||
"with_genres", "without_genres",
|
||||
"with_keywords", "without_keywords",
|
||||
"with_networks", "with_companies",
|
||||
"with_runtime.gte", "with_runtime.lte",
|
||||
"include_null_first_air_dates",
|
||||
"screened_theatrically"
|
||||
]
|
||||
discover_movie_sort = [
|
||||
"popularity.asc", "popularity.desc",
|
||||
"release_date.asc", "release_date.desc",
|
||||
"revenue.asc", "revenue.desc",
|
||||
"primary_release_date.asc", "primary_release_date.desc",
|
||||
"original_title.asc", "original_title.desc",
|
||||
"vote_average.asc", "vote_average.desc",
|
||||
"vote_count.asc", "vote_count.desc"
|
||||
]
|
||||
discover_tv_sort = [
|
||||
"vote_average.desc", "vote_average.asc",
|
||||
"first_air_date.desc", "first_air_date.asc",
|
||||
"popularity.desc", "popularity.asc"
|
||||
]
|
||||
print("|\n| Running collection update press Ctrl+C to abort at anytime")
|
||||
for c in collections:
|
||||
print("| \n|===================================================================================================|\n|")
|
||||
print("| Updating collection: {}...".format(c))
|
||||
map = {}
|
||||
|
||||
sync_collection = True if plex.sync_mode == "sync" else False
|
||||
if "sync_mode" in collections[c]:
|
||||
if collections[c]["sync_mode"]:
|
||||
|
@ -230,10 +284,12 @@ def update_from_config(config_path, plex, headless=False, no_meta=False, no_imag
|
|||
print("| Config Error: sync_mode attribute is blank")
|
||||
if sync_collection == True:
|
||||
print("| Sync Mode: sync")
|
||||
plex_collection = get_collection(plex, c, headless)
|
||||
if isinstance(plex_collection, Collections):
|
||||
try:
|
||||
plex_collection = get_collection(plex, c, headless)
|
||||
for item in plex_collection.children:
|
||||
map[item.ratingKey] = item
|
||||
except ValueError as e:
|
||||
print("| Config Error: {}".format(e))
|
||||
else:
|
||||
print("| Sync Mode: append")
|
||||
|
||||
|
@ -251,10 +307,13 @@ def update_from_config(config_path, plex, headless=False, no_meta=False, no_imag
|
|||
for m in collections[c]:
|
||||
if ("tmdb" in m or "imdb" in m) and not TMDB.valid:
|
||||
print("| Config Error: {} skipped. tmdb incorrectly configured".format(m))
|
||||
map = {}
|
||||
elif ("trakt" in m or (("tmdb" in m or "tvdb" in m) and plex.library_type == "show")) and not TraktClient.valid:
|
||||
print("| Config Error: {} skipped. trakt incorrectly configured".format(m))
|
||||
map = {}
|
||||
elif m == "tautulli" and not Tautulli.valid:
|
||||
print("| Config Error: {} skipped. tautulli incorrectly configured".format(m))
|
||||
map = {}
|
||||
elif collections[c][m]:
|
||||
if m in alias:
|
||||
method_name = alias[m]
|
||||
|
@ -331,45 +390,6 @@ def update_from_config(config_path, plex, headless=False, no_meta=False, no_imag
|
|||
print("| Config Error: {} attribute not supported".format(detail_name))
|
||||
elif method_name in all_details:
|
||||
check_details(method_name, collections[c][m])
|
||||
elif method_name == "filters":
|
||||
for filter in collections[c][m]:
|
||||
if filter in alias or (filter.endswith(".not") and filter[:-4] in alias):
|
||||
final_filter = (alias[filter[:-4]] + filter[-4:]) if filter.endswith(".not") else alias[filter]
|
||||
print("| Config Warning: {} filter will run as {}".format(filter, final_filter))
|
||||
else:
|
||||
final_filter = filter
|
||||
if final_filter in movie_only_filters and libtype == "show":
|
||||
print("| Config Error: {} filter only works for movie libraries".format(final_filter))
|
||||
elif final_filter in all_filters:
|
||||
filters.append((final_filter, collections[c][m][filter])) #TODO: validate filters contents
|
||||
else:
|
||||
print("| Config Error: {} filter not supported".format(filter))
|
||||
elif method_name == "plex_search":
|
||||
search = []
|
||||
searches_used = []
|
||||
for search_attr in collections[c][m]:
|
||||
if search_attr in alias or (search_attr.endswith(".not") and search_attr[:-4] in alias):
|
||||
final_attr = (alias[search_attr[:-4]] + search_attr[-4:]) if search_attr.endswith(".not") else alias[search_attr]
|
||||
print("| Config Warning: {} plex search attribute will run as {}".format(search_attr, final_attr))
|
||||
else:
|
||||
final_attr = search_attr
|
||||
if final_attr in movie_only_searches and libtype == "show":
|
||||
print("| Config Error: {} plex search attribute only works for movie libraries".format(final_attr))
|
||||
elif (final_attr[:-4] if final_attr.endswith(".not") else final_attr) in searches_used:
|
||||
print("| Config Error: Only one instance of {} can be used try using it as a filter instead".format(final_attr))
|
||||
elif final_attr in ["year", "year.not"]:
|
||||
year_pair = get_method_pair_year(final_attr, collections[c][m][search_attr])
|
||||
if len(year_pair[1]) > 0:
|
||||
searches_used.append(final_attr[:-4] if final_attr.endswith(".not") else final_attr)
|
||||
search.append(get_method_pair_int(final_attr, collections[c][m][search_attr], final_attr[:-4] if final_attr.endswith(".not") else final_attr))
|
||||
elif final_attr in plex_searches:
|
||||
if final_attr.startswith("tmdb_"):
|
||||
final_attr = final_attr[5:]
|
||||
searches_used.append(final_attr[:-4] if final_attr.endswith(".not") else final_attr)
|
||||
search.append((final_attr, get_attribute_list(collections[c][m][search_attr])))
|
||||
else:
|
||||
print("| Config Error: {} plex search attribute not supported".format(search_attr))
|
||||
methods.append((method_name, [search]))
|
||||
elif method_name in movie_only_searches and libtype == "show":
|
||||
print("| Config Error: {} plex search only works for movie libraries".format(method_name))
|
||||
elif method_name in ["year", "year.not"]:
|
||||
|
@ -396,8 +416,20 @@ def update_from_config(config_path, plex, headless=False, no_meta=False, no_imag
|
|||
methods.append(("plex_search", [[(method_name[5:], new_ids)]]))
|
||||
elif method_name in plex_searches:
|
||||
methods.append(("plex_search", [[(method_name, get_attribute_list(collections[c][m]))]]))
|
||||
elif method_name == "plex_collection":
|
||||
collection_list = collections[c][m] if isinstance(collections[c][m], list) else [collections[c][m]]
|
||||
final_collections = []
|
||||
for new_collection in collection_list:
|
||||
try:
|
||||
final_collections.append(get_collection(plex, new_collection, headless))
|
||||
except ValueError as e:
|
||||
print("| Config Error: {} {}".format(method_name, new_collection))
|
||||
if len(final_collections) > 0:
|
||||
methods.append(("plex_collection", final_collections))
|
||||
elif method_name == "tmdb_collection":
|
||||
methods.append(get_method_pair_tmdb(method_name, collections[c][m], "TMDb Collection ID"))
|
||||
elif method_name == "tmdb_company":
|
||||
methods.append(get_method_pair_int(method_name, collections[c][m], "TMDb Company ID"))
|
||||
elif method_name == "tmdb_id":
|
||||
id = get_method_pair_tmdb(method_name, collections[c][m], "TMDb ID")
|
||||
if tmdb_id is None:
|
||||
|
@ -407,10 +439,14 @@ def update_from_config(config_path, plex, headless=False, no_meta=False, no_imag
|
|||
details["poster"] = ["url", tmdb_get_metadata(config_path, id[1][0], "backdrop_path"), method_name]
|
||||
tmdb_id = id[1][0]
|
||||
methods.append(id)
|
||||
elif method_name == "tmdb_list": #TODO: validate
|
||||
elif method_name in ["tmdb_popular", "tmdb_top_rated", "tmdb_now_playing", "tmdb_trending_daily", "tmdb_trending_weekly"]:
|
||||
methods.append((method_name, [regex_first_int(collections[c][m], method_name, default=20)]))
|
||||
elif method_name == "tmdb_list":
|
||||
methods.append(get_method_pair_int(method_name, collections[c][m], "TMDb List ID"))
|
||||
elif method_name == "tmdb_movie":
|
||||
methods.append(get_method_pair_tmdb(method_name, collections[c][m], "TMDb Movie ID"))
|
||||
elif method_name == "tmdb_network":
|
||||
methods.append(get_method_pair_int(method_name, collections[c][m], "TMDb Network ID"))
|
||||
elif method_name == "tmdb_show":
|
||||
methods.append(get_method_pair_tmdb(method_name, collections[c][m], "TMDb Show ID"))
|
||||
elif method_name == "tvdb_show":
|
||||
|
@ -429,16 +465,129 @@ def update_from_config(config_path, plex, headless=False, no_meta=False, no_imag
|
|||
methods.append((method_name, [regex_first_int(collections[c][m], method_name, default=30)]))
|
||||
elif method_name == "trakt_watchlist":
|
||||
methods.append((method_name, get_attribute_list(collections[c][m])))
|
||||
elif method_name == "tautulli": #TODO:test
|
||||
try:
|
||||
new_dictionary = {}
|
||||
new_dictionary["list_type"] = check_for_attribute(collections[c][m], "list_type", parent="tautulli", test_list=["popular", "watched"], options="| \tpopular (Most Popular List)\n| \twatched (Most Watched List)", throw=True, save=False)
|
||||
new_dictionary["list_days"] = check_for_attribute(collections[c][m], "list_days", parent="tautulli", var_type="int", default=30, save=False)
|
||||
new_dictionary["list_size"] = check_for_attribute(collections[c][m], "list_size", parent="tautulli", var_type="int", default=10, save=False)
|
||||
new_dictionary["list_buffer"] = check_for_attribute(collections[c][m], "list_buffer", parent="tautulli", var_type="int", default=20, save=False)
|
||||
methods.append((method_name, [new_dictionary]))
|
||||
except SystemExit as e:
|
||||
print(e)
|
||||
elif method_name in ["filters", "plex_search", "tmdb_discover", "tautulli"]:
|
||||
if isinstance(collections[c][m], dict):
|
||||
if method_name == "filters":
|
||||
for filter in collections[c][m]:
|
||||
if filter in alias or (filter.endswith(".not") and filter[:-4] in alias):
|
||||
final_filter = (alias[filter[:-4]] + filter[-4:]) if filter.endswith(".not") else alias[filter]
|
||||
print("| Config Warning: {} filter will run as {}".format(filter, final_filter))
|
||||
else:
|
||||
final_filter = filter
|
||||
if final_filter in movie_only_filters and libtype == "show":
|
||||
print("| Config Error: {} filter only works for movie libraries".format(final_filter))
|
||||
elif final_filter in all_filters:
|
||||
filters.append((final_filter, collections[c][m][filter])) #TODO: validate filters contents
|
||||
else:
|
||||
print("| Config Error: {} filter not supported".format(filter))
|
||||
elif method_name == "plex_search":
|
||||
search = []
|
||||
searches_used = []
|
||||
for search_attr in collections[c][m]:
|
||||
if search_attr in alias or (search_attr.endswith(".not") and search_attr[:-4] in alias):
|
||||
final_attr = (alias[search_attr[:-4]] + search_attr[-4:]) if search_attr.endswith(".not") else alias[search_attr]
|
||||
print("| Config Warning: {} plex search attribute will run as {}".format(search_attr, final_attr))
|
||||
else:
|
||||
final_attr = search_attr
|
||||
if final_attr in movie_only_searches and libtype == "show":
|
||||
print("| Config Error: {} plex search attribute only works for movie libraries".format(final_attr))
|
||||
elif (final_attr[:-4] if final_attr.endswith(".not") else final_attr) in searches_used:
|
||||
print("| Config Error: Only one instance of {} can be used try using it as a filter instead".format(final_attr))
|
||||
elif final_attr in ["year", "year.not"]:
|
||||
year_pair = get_method_pair_year(final_attr, collections[c][m][search_attr])
|
||||
if len(year_pair[1]) > 0:
|
||||
searches_used.append(final_attr[:-4] if final_attr.endswith(".not") else final_attr)
|
||||
search.append(get_method_pair_int(final_attr, collections[c][m][search_attr], final_attr[:-4] if final_attr.endswith(".not") else final_attr))
|
||||
elif final_attr in plex_searches:
|
||||
if final_attr.startswith("tmdb_"):
|
||||
final_attr = final_attr[5:]
|
||||
searches_used.append(final_attr[:-4] if final_attr.endswith(".not") else final_attr)
|
||||
search.append((final_attr, get_attribute_list(collections[c][m][search_attr])))
|
||||
else:
|
||||
print("| Config Error: {} plex search attribute not supported".format(search_attr))
|
||||
methods.append((method_name, [search]))
|
||||
elif method_name == "tmdb_discover":
|
||||
new_dictionary = {"limit": 100}
|
||||
for attr in collections[c][m]:
|
||||
if collections[c][m][attr]:
|
||||
attr_data = collections[c][m][attr]
|
||||
if (libtype == "movie" and attr in discover_movie) or (libtype == "show" and attr in discover_tv):
|
||||
if attr == "language":
|
||||
if re.compile("([a-z]{2})-([A-Z]{2})").match(str(attr_data)):
|
||||
new_dictionary[attr] = str(attr_data)
|
||||
else:
|
||||
print("| Config Error: Skipping {} attribute {}: {} must match pattern ([a-z]{2})-([A-Z]{2}) e.g. en-US".format(m, attr, attr_data))
|
||||
elif attr == "region":
|
||||
if re.compile("^[A-Z]{2}$").match(str(attr_data)):
|
||||
new_dictionary[attr] = str(attr_data)
|
||||
else:
|
||||
print("| Config Error: Skipping {} attribute {}: {} must match pattern ^[A-Z]{2}$ e.g. US".format(m, attr, attr_data))
|
||||
elif attr == "sort_by":
|
||||
if (libtype == "movie" and attr_data in discover_movie_sort) or (libtype == "show" and attr_data in discover_tv_sort):
|
||||
new_dictionary[attr] = attr_data
|
||||
else:
|
||||
print("| Config Error: Skipping {} attribute {}: {} is invalid".format(m, attr, attr_data))
|
||||
elif attr == "certification_country":
|
||||
if "certification" in collections[c][m] or "certification.lte" in collections[c][m] or "certification.gte" in collections[c][m]:
|
||||
new_dictionary[attr] = attr_data
|
||||
else:
|
||||
print("| Config Error: Skipping {} attribute {}: must be used with either certification, certification.lte, or certification.gte".format(m, attr))
|
||||
elif attr in ["certification", "certification.lte", "certification.gte"]:
|
||||
if "certification_country" in collections[c][m]:
|
||||
new_dictionary[attr] = attr_data
|
||||
else:
|
||||
print("| Config Error: Skipping {} attribute {}: must be used with certification_country".format(m, attr))
|
||||
elif attr in ["include_adult", "include_null_first_air_dates", "screened_theatrically"]:
|
||||
if attr_data is True:
|
||||
new_dictionary[attr] = attr_data
|
||||
elif attr in ["primary_release_date.gte", "primary_release_date.lte", "release_date.gte", "release_date.lte", "air_date.gte", "air_date.lte", "first_air_date.gte", "first_air_date.lte"]:
|
||||
if re.compile("[0-1]?[0-9][/-][0-3]?[0-9][/-][1-2][890][0-9][0-9]").match(str(attr_data)):
|
||||
the_date = str(attr_data).split("/") if "/" in str(attr_data) else str(attr_data).split("-")
|
||||
new_dictionary[attr] = "{}-{}-{}".format(the_date[2], the_date[0], the_date[1])
|
||||
elif re.compile("[1-2][890][0-9][0-9][/-][0-1]?[0-9][/-][0-3]?[0-9]").match(str(attr_data)):
|
||||
the_date = str(attr_data).split("/") if "/" in str(attr_data) else str(attr_data).split("-")
|
||||
new_dictionary[attr] = "{}-{}-{}".format(the_date[0], the_date[1], the_date[2])
|
||||
else:
|
||||
print("| Config Error: Skipping {} attribute {}: {} must match pattern MM/DD/YYYY e.g. 12/25/2020".format(m, attr, attr_data))
|
||||
elif attr in ["primary_release_year", "year", "first_air_date_year"]:
|
||||
if isinstance(attr_data, int) and 1800 < attr_data and attr_data < 2200:
|
||||
new_dictionary[attr] = attr_data
|
||||
else:
|
||||
print("| Config Error: Skipping {} attribute {}: must be a valid year e.g. 1990".format(m, attr))
|
||||
elif attr in ["vote_count.gte", "vote_count.lte", "vote_average.gte", "vote_average.lte", "with_runtime.gte", "with_runtime.lte"]:
|
||||
if (isinstance(attr_data, int) or isinstance(attr_data, float)) and 0 < attr_data:
|
||||
new_dictionary[attr] = attr_data
|
||||
else:
|
||||
print("| Config Error: Skipping {} attribute {}: must be a valid number greater then 0".format(m, attr))
|
||||
elif attr in ["with_cast", "with_crew", "with_people", "with_companies", "with_networks", "with_genres", "without_genres", "with_keywords", "without_keywords", "with_original_language", "timezone"]:
|
||||
new_dictionary[attr] = attr_data
|
||||
else:
|
||||
print("| Config Error: {} attribute {} not supported".format(m, attr))
|
||||
elif attr == "limit":
|
||||
if isinstance(attr_data, int) and attr_data > 0:
|
||||
new_dictionary[attr] = attr_data
|
||||
else:
|
||||
print("| Config Error: Skipping {} attribute {}: must be a valid number greater then 0".format(m, attr))
|
||||
else:
|
||||
print("| Config Error: {} attribute {} not supported".format(m, attr))
|
||||
else:
|
||||
print("| Config Error: {} parameter {} is blank".format(m, attr))
|
||||
if len(new_dictionary) > 1:
|
||||
methods.append((method_name, [new_dictionary]))
|
||||
else:
|
||||
print("| Config Error: {} had no valid fields".format(m))
|
||||
elif method_name == "tautulli":
|
||||
try:
|
||||
new_dictionary = {}
|
||||
new_dictionary["list_type"] = check_for_attribute(collections[c][m], "list_type", parent="tautulli", test_list=["popular", "watched"], options="| \tpopular (Most Popular List)\n| \twatched (Most Watched List)", throw=True, save=False)
|
||||
new_dictionary["list_days"] = check_for_attribute(collections[c][m], "list_days", parent="tautulli", var_type="int", default=30, save=False)
|
||||
new_dictionary["list_size"] = check_for_attribute(collections[c][m], "list_size", parent="tautulli", var_type="int", default=10, save=False)
|
||||
new_dictionary["list_buffer"] = check_for_attribute(collections[c][m], "list_buffer", parent="tautulli", var_type="int", default=20, save=False)
|
||||
methods.append((method_name, [new_dictionary]))
|
||||
except SystemExit as e:
|
||||
print(e)
|
||||
else:
|
||||
print("| Config Error: {} attribute is not a dictionary: {}".format(m, collections[c][m]))
|
||||
elif method_name == "all":
|
||||
methods.append((method_name, [""]))
|
||||
elif method_name != "sync_mode":
|
||||
|
@ -458,7 +607,9 @@ def update_from_config(config_path, plex, headless=False, no_meta=False, no_imag
|
|||
for v in values:
|
||||
if m == "imdb_list":
|
||||
print("| \n| Processing {}: {}".format(m, v[0]))
|
||||
elif m != "plex_search":
|
||||
elif m == "plex_collection":
|
||||
print("| \n| Processing {}: {}".format(m, v.title))
|
||||
elif m not in ["plex_search", "tmdb_list", "tmdb_id", "tmdb_movie", "tmdb_collection", "tmdb_company", "tmdb_network", "tmdb_discover", "tmdb_show"]:
|
||||
print("| \n| Processing {}: {}".format(m, v))
|
||||
try:
|
||||
missing, map = add_to_collection(config_path, plex, m, v, c, map, filters)
|
||||
|
@ -505,9 +656,10 @@ def update_from_config(config_path, plex, headless=False, no_meta=False, no_imag
|
|||
|
||||
print("| ")
|
||||
|
||||
plex_collection = get_collection(plex, c, headless)
|
||||
|
||||
if not isinstance(plex_collection, Collections):
|
||||
try:
|
||||
plex_collection = get_collection(plex, c, headless)
|
||||
except ValueError as e:
|
||||
print("| Config Error: {}".format(e))
|
||||
continue # No collections created with requested criteria
|
||||
|
||||
if not no_meta:
|
||||
|
@ -620,162 +772,164 @@ def update_from_config(config_path, plex, headless=False, no_meta=False, no_imag
|
|||
|
||||
def append_collection(config_path, config_update=None):
|
||||
while True:
|
||||
if config_update:
|
||||
collection_name = config_update
|
||||
selected_collection = get_collection(plex, collection_name, True)
|
||||
else:
|
||||
collection_name = input("| Enter collection to add to: ")
|
||||
selected_collection = get_collection(plex, collection_name)
|
||||
selected_collection = None
|
||||
try:
|
||||
if not isinstance(selected_collection, str):
|
||||
print("| \"{}\" Selected.".format(selected_collection.title))
|
||||
finished = False
|
||||
while not finished:
|
||||
try:
|
||||
collection_type = selected_collection.subtype
|
||||
if collection_type == 'movie':
|
||||
method = input("| Add Movie(m), Actor(a), IMDb/TMDb/Trakt List(l), Custom(c), Back(b)?: ")
|
||||
else:
|
||||
method = input("| Add Show(s), Actor(a), IMDb/TMDb/Trakt List(l), Custom(c), Back(b)?: ")
|
||||
if method == "m":
|
||||
if not config_update:
|
||||
method = "movie"
|
||||
value = input("| Enter Movie (Name or Rating Key): ")
|
||||
if value is int:
|
||||
plex_movie = get_movie(plex, int(value))
|
||||
print('| +++ Adding %s to collection %s' % (
|
||||
plex_movie.title, selected_collection.title))
|
||||
plex_movie.addCollection(selected_collection.title)
|
||||
else:
|
||||
results = get_movie(plex, value)
|
||||
if len(results) > 1:
|
||||
while True:
|
||||
i = 1
|
||||
for result in results:
|
||||
print("| {POS}) {TITLE} - {RATINGKEY}".format(POS=i, TITLE=result.title,
|
||||
RATINGKEY=result.ratingKey))
|
||||
i += 1
|
||||
s = input("| Select movie (N for None): ")
|
||||
if int(s):
|
||||
s = int(s)
|
||||
if len(results) >= s > 0:
|
||||
result = results[s - 1]
|
||||
print('| +++ Adding %s to collection %s' % (
|
||||
result.title, selected_collection.title))
|
||||
result.addCollection(selected_collection.title)
|
||||
break
|
||||
else:
|
||||
break
|
||||
if config_update:
|
||||
collection_name = config_update
|
||||
selected_collection = get_collection(plex, collection_name, True)
|
||||
else:
|
||||
collection_name = input("| Enter collection to add to: ")
|
||||
selected_collection = get_collection(plex, collection_name)
|
||||
except ValueError as e:
|
||||
print("| Config Error: {}".format(e))
|
||||
break
|
||||
|
||||
try:
|
||||
print("| \"{}\" Selected.".format(selected_collection.title))
|
||||
finished = False
|
||||
while not finished:
|
||||
try:
|
||||
collection_type = selected_collection.subtype
|
||||
if collection_type == 'movie':
|
||||
method = input("| Add Movie(m), Actor(a), IMDb/TMDb/Trakt List(l), Custom(c), Back(b)?: ")
|
||||
else:
|
||||
method = input("| Add Show(s), Actor(a), IMDb/TMDb/Trakt List(l), Custom(c), Back(b)?: ")
|
||||
if method == "m":
|
||||
if not config_update:
|
||||
method = "movie"
|
||||
value = input("| Enter Movie (Name or Rating Key): ")
|
||||
if value is int:
|
||||
plex_movie = get_movie(plex, int(value))
|
||||
print('| +++ Adding %s to collection %s' % (
|
||||
plex_movie.title, selected_collection.title))
|
||||
plex_movie.addCollection(selected_collection.title)
|
||||
else:
|
||||
print("| Movies in configuration file not yet supported")
|
||||
results = get_movie(plex, value)
|
||||
if len(results) > 1:
|
||||
while True:
|
||||
i = 1
|
||||
for result in results:
|
||||
print("| {POS}) {TITLE} - {RATINGKEY}".format(POS=i, TITLE=result.title,
|
||||
RATINGKEY=result.ratingKey))
|
||||
i += 1
|
||||
s = input("| Select movie (N for None): ")
|
||||
if int(s):
|
||||
s = int(s)
|
||||
if len(results) >= s > 0:
|
||||
result = results[s - 1]
|
||||
print('| +++ Adding %s to collection %s' % (
|
||||
result.title, selected_collection.title))
|
||||
result.addCollection(selected_collection.title)
|
||||
break
|
||||
else:
|
||||
break
|
||||
else:
|
||||
print("| Movies in configuration file not yet supported")
|
||||
|
||||
# elif method == "s":
|
||||
# if not config_update:
|
||||
# method = "show"
|
||||
# value = input("Enter Show (Name or Rating Key): ")
|
||||
# if value is int:
|
||||
# plex_show = get_show(int(value))
|
||||
# print('+++ Adding %s to collection %s' % (
|
||||
# plex_show.title, selected_collection.title))
|
||||
# plex_show.addCollection(selected_collection.title)
|
||||
# else:
|
||||
# results = get_show(plex, value)
|
||||
# if len(results) > 1:
|
||||
# while True:
|
||||
# i = 1
|
||||
# for result in results:
|
||||
# print("{POS}) {TITLE} - {RATINGKEY}".format(POS=i, TITLE=result.title,
|
||||
# RATINGKEY=result.ratingKey))
|
||||
# i += 1
|
||||
# s = input("Select show (N for None): ")
|
||||
# if int(s):
|
||||
# s = int(s)
|
||||
# if len(results) >= s > 0:
|
||||
# result = results[s - 1]
|
||||
# print('+++ Adding %s to collection %s' % (
|
||||
# result.title, selected_collection.title))
|
||||
# result.addCollection(selected_collection.title)
|
||||
# break
|
||||
# else:
|
||||
# break
|
||||
# else:
|
||||
# print("Shows in configuration file not yet supported")
|
||||
# elif method == "s":
|
||||
# if not config_update:
|
||||
# method = "show"
|
||||
# value = input("Enter Show (Name or Rating Key): ")
|
||||
# if value is int:
|
||||
# plex_show = get_show(int(value))
|
||||
# print('+++ Adding %s to collection %s' % (
|
||||
# plex_show.title, selected_collection.title))
|
||||
# plex_show.addCollection(selected_collection.title)
|
||||
# else:
|
||||
# results = get_show(plex, value)
|
||||
# if len(results) > 1:
|
||||
# while True:
|
||||
# i = 1
|
||||
# for result in results:
|
||||
# print("{POS}) {TITLE} - {RATINGKEY}".format(POS=i, TITLE=result.title,
|
||||
# RATINGKEY=result.ratingKey))
|
||||
# i += 1
|
||||
# s = input("Select show (N for None): ")
|
||||
# if int(s):
|
||||
# s = int(s)
|
||||
# if len(results) >= s > 0:
|
||||
# result = results[s - 1]
|
||||
# print('+++ Adding %s to collection %s' % (
|
||||
# result.title, selected_collection.title))
|
||||
# result.addCollection(selected_collection.title)
|
||||
# break
|
||||
# else:
|
||||
# break
|
||||
# else:
|
||||
# print("Shows in configuration file not yet supported")
|
||||
|
||||
elif method == "a":
|
||||
method = "actors"
|
||||
value = input("| Enter Actor Name: ")
|
||||
try:
|
||||
a_rkey = get_actor_rkey(plex, value)
|
||||
elif method == "a":
|
||||
method = "actors"
|
||||
value = input("| Enter Actor Name: ")
|
||||
try:
|
||||
a_rkey = get_actor_rkey(plex, value)
|
||||
if config_update:
|
||||
modify_config(config_path, collection_name, method, value)
|
||||
else:
|
||||
add_to_collection(config_path, plex, method, a_rkey, selected_collection.title)
|
||||
except ValueError as e:
|
||||
print(e)
|
||||
|
||||
elif method == "l":
|
||||
l_type = input("| Enter list type IMDb(i) TMDb(t) Trakt(k): ")
|
||||
if l_type == "i":
|
||||
l_type = "IMDb"
|
||||
method = "imdb_list"
|
||||
elif l_type == "t":
|
||||
l_type = "TMDb"
|
||||
method = "tmdb_collection"
|
||||
elif l_type == "k":
|
||||
l_type = "Trakt"
|
||||
method = "trakt_list"
|
||||
else:
|
||||
return
|
||||
url = input("| Enter {} List URL: ".format(l_type)).strip()
|
||||
print("| Processing {} List: {}".format(l_type, url))
|
||||
if config_update:
|
||||
modify_config(config_path, collection_name, method, url)
|
||||
else:
|
||||
missing = add_to_collection(config_path, plex, method, url, selected_collection.title)
|
||||
if missing:
|
||||
if collection_type == 'movie':
|
||||
print("| {} missing movies from {} List: {}".format(len(missing), l_type, url))
|
||||
if input("| Add missing movies to Radarr? (y/n)").upper() == "Y":
|
||||
add_to_radarr(config_path, missing)
|
||||
# elif collection_type == 'show':
|
||||
# print("{} missing shows from {} List: {}".format(len(missing_shows), l_type, url))
|
||||
# if input("Add missing shows to Sonarr? (y/n)").upper() == "Y":
|
||||
# add_to_sonarr(missing_shows)
|
||||
print("| Bad {} List URL".format(l_type))
|
||||
|
||||
elif method == "c":
|
||||
print("| Please read the below link to see valid search types. "
|
||||
"Please note not all have been tested")
|
||||
print(
|
||||
"| https://python-plexapi.readthedocs.io/en/latest/modules/video.html?highlight=plexapi.video.Movie#plexapi.video.Movie")
|
||||
while True:
|
||||
method = input("| Enter Search method (q to quit): ")
|
||||
if method in "quit":
|
||||
break
|
||||
m_search = " " + method + " "
|
||||
if m_search in Movie.__doc__ or hasattr(Movie, m_search):
|
||||
if method[-1:] == "s":
|
||||
method_p = method[:-1]
|
||||
else:
|
||||
method_p = method
|
||||
value = input("| Enter {}: ".format(method_p))
|
||||
if config_update:
|
||||
modify_config(config_path, collection_name, method, value)
|
||||
else:
|
||||
add_to_collection(config_path, plex, method, a_rkey, selected_collection.title)
|
||||
except ValueError as e:
|
||||
print(e)
|
||||
|
||||
elif method == "l":
|
||||
l_type = input("| Enter list type IMDb(i) TMDb(t) Trakt(k): ")
|
||||
if l_type == "i":
|
||||
l_type = "IMDb"
|
||||
method = "imdb_list"
|
||||
elif l_type == "t":
|
||||
l_type = "TMDb"
|
||||
method = "tmdb_collection"
|
||||
elif l_type == "k":
|
||||
l_type = "Trakt"
|
||||
method = "trakt_list"
|
||||
add_to_collection(config_path, plex, method, value, selected_collection.title)
|
||||
break
|
||||
else:
|
||||
return
|
||||
url = input("| Enter {} List URL: ".format(l_type)).strip()
|
||||
print("| Processing {} List: {}".format(l_type, url))
|
||||
if config_update:
|
||||
modify_config(config_path, collection_name, method, url)
|
||||
else:
|
||||
missing = add_to_collection(config_path, plex, method, url, selected_collection.title)
|
||||
if missing:
|
||||
if collection_type == 'movie':
|
||||
print("| {} missing movies from {} List: {}".format(len(missing), l_type, url))
|
||||
if input("| Add missing movies to Radarr? (y/n)").upper() == "Y":
|
||||
add_to_radarr(config_path, missing)
|
||||
# elif collection_type == 'show':
|
||||
# print("{} missing shows from {} List: {}".format(len(missing_shows), l_type, url))
|
||||
# if input("Add missing shows to Sonarr? (y/n)").upper() == "Y":
|
||||
# add_to_sonarr(missing_shows)
|
||||
print("| Bad {} List URL".format(l_type))
|
||||
|
||||
elif method == "c":
|
||||
print("| Please read the below link to see valid search types. "
|
||||
"Please note not all have been tested")
|
||||
print(
|
||||
"| https://python-plexapi.readthedocs.io/en/latest/modules/video.html?highlight=plexapi.video.Movie#plexapi.video.Movie")
|
||||
while True:
|
||||
method = input("| Enter Search method (q to quit): ")
|
||||
if method in "quit":
|
||||
break
|
||||
m_search = " " + method + " "
|
||||
if m_search in Movie.__doc__ or hasattr(Movie, m_search):
|
||||
if method[-1:] == "s":
|
||||
method_p = method[:-1]
|
||||
else:
|
||||
method_p = method
|
||||
value = input("| Enter {}: ".format(method_p))
|
||||
if config_update:
|
||||
modify_config(config_path, collection_name, method, value)
|
||||
else:
|
||||
add_to_collection(config_path, plex, method, value, selected_collection.title)
|
||||
break
|
||||
else:
|
||||
print("| Search method did not match an attribute for plexapi.video.Movie")
|
||||
except TypeError:
|
||||
print("| Bad {} URL".format(l_type))
|
||||
except KeyError as e:
|
||||
print("| " + str(e))
|
||||
if input("| Add more to collection? (y/n): ") == "n":
|
||||
finished = True
|
||||
break
|
||||
else:
|
||||
print("| " + selected_collection)
|
||||
break
|
||||
print("| Search method did not match an attribute for plexapi.video.Movie")
|
||||
except TypeError:
|
||||
print("| Bad {} URL".format(l_type))
|
||||
except KeyError as e:
|
||||
print("| " + str(e))
|
||||
if input("| Add more to collection? (y/n): ") == "n":
|
||||
finished = True
|
||||
break
|
||||
except AttributeError:
|
||||
print("| No collection found")
|
||||
|
||||
|
@ -808,12 +962,11 @@ print("| | _/| |/ -_)\ \ / / _ \| || || _|/ _ \ | (__ / _ \| || |/ -_)/ _|
|
|||
print("| |_| |_|\___|/_\_\ /_/ \_\\\\_,_| \__|\___/ \___|\___/|_||_|\___|\__| \__||_|\___/|_||_|/__/ |")
|
||||
print("| |")
|
||||
print("|===================================================================================================|")
|
||||
print("| Version 2.5.0")
|
||||
print("| Version 2.6.0")
|
||||
print("| Locating config...")
|
||||
config_path = None
|
||||
app_dir = os.path.dirname(os.path.abspath(__file__))
|
||||
|
||||
|
||||
if args.config_path and os.path.exists(args.config_path):
|
||||
config_path = os.path.abspath(args.config_path) # Set config_path from command line switch
|
||||
elif args.config_path and not os.path.exists(args.config_path):
|
||||
|
@ -831,6 +984,7 @@ if args.update:
|
|||
config = Config(config_path, headless=True)
|
||||
plex = Plex(config_path)
|
||||
update_from_config(config_path, plex, True, args.no_meta, args.no_images)
|
||||
print("|\n|===================================================================================================|")
|
||||
sys.exit(0)
|
||||
|
||||
config = Config(config_path)
|
||||
|
@ -920,24 +1074,23 @@ while not mode == "q":
|
|||
elif mode == "-":
|
||||
print("|\n|===================================================================================================|")
|
||||
data = input("| \n| Enter collection name to search for (blank for all): ")
|
||||
collection = get_collection(plex, data)
|
||||
if not isinstance(collection, str):
|
||||
delete_collection(collection)
|
||||
else:
|
||||
print("| " + collection)
|
||||
try:
|
||||
delete_collection(get_collection(plex, data))
|
||||
except ValueError as e:
|
||||
print("| Config Error: {}".format(e))
|
||||
|
||||
elif mode == "s":
|
||||
print("|\n|===================================================================================================|")
|
||||
data = input("| \n| Enter collection name to search for (blank for all): ")
|
||||
collection = get_collection(plex, data)
|
||||
if not isinstance(collection, str):
|
||||
try:
|
||||
collection = get_collection(plex, data)
|
||||
print("| Found {} collection {}".format(collection.subtype, collection.title))
|
||||
items = collection.children
|
||||
print("| {}s in collection: ".format(collection.subtype).capitalize())
|
||||
for i, m in enumerate(items):
|
||||
print("| {}) {}".format(i + 1, m.title))
|
||||
else:
|
||||
print("| " + collection)
|
||||
except ValueError as e:
|
||||
print("| Error: {}".format(e))
|
||||
except KeyboardInterrupt:
|
||||
print()
|
||||
pass
|
||||
|
|
|
@ -100,22 +100,15 @@ def get_collection(plex, data, exact=None, subtype=None):
|
|||
if selection >= 0:
|
||||
return collection_list[selection]
|
||||
elif selection == -1:
|
||||
return "No collection selected"
|
||||
raise ValueError("No collection selected")
|
||||
else:
|
||||
print("| Invalid entry")
|
||||
except (IndexError, ValueError) as E:
|
||||
print("| Invalid entry")
|
||||
elif len(collection_list) == 1:
|
||||
if exact:
|
||||
# if collection_list[0] == data:
|
||||
if collection_list[0].title == data:
|
||||
return collection_list[0]
|
||||
else:
|
||||
return "Collection not in Plex, please update from config first"
|
||||
else:
|
||||
return collection_list[0]
|
||||
elif len(collection_list) == 1 and (exact is None or (exact and collection_list[0].title == data)):
|
||||
return collection_list[0]
|
||||
else:
|
||||
return "No collection found"
|
||||
raise ValueError("Collection {} not found".format(data))
|
||||
|
||||
def add_to_collection(config_path, plex, method, value, c, map, filters=None):
|
||||
movies = []
|
||||
|
@ -150,16 +143,14 @@ def add_to_collection(config_path, plex, method, value, c, map, filters=None):
|
|||
elif method == "tautulli" and not Tautulli.valid:
|
||||
raise KeyError("| tautulli connection required for {}",format(method))
|
||||
elif plex.library_type == "movie":
|
||||
if method == "imdb_list":
|
||||
if method == "plex_collection":
|
||||
movies = value.children
|
||||
elif method == "imdb_list":
|
||||
movies, missing = imdb_tools.imdb_get_movies(config_path, plex, value)
|
||||
elif method in ["tmdb_list", "tmdb_id", "tmdb_movie", "tmdb_collection", "tmdb_company"]:
|
||||
elif "tmdb" in method:
|
||||
movies, missing = imdb_tools.tmdb_get_movies(config_path, plex, value, method)
|
||||
elif method == "trakt_list":
|
||||
movies, missing = trakt_tools.trakt_get_movies(config_path, plex, value)
|
||||
elif method == "trakt_trending":
|
||||
movies, missing = trakt_tools.trakt_get_movies(config_path, plex, value, list_type='trending')
|
||||
elif method == "trakt_watchlist":
|
||||
movies, missing = trakt_tools.trakt_get_movies(config_path, plex, value, list_type='watchlist')
|
||||
elif "trakt" in method:
|
||||
movies, missing = trakt_tools.trakt_get_movies(config_path, plex, value, method)
|
||||
elif method == "tautulli":
|
||||
movies, missing = imdb_tools.get_tautulli(config_path, plex, value)
|
||||
elif method == "all":
|
||||
|
@ -169,18 +160,14 @@ def add_to_collection(config_path, plex, method, value, c, map, filters=None):
|
|||
else:
|
||||
print("| Config Error: {} method not supported".format(method))
|
||||
elif plex.library_type == "show":
|
||||
if method == "tmdb_list":
|
||||
shows, missing = imdb_tools.tmdb_get_shows(config_path, plex, value, is_list=True)
|
||||
elif method in ["tmdb_id", "tmdb_show"]:
|
||||
shows, missing = imdb_tools.tmdb_get_shows(config_path, plex, value)
|
||||
if method == "plex_collection":
|
||||
shows = value.children
|
||||
elif "tmdb" in method:
|
||||
shows, missing = imdb_tools.tmdb_get_shows(config_path, plex, value, method)
|
||||
elif method == "tvdb_show":
|
||||
shows, missing = imdb_tools.tvdb_get_shows(config_path, plex, value)
|
||||
elif method == "trakt_list":
|
||||
shows, missing = trakt_tools.trakt_get_shows(config_path, plex, value)
|
||||
elif method == "trakt_trending":
|
||||
shows, missing = trakt_tools.trakt_get_shows(config_path, plex, value, list_type='trending')
|
||||
elif method == "trakt_watchlist":
|
||||
shows, missing = trakt_tools.trakt_get_shows(config_path, plex, value, list_type='watchlist')
|
||||
elif "trakt" in method:
|
||||
shows, missing = trakt_tools.trakt_get_shows(config_path, plex, value, method)
|
||||
elif method == "tautulli":
|
||||
shows, missing = imdb_tools.get_tautulli(config_path, plex, value)
|
||||
elif method == "all":
|
||||
|
|
|
@ -4,23 +4,24 @@ import plex_tools
|
|||
import trakt
|
||||
import os
|
||||
|
||||
def trakt_get_movies(config_path, plex, data, list_type='userlist'):
|
||||
|
||||
def trakt_get_movies(config_path, plex, data, method):
|
||||
config_tools.TraktClient(config_path)
|
||||
if list_type == 'userlist':
|
||||
trakt_url = data
|
||||
if trakt_url[-1:] == " ":
|
||||
trakt_url = trakt_url[:-1]
|
||||
trakt_list_path = urlparse(trakt_url).path
|
||||
trakt_list_items = trakt.Trakt[trakt_list_path].items()
|
||||
elif list_type == 'trending':
|
||||
if method == "trakt_trending":
|
||||
max_items = int(data)
|
||||
trakt_list_items = trakt.Trakt['movies'].trending(per_page=max_items)
|
||||
elif list_type == 'watchlist':
|
||||
elif method == "trakt_watchlist":
|
||||
trakt_url = data
|
||||
if trakt_url[-1:] == " ":
|
||||
trakt_url = trakt_url[:-1]
|
||||
trakt_list_path = 'users/{}/watchlist'.format(data)
|
||||
trakt_list_items = [movie for movie in trakt.Trakt[trakt_list_path].movies()]
|
||||
else:
|
||||
trakt_url = data
|
||||
if trakt_url[-1:] == " ":
|
||||
trakt_url = trakt_url[:-1]
|
||||
trakt_list_path = urlparse(trakt_url).path
|
||||
trakt_list_items = trakt.Trakt[trakt_list_path].items()
|
||||
title_ids = [m.pk[1] for m in trakt_list_items if isinstance(m, trakt.objects.movie.Movie)]
|
||||
|
||||
imdb_map = {}
|
||||
|
@ -68,23 +69,23 @@ def trakt_get_movies(config_path, plex, data, list_type='userlist'):
|
|||
# No movies
|
||||
return None, None
|
||||
|
||||
def trakt_get_shows(config_path, plex, data, list_type='userlist'):
|
||||
def trakt_get_shows(config_path, plex, data, method):
|
||||
config_tools.TraktClient(config_path)
|
||||
if list_type == 'userlist':
|
||||
trakt_url = data
|
||||
if trakt_url[-1:] == " ":
|
||||
trakt_url = trakt_url[:-1]
|
||||
trakt_list_path = urlparse(trakt_url).path
|
||||
trakt_list_items = trakt.Trakt[trakt_list_path].items()
|
||||
elif list_type == 'trending':
|
||||
if method == "trakt_trending":
|
||||
max_items = int(data)
|
||||
trakt_list_items = trakt.Trakt['shows'].trending(per_page=max_items)
|
||||
elif list_type == 'watchlist':
|
||||
elif method == "trakt_watchlist":
|
||||
trakt_url = data
|
||||
if trakt_url[-1:] == " ":
|
||||
trakt_url = trakt_url[:-1]
|
||||
trakt_list_path = 'users/{}/watchlist'.format(data)
|
||||
trakt_list_items = [show for show in trakt.Trakt[trakt_list_path].shows()]
|
||||
else:
|
||||
trakt_url = data
|
||||
if trakt_url[-1:] == " ":
|
||||
trakt_url = trakt_url[:-1]
|
||||
trakt_list_path = urlparse(trakt_url).path
|
||||
trakt_list_items = trakt.Trakt[trakt_list_path].items()
|
||||
|
||||
tvdb_map = {}
|
||||
title_ids = []
|
||||
|
|
|
@ -37,6 +37,10 @@ collections:
|
|||
content_rating: G
|
||||
collection_mode: show_items
|
||||
collection_order: alpha
|
||||
Studio Ghibli:
|
||||
tmdb_company: https://www.themoviedb.org/company/10342
|
||||
CBS:
|
||||
tmdb_network: https://www.themoviedb.org/network/16
|
||||
90s Comedies:
|
||||
plex_search:
|
||||
year: [1990,1991,1992,1993,1994,1995,1996,1997,1998,1999]
|
||||
|
|
Loading…
Reference in a new issue