added more options to plex_search and smart_filter

This commit is contained in:
meisnate12 2021-05-27 16:09:39 -04:00
parent e87c71f659
commit f2f28a59d5
2 changed files with 45 additions and 107 deletions

View file

@ -551,7 +551,7 @@ class CollectionBuilder:
for smart_key, smart_data in filter_dict.items():
smart, smart_mod, smart_final = self._split(smart_key)
def build_url_arg(arg, mod=None, arg_s=None, mod_s=None, param_s=None):
def build_url_arg(arg, mod=None, arg_s=None, mod_s=None):
arg_key = plex.search_translation[smart] if smart in plex.search_translation else smart
if mod is None:
mod = plex.modifier_translation[smart_mod] if smart_mod in plex.modifier_translation else smart_mod
@ -561,17 +561,16 @@ class CollectionBuilder:
mod_s = "does not contain" if smart_mod == ".not" else "contains"
elif mod_s is None:
mod_s = plex.mod_displays[smart_mod]
if param_s is None:
param_s = smart.title().replace('_', ' ')
param_s = plex.search_display[smart] if smart in plex.search_display else smart.title().replace('_', ' ')
display_line = f"{indent}{param_s} {mod_s} {arg_s}"
return f"{arg_key}{mod}={arg}&", display_line
if smart_final in plex.movie_only_smart_searches and self.library.is_show:
raise Failed(f"Collection Error: {smart_final} smart filter attribute only works for movie libraries")
elif smart_final in plex.show_only_smart_searches and self.library.is_movie:
raise Failed(f"Collection Error: {smart_final} smart filter attribute only works for show libraries")
elif smart_final not in plex.smart_searches:
if smart_final not in plex.searches and smart_final not in ["any", "all"] and smart_mod != ".and":
raise Failed(f"Collection Error: {smart_final} is not a valid smart filter attribute")
elif smart_final in plex.movie_only_searches and self.library.is_show:
raise Failed(f"Collection Error: {smart_final} smart filter attribute only works for movie libraries")
elif smart_final in plex.show_only_searches and self.library.is_movie:
raise Failed(f"Collection Error: {smart_final} smart filter attribute only works for show libraries")
elif smart_data is None:
raise Failed(f"Collection Error: {smart_final} smart filter attribute is blank")
elif smart in ["all", "any"]:
@ -589,16 +588,16 @@ class CollectionBuilder:
validation = self.validate_attribute(smart, smart_mod, smart_final, smart_data, validate, smart=True)
if validation is None:
continue
elif smart in ["added", "episode_added", "release", "episode_air_date"] and smart_mod in ["", ".not"]:
elif smart in plex.date_searches and smart_mod in ["", ".not"]:
last_text = "is not in the last" if smart_mod == ".not" else "is in the last"
last_mod = "%3E%3E" if smart_mod == "" else "%3C%3C"
results, display_add = build_url_arg(f"-{validation}d", mod=last_mod, arg_s=f"{validation} Days", mod_s=last_text)
elif smart in ["duration"] and smart_mod in [".gt", ".gte", ".lt", ".lte"]:
elif smart == "duration" and smart_mod in [".gt", ".gte", ".lt", ".lte"]:
results, display_add = build_url_arg(validation * 60000)
elif smart == "hdr":
hdr_mod = "" if validation else "!"
hdr_arg = "true" if validation else "false"
results, display_add = build_url_arg(1, mod=hdr_mod, arg_s=hdr_arg, mod_s="is", param_s="HDR")
elif smart in plex.boolean_searches:
bool_mod = "" if validation else "!"
bool_arg = "true" if validation else "false"
results, display_add = build_url_arg(1, mod=bool_mod, arg_s=bool_arg, mod_s="is")
elif (smart in ["title", "episode_title", "studio", "decade", "year", "episode_year"] or smart in plex.tags) and smart_mod in ["", ".not", ".begins", ".ends"]:
results = ""
display_add = ""
@ -730,21 +729,21 @@ class CollectionBuilder:
elif method_name == "sync_mode":
if str(method_data).lower() in ["append", "sync"]: self.details[method_name] = method_data.lower()
else: raise Failed("Collection Error: sync_mode attribute must be either 'append' or 'sync'")
elif method_name in ["label", "label.remove", "label.sync"]:
elif method_name == "label":
if "label" in self.data and "label.sync" in self.data:
raise Failed(f"Collection Error: Cannot use label and label.sync together")
if "label.remove" in self.data and "label.sync" in self.data:
raise Failed(f"Collection Error: Cannot use label.remove and label.sync together")
if method_name == "label" and "label_sync_mode" in self.data and self.data["label_sync_mode"] == "sync":
if method_final == "label" and "label_sync_mode" in self.data and self.data["label_sync_mode"] == "sync":
self.details["label.sync"] = util.get_list(method_data)
else:
self.details[method_name] = util.get_list(method_data)
elif method_name in ["item_label", "item_label.remove", "item_label.sync"]:
self.details[method_final] = util.get_list(method_data)
elif method_name == "item_label":
if "item_label" in self.data and "item_label.sync" in self.data:
raise Failed(f"Collection Error: Cannot use item_label and item_label.sync together")
if "item_label.remove" in self.data and "item_label.sync" in self.data:
raise Failed(f"Collection Error: Cannot use item_label.remove and item_label.sync together")
self.item_details[method_name] = util.get_list(method_data)
self.item_details[method_final] = util.get_list(method_data)
elif method_name in plex.item_advance_keys:
key, options = plex.item_advance_keys[method_name]
if method_name in advance_new_agent and self.library.agent not in plex.new_plex_agents:
@ -799,31 +798,8 @@ class CollectionBuilder:
self.sonarr_options[method_name[7:]] = util.get_bool(method_name, method_data)
elif method_name == "sonarr_tag":
self.sonarr_options["tag"] = util.get_list(method_data)
elif method_name in ["title", "title.and", "title.not", "title.begins", "studio.ends", "studio", "studio.and", "studio.not", "studio.begins", "studio.ends"]:
self.methods.append(("plex_search", [{method_name: util.get_list(method_data, split=False)}]))
elif method_name in ["year.gt", "year.gte", "year.lt", "year.lte"]:
self.methods.append(("plex_search", [{method_name: util.check_year(method_data, self.current_year, method_name)}]))
elif method_name in ["added.before", "added.after", "release.before", "release.after"]:
self.methods.append(("plex_search", [{method_name: util.check_date(method_data, method_name, return_string=True, plex_date=True)}]))
elif method_name in ["added", "added.not", "release", "release.not", "duration.gt", "duration.gte", "duration.lt", "duration.lte"]:
self.methods.append(("plex_search", [{method_name: util.check_number(method_data, method_name, minimum=1)}]))
elif method_name in ["user_rating.gt", "user_rating.gte", "user_rating.lt", "user_rating.lte", "critic_rating.gt", "critic_rating.gte", "critic_rating.lt", "critic_rating.lte", "audience_rating.gt", "audience_rating.gte", "audience_rating.lt", "audience_rating.lte"]:
self.methods.append(("plex_search", [{method_name: util.check_number(method_data, method_name, number_type="float", minimum=0, maximum=10)}]))
elif method_name in ["decade", "year", "year.not"]:
self.methods.append(("plex_search", [{method_name: util.get_year_list(method_data, self.current_year, method_name)}]))
elif method_name in plex.searches:
if method_name in plex.tmdb_searches:
final_values = []
for value in util.get_list(method_data):
if value.lower() == "tmdb" and "tmdb_person" in self.details:
for name in self.details["tmdb_person"]:
final_values.append(name)
else:
final_values.append(value)
else:
final_values = method_data
search = self.library.validate_search_list(final_values, os.path.splitext(method_name)[0])
self.methods.append(("plex_search", [{method_name: search}]))
elif method_final in plex.searches:
self.methods.append(("plex_search", [{method_name: self.validate_attribute(method_name, method_mod, method_final, method_data, True)}]))
elif method_name == "plex_all":
self.methods.append((method_name, [""]))
elif method_name == "anidb_popular":
@ -1334,7 +1310,7 @@ class CollectionBuilder:
return util.check_number(data, final, number_type="float", minimum=0, maximum=10)
elif attribute in ["decade", "year", "episode_year"] and modifier in ["", ".not"]:
return smart_pair(util.get_year_list(data, self.current_year, final))
elif attribute == "hdr":
elif attribute in plex.boolean_searches:
return util.get_bool(attribute, data)
else:
raise Failed(f"Collection Error: modifier: {modifier} not supported with the {attribute} attribute")
@ -1358,6 +1334,7 @@ class CollectionBuilder:
current = self.library.fetchItem(item.ratingKey if isinstance(item, (Movie, Show)) else int(item))
if not isinstance(current, (Movie, Show)):
raise NotFound
return current
except (BadRequest, NotFound):
raise Failed(f"Plex Error: Item {item} not found")

