def append_collection(config_path, config_update=None): while True: if config_update: collection_name = config_update selected_collection = plex_tools.get_collection( plex, collection_name, True) else: collection_name = input("Enter collection to add to: ") selected_collection = plex_tools.get_collection( plex, collection_name) 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)?: " ) else: method = input( "Add Show(s), Actor(a), IMDb/TMDb/Trakt List(l), Custom(c)?: " ) if method == "m": if not config_update: method = "movie" value = input( "Enter Movie (Name or Rating Key): ") if value is int: plex_movie = plex_tools.get_movie( int(value)) print('+++ Adding %s to collection %s' % (plex_movie.title, selected_collection.title)) plex_movie.addCollection( selected_collection.title) else: results = plex_tools.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 = plex_tools.get_show(int(value)) print('+++ Adding %s to collection %s' % (plex_show.title, selected_collection.title)) plex_show.addCollection( selected_collection.title) else: results = plex_tools.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: ") a_rkey = plex_tools.get_actor_rkey(plex, value) if config_update: modify_config(config_path, collection_name, method, value) else: plex_tools.add_to_collection( config_path, plex, method, a_rkey, selected_collection.title) 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-list" 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 = plex_tools.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 filter 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 filter 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: plex_tools.add_to_collection( config_path, plex, method, value, selected_collection.title) break else: print( "Filter method did not match an attribute for plexapi.video.Movie" ) except TypeError: print("Bad {} URL".format(l_type)) except KeyError as e: print(e) if input("Add more to collection? (y/n): ") == "n": finished = True print("\n") break else: print(selected_collection) break except AttributeError: print("No collection found")
while not mode == "q": try: print("Modes: Rescan(r), Actor(a), IMDb/TMDb/Trakt List(l), " "Add to Existing Collection(+), Delete(-), " "Search(s), Quit(q)\n") mode = input("Select Mode: ") if mode == "r": update_from_config(config_path, plex) elif mode == "a": actor = input("Enter actor name: ") a_rkey = plex_tools.get_actor_rkey(plex, actor) if isinstance(a_rkey, int): c_name = input("Enter collection name: ") plex_tools.add_to_collection(config_path, plex, "actors", a_rkey, c_name) else: print("Invalid actor") print("\n") elif mode == "l": l_type = input("Enter list type IMDb(i) TMDb(t) Trakt(k): ") method_map = { "i": ("IMDb", "imdb-list"), "t": ("TMDb", "tmdb-list"), "k": ("Trakt", "trakt-list") } if l_type in ("i", "t", "k"): l_type, method = method_map[l_type] url = input("Enter {} List URL: ".format(l_type)).strip() c_name = input("Enter collection name: ")
def update_from_config(config_path, plex): config = Config(config_path) collections = config.collections if isinstance(plex.Library, MovieSection): libtype = "movie" elif isinstance(plex.Library, ShowSection): libtype = "show" for c in collections: print("Updating collection: {}...".format(c)) methods = [m for m in collections[c] if m not in ("details", "subfilters")] subfilters = [] if "subfilters" in collections[c]: for sf in collections[c]["subfilters"]: sf_string = sf, collections[c]["subfilters"][sf] subfilters.append(sf_string) for m in methods: if isinstance(collections[c][m], list): # Support multiple imdb/tmdb/trakt lists values = collections[c][m] else: values = collections[c][m].split(", ") for v in values: if m[-1:] == "s": m_print = m[:-1] else: m_print = m print("Processing {}: {}".format(m_print, v)) if m == "actors" or m == "actor": v = get_actor_rkey(plex, v) try: missing = add_to_collection(config_path, plex, m, v, c, subfilters) except UnboundLocalError: # No sub-filters missing = add_to_collection(config_path, plex, m, v, c) except (KeyError, ValueError) as e: print(e) missing = False if missing: if libtype == "movie": if "imdb" in m: method_name = "IMDb" elif "trakt" in m: method_name = "Trakt" else: method_name = "TMDb" print("{} missing movies from {} List: {}".format(len(missing), method_name, v)) if 'add_movie' in config.radarr: if config.radarr['add_movie'] is True: print("Adding missing movies to Radarr") add_to_radarr(config_path, missing) else: if input("Add missing movies to Radarr? (y/n): ").upper() == "Y": add_to_radarr(config_path, missing) elif libtype == "show": if "trakt" in m: method_name = "Trakt" else: method_name = "TMDb" print("{} missing shows from {} List: {}".format(len(missing), method_name, v)) # if not skip_sonarr: # if input("Add missing shows to Sonarr? (y/n): ").upper() == "Y": # add_to_radarr(missing_shows) # Multiple collections of the same name if "details" in collections[c]: # # Check if there are multiple collections with the same name # movie_collections = plex.MovieLibrary.search(title=c, libtype="collection") # show_collections = plex.ShowLibrary.search(title=c, libtype="collection") # if len(movie_collections + show_collections) > 1: # print("Multiple collections named {}.\nUpdate of \"details\" is currently unsupported.".format(c)) # continue plex_collection = get_collection(plex, c) if not isinstance(plex_collection, Collections): # No collections created with requested criteria continue rkey = plex_collection.ratingKey # Handle collection summary summary = None if "summary" in collections[c]["details"]: summary = collections[c]["details"]["summary"] elif "tmdb-summary" in collections[c]["details"]: # Seems clunky ... try: summary = tmdb_get_summary(config_path, collections[c]["details"]["tmdb-summary"], "overview") except AttributeError: summary = tmdb_get_summary(config_path, collections[c]["details"]["tmdb-summary"], "biography") if summary: # Push summary to Plex # Waiting on https://github.com/pkkid/python-plexapi/pull/509 # See https://github.com/pkkid/python-plexapi/issues/514 url = plex.url + "/library/sections/" + str(plex.Library.key) + "/all" querystring = {"type": "18", "id": str(rkey), "summary.value": summary, "X-Plex-Token": config.plex['token']} response = requests.put(url, params=querystring) # To do: add logic to report errors # Handle collection posters poster = None if "poster" in collections[c]["details"]: poster = collections[c]["details"]["poster"] elif "tmdb-poster" in collections[c]["details"]: # Seems clunky ... try: slug = tmdb_get_summary(config_path, collections[c]["details"]["tmdb-poster"], "poster_path") except AttributeError: slug = tmdb_get_summary(config_path, collections[c]["details"]["tmdb-poster"], "profile_path") poster = "https://image.tmdb.org/t/p/original/" + slug else: # Try to pull image from image_server. # To do: this should skip if it's run without the image server # To do: this only runs if 'details' key is set - might make sense to run regardless # Setup connection to image_server config_client = ImageServer(config_path, "client") # Url encode collection name c_name = urllib.parse.quote(c, safe='') # Create local url to where image would be if exists local_poster_url = "http://" + config_client.host + ":" + str(config_client.port) + "/images/" + c_name # Test local url response = requests.head(local_poster_url) if response.status_code < 400: poster = local_poster_url if poster: # Push poster to Plex # Waiting on https://github.com/pkkid/python-plexapi/pull/509 # See https://github.com/pkkid/python-plexapi/issues/514 url = plex.url + "/library/metadata/" + str(rkey) + "/posters" querystring = {"url": poster, "X-Plex-Token": config.plex['token']} response = requests.post(url, params=querystring)
def update_from_config(plex, skip_radarr=False): config = Config() collections = config.collections for c in collections: print("Updating collection: {}...".format(c)) methods = [ m for m in collections[c] if m not in ("details", "subfilters") ] subfilters = [] if "subfilters" in collections[c]: for sf in collections[c]["subfilters"]: sf_string = sf, collections[c]["subfilters"][sf] subfilters.append(sf_string) for m in methods: values = collections[c][m].split(", ") for v in values: if m[-1:] == "s": m_print = m[:-1] else: m_print = m print("Processing {}: {}".format(m_print, v)) if m == "actors" or m == "actor": v = get_actor_rkey(plex, v) try: missing = add_to_collection(plex, m, v, c, subfilters) except UnboundLocalError: # No sub-filters missing = add_to_collection(plex, m, v, c) except KeyError as e: print(e) missing = False if missing: if "imdb" in m: m = "IMDB" else: m = "TMDb" print("{} missing movies from {} List: {}".format( len(missing), m, v)) if not skip_radarr: if input("Add missing movies to Radarr? (y/n): " ).upper() == "Y": add_to_radarr(missing) if "details" in collections[c]: for dt_m in collections[c]["details"]: rkey = get_collection(plex, c).ratingKey dt_v = collections[c]["details"][dt_m] if "summary" in dt_m: if "tmdb" in dt_m: try: dt_v = tmdb_get_summary(dt_v, "overview") except AttributeError: dt_v = tmdb_get_summary(dt_v, "biography") library_name = plex.library section = plex.Server.library.section(library_name).key url = plex.url + "/library/sections/" + str( section) + "/all" querystring = { "type": "18", "id": str(rkey), "summary.value": dt_v, "X-Plex-Token": config.plex['token'] } response = requests.request("PUT", url, params=querystring) poster = None if "poster" in dt_m: if "tmdb" in dt_m: poster = "https://image.tmdb.org/t/p/original/" poster = poster + tmdb_get_summary(dt_v).poster_path else: poster = dt_v if not poster: # try to pull image from image_server. File is Collection name.png # Setup connection to image_server try: host = config.image_server["host"] except AttributeError: host = "127.0.0.1" try: port = config.image_server["port"] except AttributeError: port = "5000" # Replace spaces in collection name with %20 c_name = c.replace(" ", "%20") # Create url to where image would be if exists poster = "http://" + host + ":" + str( port) + "/images/" + c_name try: r = requests.request("GET", poster) if not r.status_code == 404: # Create url for request to Plex url = plex.url + "/library/metadata/" + str( rkey) + "/posters" querystring = { "url": poster, "X-Plex-Token": config.plex['token'] } response = requests.request("POST", url, params=querystring) except: False
def update_from_config(config_path, plex, skip_radarr=False): config = Config(config_path) collections = config.collections if isinstance(plex.Library, MovieSection): libtype = "movie" elif isinstance(plex.Library, ShowSection): libtype = "show" for c in collections: print("Updating collection: {}...".format(c)) methods = [ m for m in collections[c] if m not in ("details", "subfilters") ] subfilters = [] if "subfilters" in collections[c]: for sf in collections[c]["subfilters"]: sf_string = sf, collections[c]["subfilters"][sf] subfilters.append(sf_string) for m in methods: if isinstance(collections[c][m], list): # Support multiple imdb/tmdb/trakt lists values = collections[c][m] else: values = collections[c][m].split(", ") for v in values: if m[-1:] == "s": m_print = m[:-1] else: m_print = m print("Processing {}: {}".format(m_print, v)) if m == "actors" or m == "actor": v = get_actor_rkey(plex, v) try: missing = add_to_collection(config_path, plex, m, v, c, subfilters) except UnboundLocalError: # No sub-filters missing = add_to_collection(config_path, plex, m, v, c) except (KeyError, ValueError) as e: print(e) missing = False if missing: if libtype == "movie": if "imdb" in m: method_name = "IMDb" elif "trakt" in m: method_name = "Trakt" else: method_name = "TMDb" print("{} missing movies from {} List: {}".format( len(missing), method_name, v)) if not skip_radarr: if input("Add missing movies to Radarr? (y/n): " ).upper() == "Y": add_to_radarr(config_path, missing) elif libtype == "show": if "trakt" in m: method_name = "Trakt" else: method_name = "TMDb" print("{} missing shows from {} List: {}".format( len(missing), method_name, v)) # if not skip_sonarr: # if input("Add missing shows to Sonarr? (y/n): ").upper() == "Y": # add_to_radarr(missing_shows) # Multiple collections of the same name if "details" in collections[c]: # # Check if there are multiple collections with the same name # movie_collections = plex.MovieLibrary.search(title=c, libtype="collection") # show_collections = plex.ShowLibrary.search(title=c, libtype="collection") # if len(movie_collections + show_collections) > 1: # print("Multiple collections named {}.\nUpdate of \"details\" is currently unsupported.".format(c)) # continue plex_collection = get_collection(plex, c) if not isinstance(plex_collection, Collections): # No collections created with requested criteria continue for dt_m in collections[c]["details"]: rkey = plex_collection.ratingKey # subtype = plex_collection.subtype dt_v = collections[c]["details"][dt_m] if "summary" in dt_m: if "tmdb" in dt_m: try: dt_v = tmdb_get_summary(config_path, dt_v, "overview") except AttributeError: dt_v = tmdb_get_summary(config_path, dt_v, "biography") library_name = plex.Library #section = plex.Server.library.section(library_name).key section = library_name.key url = plex.url + "/library/sections/" + str( section) + "/all" querystring = { "type": "18", "id": str(rkey), "summary.value": dt_v, "X-Plex-Token": config.plex['token'] } response = requests.request("PUT", url, params=querystring) poster = None if "poster" in dt_m: if "tmdb" in dt_m: poster = "https://image.tmdb.org/t/p/original/" poster = poster + tmdb_get_summary(dt_v).poster_path else: poster = dt_v if not poster: # try to pull image from image_server. File is Collection name.png # Setup connection to image_server try: host = config.image_server["host"] except AttributeError: host = "127.0.0.1" try: port = config.image_server["port"] except AttributeError: port = "5000" # Replace spaces in collection name with %20 c_name = c.replace(" ", "%20") # Create url to where image would be if exists poster = "http://" + host + ":" + str( port) + "/images/" + c_name try: r = requests.request("GET", poster) if not r.status_code == 404: # Create url for request to Plex url = plex.url + "/library/metadata/" + str( rkey) + "/posters" querystring = { "url": poster, "X-Plex-Token": config.plex['token'] } response = requests.request("POST", url, params=querystring) except: False