def add_to_collection(config_path, plex, method, value, c, subfilters=None): movies = [] shows = [] items = [] if method in Movie.__doc__ or hasattr(Movie, method): try: movies = plex.Library.search(**{method: value}) except PlexExceptions.BadRequest: # If last character is "s" remove it and try again if method[-1:] == "s": movies = plex.Library.search(**{method[:-1]: value}) movies = [m.ratingKey for m in movies if movies] elif method in Show.__doc__ or hasattr(Show, method): try: shows = plex.Library.search(**{method: value}) except PlexExceptions.BadRequest as e: print(e) else: if isinstance(plex.Library, MovieSection): if method == "imdb-list": movies, missing = imdb_tools.imdb_get_movies( config_path, plex, value) elif method == "tmdb-list": movies, missing = imdb_tools.tmdb_get_movies( config_path, plex, value) elif method == "trakt-list": movies, missing = trakt_tools.trakt_get_movies( config_path, plex, value) elif isinstance(plex.Library, ShowSection): if method == "trakt-list": shows, missing = trakt_tools.trakt_get_shows( config_path, plex, value) if movies: # Check if already in collection cols = plex.Library.search(title=c, libtype="collection") try: fs = cols[0].children except IndexError: fs = [] for rk in movies: current_m = get_movie(plex, rk) current_m.reload() if current_m in fs: print("{} is already in collection: {}".format( current_m.title, c)) elif subfilters: match = True for sf in subfilters: method = sf[0] terms = str(sf[1]).split(", ") try: mv_attrs = getattr(current_m, method) # If it returns a list, get the 'tag' attribute # Otherwise, it's a string. Make it a list. if isinstance(mv_attrs, list) and "-" not in method: mv_attrs = [getattr(x, 'tag') for x in mv_attrs] else: mv_attrs = [str(mv_attrs)] except AttributeError: for media in current_m.media: if method == "video-resolution": mv_attrs = [media.videoResolution] for part in media.parts: if method == "audio-language": mv_attrs = ([ audio_stream.language for audio_stream in part.audioStreams() ]) if method == "subtitle-language": mv_attrs = ([ subtitle_stream.language for subtitle_stream in part.subtitleStreams() ]) # Get the intersection of the user's terms and movie's terms # If it's empty, it's not a match if not list(set(terms) & set(mv_attrs)): match = False break if match: print("+++ Adding {} to collection {}".format( current_m.title, c)) current_m.addCollection(c) elif not subfilters: print("+++ Adding {} to collection: {}".format( current_m.title, c)) current_m.addCollection(c) if shows: # Check if already in collection cols = plex.Library.search(title=c, libtype="collection") try: fs = cols[0].children except IndexError: fs = [] for rk in shows: current_s = get_item(plex, rk) current_s.reload() if current_s in fs: print("{} is already in collection: {}".format( current_s.title, c)) elif subfilters: match = True for sf in subfilters: method = sf[0] terms = str(sf[1]).split(", ") try: show_attrs = getattr(current_s, method) # If it returns a list, get the 'tag' attribute # Otherwise, it's a string. Make it a list. if isinstance(show_attrs, list) and "-" not in method: show_attrs = [ getattr(x, 'tag') for x in show_attrs ] else: show_attrs = [str(show_attrs)] except AttributeError as e: print(e) # for media in current_s.media: # if method == "video-resolution": # show_attrs = [media.videoResolution] # for part in media.parts: # if method == "audio-language": # show_attrs = ([audio_stream.language for audio_stream in part.audioStreams()]) # if method == "subtitle-language": # show_attrs = ([subtitle_stream.language for subtitle_stream in part.subtitleStreams()]) # Get the intersection of the user's terms and movie's terms # If it's empty, it's not a match if not list(set(terms) & set(show_attrs)): match = False break if match: print("+++ Adding {} to collection {}".format( current_s.title, c)) current_s.addCollection(c) elif not subfilters: print("+++ Adding {} to collection: {}".format( current_s.title, c)) current_s.addCollection(c) try: missing except UnboundLocalError: return else: return missing
def add_to_collection(config_path, plex, method, value, c, plex_map=None, map=None, filters=None): if plex_map is None and ("imdb" in method or "tvdb" in method or "tmdb" in method or "trakt" in method): plex_map = get_map(config_path, plex) if map is None: map = {} items = [] missing = [] if method == "all": items = plex.Library.all() elif method == "plex_collection": items = value.children elif method == "plex_search": search_terms = {} output = "" for attr_pair in value: if attr_pair[0] == "actor": search_list = [] for actor in attr_pair[1]: search_list.append(get_actor_rkey(plex, actor)) else: search_list = attr_pair[1] final_method = attr_pair[0][:-4] + "!" if attr_pair[0][ -4:] == ".not" else attr_pair[0] if plex.library_type == "show": final_method = "show." + final_method search_terms[final_method] = search_list ors = "" for param in attr_pair[1]: ors = ors + (" OR " if len(ors) > 0 else attr_pair[0] + "(") + str(param) output = output + ("\n|\t\t AND " if len(output) > 0 else "| Processing Plex Search: ") + ors + ")" print(output) items = plex.Library.search(**search_terms) elif method == "tvdb_show" and plex.library_type == "show": items, missing = imdb_tools.tvdb_get_shows(config_path, plex, plex_map, value) elif "imdb" in method or "tmdb" in method: if not TMDB.valid: raise KeyError("| tmdb connection required for {}", format(method)) elif method == "imdb_list" and plex.library_type == "movie": items, missing = imdb_tools.imdb_get_movies( config_path, plex, plex_map, value) elif "tmdb" in method and plex.library_type == "movie": items, missing = imdb_tools.tmdb_get_movies( config_path, plex, plex_map, value, method) elif "tmdb" in method and plex.library_type == "show": items, missing = imdb_tools.tmdb_get_shows(config_path, plex, plex_map, value, method) elif "trakt" in method: if not TraktClient.valid: raise KeyError("| trakt connection required for {}", format(method)) elif plex.library_type == "movie": items, missing = trakt_tools.trakt_get_movies( config_path, plex, plex_map, value, method) elif plex.library_type == "show": items, missing = trakt_tools.trakt_get_shows( config_path, plex, plex_map, value, method) elif method == "tautulli": if not Tautulli.valid: raise KeyError("| tautulli connection required for {}", format(method)) else: items, missing = imdb_tools.get_tautulli(config_path, plex, value) else: print("| Config Error: {} method not supported".format(method)) filter_alias = { "actor": "actors", "content_rating": "contentRating", "country": "countries", "director": "directors", "genre": "genres", "studio": "studio", "year": "year", "writer": "writers", "rating": "rating", "max_age": "max_age", "originally_available": "originallyAvailableAt", "video_resolution": "video_resolution", "audio_language": "audio_language", "subtitle_language": "subtitle_language", "plex_collection": "collections", } if items: # Check if already in collection cols = plex.Library.search(title=c, libtype="collection") try: fs = cols[0].children except IndexError: fs = [] item_count = 0 item_max = len(items) max_str_len = len(str(item_max)) current_length = 0 for rk in items: current_item = get_item(plex, rk) item_count += 1 match = True if filters: display_count = ( " " * (max_str_len - len(str(item_count)))) + str(item_count) print_display = "| Filtering {}/{} {}".format( display_count, item_max, current_item.title) print(adjust_space(current_length, print_display), end="\r") current_length = len(print_display) for f in filters: modifier = f[0][-4:] method = filter_alias[f[0][:-4]] if modifier in [ ".not", ".lte", ".gte" ] else filter_alias[f[0]] if method == "max_age": threshold_date = datetime.now() - timedelta(days=f[1]) attr = getattr(current_item, "originallyAvailableAt") if attr is None or attr < threshold_date: match = False break elif modifier in [".gte", ".lte"]: if method == "originallyAvailableAt": threshold_date = datetime.strptime( f[1], "%m/%d/%y") attr = getattr(current_item, "originallyAvailableAt") if (modifier == ".lte" and attr > threshold_date ) or (modifier == ".gte" and attr < threshold_date): match = False break elif method in ["year", "rating"]: attr = getattr(current_item, method) if (modifier == ".lte" and attr > f[1]) or (modifier == ".gte" and attr < f[1]): match = False break else: terms = f[1] if isinstance(f[1], list) else str( f[1]).split(", ") if method in [ "video_resolution", "audio_language", "subtitle_language" ]: for media in current_item.media: if method == "video_resolution": attrs = [media.videoResolution] for part in media.parts: if method == "audio_language": attrs = ([ audio_stream.language for audio_stream in part.audioStreams() ]) if method == "subtitle_language": attrs = ([ subtitle_stream.language for subtitle_stream in part.subtitleStreams() ]) elif method in [ "contentRating", "studio", "year", "rating", "originallyAvailableAt" ]: # Otherwise, it's a string. Make it a list. attrs = [str(getattr(current_item, method))] elif method in [ "actors", "countries", "directors", "genres", "writers", "collections" ]: attrs = [ getattr(x, 'tag') for x in getattr(current_item, method) ] # Get the intersection of the user's terms and item's terms # If it's empty and modifier is not .not, it's not a match # If it's not empty and modifier is .not, it's not a match if (not list(set(terms) & set(attrs)) and modifier != ".not") or (list(set(terms) & set(attrs)) and modifier == ".not"): match = False break if match: if current_item in fs: map[current_item.ratingKey] = None else: current_item.addCollection(c) print( adjust_space( current_length, "| {} Collection | {} | {}".format( c, "=" if current_item in fs else "+", current_item.title))) print( adjust_space( current_length, "| Processed {} {}".format( item_max, "Movies" if plex.library_type == "movie" else "Shows"))) else: print("| No {} Found".format("Movies" if plex.library_type == "movie" else "Shows")) return missing, map