View file

@ -91,20 +91,21 @@ searches = [
"producer", "producer.and", "producer.not",
"subtitle_language", "subtitle_language.and", "subtitle_language.not",
"writer", "writer.and", "writer.not",
"decade", "resolution", "hdr",
"decade", "resolution", "hdr", "unmatched", "duplicate", "unplayed", "progress", "trash",
"last_played", "last_played.not", "last_played.before", "last_played.after",
"added", "added.not", "added.before", "added.after",
"release", "release.not",
"release.before", "release.after",
"release", "release.not", "release.before", "release.after",
"duration.gt", "duration.gte", "duration.lt", "duration.lte",
"plays.gt", "plays.gte", "plays.lt", "plays.lte",
"user_rating.gt", "user_rating.gte", "user_rating.lt", "user_rating.lte",
"critic_rating.gt", "critic_rating.gte", "critic_rating.lt", "critic_rating.lte",
"audience_rating.gt", "audience_rating.gte", "audience_rating.lt", "audience_rating.lte",
"year", "year.not", "year.gt", "year.gte", "year.lt", "year.lte",
"unplayed_episodes", "episode_unplayed", "episode_duplicate", "episode_progress", "episode_unmatched",
"episode_title", "episode_title.and", "episode_title.not", "episode_title.begins", "episode_title.ends",
"episode_added", "episode_added.not", "episode_added.before", "episode_added.after",
"episode_air_date", "episode_air_date.not",
"episode_air_date.before", "episode_air_date.after",
"episode_air_date", "episode_air_date.not", "episode_air_date.before", "episode_air_date.after",
"episode_last_played", "episode_last_played.not", "episode_last_played.before", "episode_last_played.after",
"episode_plays.gt", "episode_plays.gte", "episode_plays.lt", "episode_plays.lte",
"episode_user_rating.gt", "episode_user_rating.gte", "episode_user_rating.lt", "episode_user_rating.lte",
"episode_year", "episode_year.not", "episode_year.gt", "episode_year.gte", "episode_year.lt", "episode_year.lte"
@ -114,7 +115,8 @@ movie_only_searches = [
"director", "director.and", "director.not",
"producer", "producer.and", "producer.not",
"writer", "writer.and", "writer.not",
"decade", "resolution",
"decade", "duplicate", "unplayed", "progress", "trash",
"plays.gt", "plays.gte", "plays.lt", "plays.lte",
"duration.gt", "duration.gte", "duration.lt", "duration.lte"
]
show_only_searches = [
@ -133,6 +135,18 @@ tmdb_searches = [
"producer", "producer.and", "producer.not",
"writer", "writer.and", "writer.not"
]
boolean_searches = [
"hdr", "unmatched", "duplicate", "unplayed", "progress", "trash",
"unplayed_episodes", "episode_unplayed", "episode_duplicate", "episode_progress", "episode_unmatched",
]
date_searches = ["added", "episode_added", "release", "episode_air_date", "last_played", "episode_last_played"]
search_display = {
"added": "Date Added",
"release": "Release Date",
"hdr": "HDR",
"progress": "In Progress",
"episode_progress": "Episode In Progress"
}
sorts = {
None: None,
"title.asc": "titleSort:asc", "title.desc": "titleSort:desc",
@ -183,59 +197,6 @@ tags = [
"subtitle_language",
"writer"
]
smart_searches = [
"all", "any",
"title", "title.not", "title.begins", "title.ends",
"studio", "studio.not", "studio.begins", "studio.ends",
"actor", "actor.not",
"audio_language", "audio_language.not",
"collection", "collection.not",
"content_rating", "content_rating.not",
"country", "country.not",
"director", "director.not",
"genre", "genre.not",
"label", "label.not",
"network", "network.not",
"producer", "producer.not",
"subtitle_language", "subtitle_language.not",
"writer", "writer.not",
"decade", "resolution", "hdr",
"added", "added.not", "added.before", "added.after",
"release", "release.not",
"release.before", "release.after",
"plays.gt", "plays.gte", "plays.lt", "plays.lte",
"duration.gt", "duration.gte", "duration.lt", "duration.lte",
"user_rating.gt", "user_rating.gte", "user_rating.lt", "user_rating.lte",
"audience_rating.gt", "audience_rating.gte", "audience_rating.lt","audience_rating.lte",
"critic_rating.gt", "critic_rating.gte", "critic_rating.lt","critic_rating.lte",
"year", "year.not", "year.gt", "year.gte", "year.lt","year.lte",
"episode_title", "episode_title.not", "episode_title.begins", "episode_title.ends",
"episode_added", "episode_added.not", "episode_added.before", "episode_added.after",
"episode_air_date", "episode_air_date.not",
"episode_air_date.before", "episode_air_date.after",
"episode_year", "episode_year.not", "episode_year.gt", "episode_year.gte", "episode_year.lt","episode_year.lte",
"episode_user_rating.gt", "episode_user_rating.gte", "episode_user_rating.lt","episode_user_rating.lte",
"episode_plays.gt", "episode_plays.gte", "episode_plays.lt", "episode_plays.lte"
]
movie_only_smart_searches = [
"country", "country.not",
"director", "director.not",
"producer", "producer.not",
"writer", "writer.not",
"decade",
"plays.gt", "plays.gte", "plays.lt", "plays.lte",
"duration.gt", "duration.gte", "duration.lt", "duration.lte"
]
show_only_smart_searches = [
"network", "network.not",
"episode_title", "episode_title.not", "episode_title.begins", "episode_title.ends",
"episode_added", "episode_added.not", "episode_added.before", "episode_added.after",
"episode_air_date", "episode_air_date.not",
"episode_air_date.before", "episode_air_date.after",
"episode_year", "episode_year.not", "episode_year.gt", "episode_year.gte", "episode_year.lt","episode_year.lte",
"episode_user_rating.gt", "episode_user_rating.gte", "episode_user_rating.lt","episode_user_rating.lte",
"episode_plays.gt", "episode_plays.gte", "episode_plays.lt", "episode_plays.lte"
]
movie_smart_sorts = {
"title.asc": "titleSort", "title.desc": "titleSort%3Adesc",
"year.asc": "year", "year.desc": "year%3Adesc",
@ -569,9 +530,9 @@ class PlexAPI:
else:
search, modifier = os.path.splitext(str(search_method).lower())
final_search = search_translation[search] if search in search_translation else search
if search in ["added", "release", "episode_air_date"] and modifier == "":
if search in date_searches and modifier == "":
final_mod = ">>"
elif search in ["added", "release", "episode_air_date"] and modifier == ".not":
elif search in date_searches and modifier == ".not":
final_mod = "<<"
elif search in ["critic_rating", "audience_rating"] and modifier == ".gt":
final_mod = "__gt"
@ -583,7 +544,7 @@ class PlexAPI:
if search == "duration":
search_terms[final_method] = search_data * 60000
elif search in ["added", "release", "episode_air_date"] and modifier in ["", ".not"]:
elif search in date_searches and modifier in ["", ".not"]:
search_terms[final_method] = f"{search_data}d"
else:
search_terms[final_method] = search_data