fixed missing filters

pull/351/head
meisnate12 3 years ago
parent a9f9cca61e
commit b76b54ade5

@ -110,6 +110,7 @@ all_filters = [
"writer", "writer.not", "writer", "writer.not",
"year", "year.gt", "year.gte", "year.lt", "year.lte", "year.not" "year", "year.gt", "year.gte", "year.lt", "year.lte", "year.not"
] ]
tmdb_filters = ("original_language", "tmdb_vote_count", "year")
movie_only_filters = [ movie_only_filters = [
"audio_language", "audio_language.not", "audio_language", "audio_language.not",
"audio_track_title", "audio_track_title.not", "audio_track_title.begins", "audio_track_title.ends", "audio_track_title.regex", "audio_track_title", "audio_track_title.not", "audio_track_title.begins", "audio_track_title.ends", "audio_track_title.regex",
@ -158,10 +159,9 @@ class CollectionBuilder:
self.sonarr_options = {} self.sonarr_options = {}
self.missing_movies = [] self.missing_movies = []
self.missing_shows = [] self.missing_shows = []
self.filtered_missing_movies = []
self.filtered_missing_shows = []
self.builders = [] self.builders = []
self.filters = [] self.filters = []
self.tmdb_filters = []
self.rating_keys = [] self.rating_keys = []
self.run_again_movies = [] self.run_again_movies = []
self.run_again_shows = [] self.run_again_shows = []
@ -177,8 +177,8 @@ class CollectionBuilder:
methods = {m.lower(): m for m in self.data} methods = {m.lower(): m for m in self.data}
if "template" in methods: if "template" in methods:
logger.info("") logger.debug("")
logger.info("Validating Method: template") logger.debug("Validating Method: template")
if not self.metadata.templates: if not self.metadata.templates:
raise Failed("Collection Error: No templates found") raise Failed("Collection Error: No templates found")
elif not self.data[methods["template"]]: elif not self.data[methods["template"]]:
@ -290,8 +290,8 @@ class CollectionBuilder:
continue continue
if "schedule" in methods: if "schedule" in methods:
logger.info("") logger.debug("")
logger.info("Validating Method: schedule") logger.debug("Validating Method: schedule")
if not self.data[methods["schedule"]]: if not self.data[methods["schedule"]]:
raise Failed("Collection Error: schedule attribute is blank") raise Failed("Collection Error: schedule attribute is blank")
else: else:
@ -359,29 +359,29 @@ class CollectionBuilder:
self.validate_builders = True self.validate_builders = True
if "validate_builders" in methods: if "validate_builders" in methods:
logger.info("") logger.debug("")
logger.info("Validating Method: validate_builders") logger.debug("Validating Method: validate_builders")
logger.info(f"Value: {data[methods['validate_builders']]}") logger.debug(f"Value: {data[methods['validate_builders']]}")
self.validate_builders = util.parse("validate_builders", self.data, datatype="bool", methods=methods, default=True) self.validate_builders = util.parse("validate_builders", self.data, datatype="bool", methods=methods, default=True)
self.run_again = False self.run_again = False
if "run_again" in methods: if "run_again" in methods:
logger.info("") logger.debug("")
logger.info("Validating Method: run_again") logger.debug("Validating Method: run_again")
logger.info(f"Value: {data[methods['run_again']]}") logger.debug(f"Value: {data[methods['run_again']]}")
self.run_again = util.parse("run_again", self.data, datatype="bool", methods=methods, default=False) self.run_again = util.parse("run_again", self.data, datatype="bool", methods=methods, default=False)
self.build_collection = True self.build_collection = True
if "build_collection" in methods: if "build_collection" in methods:
logger.info("") logger.debug("")
logger.info("Validating Method: build_collection") logger.debug("Validating Method: build_collection")
logger.info(f"Value: {data[methods['build_collection']]}") logger.debug(f"Value: {data[methods['build_collection']]}")
self.build_collection = util.parse("build_collection", self.data, datatype="bool", methods=methods, default=True) self.build_collection = util.parse("build_collection", self.data, datatype="bool", methods=methods, default=True)
self.sync = self.library.sync_mode == "sync" self.sync = self.library.sync_mode == "sync"
if "sync_mode" in methods: if "sync_mode" in methods:
logger.info("") logger.debug("")
logger.info("Validating Method: sync_mode") logger.debug("Validating Method: sync_mode")
if not self.data[methods["sync_mode"]]: if not self.data[methods["sync_mode"]]:
logger.warning(f"Collection Warning: sync_mode attribute is blank using general: {self.library.sync_mode}") logger.warning(f"Collection Warning: sync_mode attribute is blank using general: {self.library.sync_mode}")
else: else:
@ -393,20 +393,22 @@ class CollectionBuilder:
self.custom_sort = False self.custom_sort = False
if "collection_order" in methods: if "collection_order" in methods:
logger.info("") logger.debug("")
logger.info("Validating Method: collection_order") logger.debug("Validating Method: collection_order")
if self.data[methods["collection_order"]] is None: if self.data[methods["collection_order"]] is None:
raise Failed(f"Collection Warning: collection_order attribute is blank") raise Failed(f"Collection Warning: collection_order attribute is blank")
elif self.data[methods["collection_order"]].lower() in plex.collection_order_options:
self.details["collection_order"] = self.data[methods["collection_order"]].lower()
if self.data[methods["collection_order"]].lower() == "custom" and self.build_collection:
self.custom_sort = True
else: else:
raise Failed(f"Collection Error: {self.data[methods['collection_order']]} collection_order invalid\n\trelease (Order Collection by release dates)\n\talpha (Order Collection Alphabetically)\n\tcustom (Custom Order Collection)") logger.debug(f"Value: {self.data[methods['collection_order']]}")
if self.data[methods["collection_order"]].lower() in plex.collection_order_options:
self.details["collection_order"] = self.data[methods["collection_order"]].lower()
if self.data[methods["collection_order"]].lower() == "custom" and self.build_collection:
self.custom_sort = True
else:
raise Failed(f"Collection Error: {self.data[methods['collection_order']]} collection_order invalid\n\trelease (Order Collection by release dates)\n\talpha (Order Collection Alphabetically)\n\tcustom (Custom Order Collection)")
if "tmdb_person" in methods: if "tmdb_person" in methods:
logger.info("") logger.debug("")
logger.info("Validating Method: tmdb_person") logger.debug("Validating Method: tmdb_person")
if not self.data[methods["tmdb_person"]]: if not self.data[methods["tmdb_person"]]:
raise Failed("Collection Error: tmdb_person attribute is blank") raise Failed("Collection Error: tmdb_person attribute is blank")
else: else:
@ -427,8 +429,8 @@ class CollectionBuilder:
self.smart_sort = "random" self.smart_sort = "random"
self.smart_label_collection = False self.smart_label_collection = False
if "smart_label" in methods: if "smart_label" in methods:
logger.info("") logger.debug("")
logger.info("Validating Method: smart_label") logger.debug("Validating Method: smart_label")
self.smart_label_collection = True self.smart_label_collection = True
if not self.data[methods["smart_label"]]: if not self.data[methods["smart_label"]]:
logger.warning("Collection Error: smart_label attribute is blank defaulting to random") logger.warning("Collection Error: smart_label attribute is blank defaulting to random")
@ -444,8 +446,8 @@ class CollectionBuilder:
self.smart_type_key = None self.smart_type_key = None
self.smart_filter_details = "" self.smart_filter_details = ""
if "smart_url" in methods: if "smart_url" in methods:
logger.info("") logger.debug("")
logger.info("Validating Method: smart_url") logger.debug("Validating Method: smart_url")
if not self.data[methods["smart_url"]]: if not self.data[methods["smart_url"]]:
raise Failed("Collection Error: smart_url attribute is blank") raise Failed("Collection Error: smart_url attribute is blank")
else: else:
@ -524,6 +526,8 @@ class CollectionBuilder:
else: else:
logger.error(e) logger.error(e)
self.tmdb_filters = [(fm, fd) for fm, fd in self.filters if fm.startswith(tmdb_filters)]
if self.custom_sort and len(self.builders) > 1: if self.custom_sort and len(self.builders) > 1:
raise Failed("Collection Error: collection_order: custom can only be used with a single builder per collection") raise Failed("Collection Error: collection_order: custom can only be used with a single builder per collection")
@ -969,16 +973,22 @@ class CollectionBuilder:
validate = dict_data["validate"] validate = dict_data["validate"]
for filter_method, filter_data in dict_data.items(): for filter_method, filter_data in dict_data.items():
filter_attr, modifier, filter_final = self._split(filter_method) filter_attr, modifier, filter_final = self._split(filter_method)
message = None
if filter_final not in all_filters: if filter_final not in all_filters:
raise Failed(f"Collection Error: {filter_final} is not a valid filter attribute") message = f"Collection Error: {filter_final} is not a valid filter attribute"
elif filter_final in movie_only_filters and self.library.is_show: elif filter_final in movie_only_filters and self.library.is_show:
raise Failed(f"Collection Error: {filter_final} filter attribute only works for movie libraries") message = f"Collection Error: {filter_final} filter attribute only works for movie libraries"
elif filter_final in show_only_filters and self.library.is_movie: elif filter_final in show_only_filters and self.library.is_movie:
raise Failed(f"Collection Error: {filter_final} filter attribute only works for show libraries") message = f"Collection Error: {filter_final} filter attribute only works for show libraries"
elif filter_final is None: elif filter_final is None:
raise Failed(f"Collection Error: {filter_final} filter attribute is blank") message = f"Collection Error: {filter_final} filter attribute is blank"
else: else:
self.filters.append((filter_final, self.validate_attribute(filter_attr, modifier, f"{filter_final} filter", filter_data, validate))) self.filters.append((filter_final, self.validate_attribute(filter_attr, modifier, f"{filter_final} filter", filter_data, validate)))
if message:
if validate:
raise Failed(message)
else:
logger.error(message)
def collect_rating_keys(self): def collect_rating_keys(self):
filtered_keys = {} filtered_keys = {}
@ -1018,37 +1028,15 @@ class CollectionBuilder:
for movie_id in movie_ids: for movie_id in movie_ids:
if movie_id in self.library.movie_map: if movie_id in self.library.movie_map:
add_rating_keys(self.library.movie_map[movie_id]) add_rating_keys(self.library.movie_map[movie_id])
elif movie_id not in self.missing_movies and movie_id not in self.filtered_missing_movies: elif movie_id not in self.missing_movies:
filter_missing = False self.missing_movies.append(movie_id)
if self.details["released_missing_only"]:
try:
movie = self.config.TMDb.get_movie(movie_id)
if util.validate_date(movie.release_date, "") > self.current_time:
filter_missing = True
except Failed:
pass
if filter_missing:
self.filtered_missing_movies.append(movie_id)
else:
self.missing_movies.append(movie_id)
if len(show_ids) > 0: if len(show_ids) > 0:
items_found_inside += len(show_ids) items_found_inside += len(show_ids)
for show_id in show_ids: for show_id in show_ids:
if show_id in self.library.show_map: if show_id in self.library.show_map:
add_rating_keys(self.library.show_map[show_id]) add_rating_keys(self.library.show_map[show_id])
elif show_id not in self.missing_shows and show_id not in self.filtered_missing_shows: elif show_id not in self.missing_shows:
filter_missing = False self.missing_shows.append(show_id)
if self.details["released_missing_only"]:
try:
show = self.config.TMDb.get_show(show_id)
if util.validate_date(show.first_air_date, "") > self.current_time:
filter_missing = True
except Failed:
pass
if filter_missing:
self.filtered_missing_shows.append(show_id)
else:
self.missing_shows.append(show_id)
return items_found_inside return items_found_inside
for method, value in self.builders: for method, value in self.builders:
logger.debug("") logger.debug("")
@ -1068,6 +1056,31 @@ class CollectionBuilder:
elif "trakt" in method: check_map(self.config.Trakt.get_items(method, value, self.library.is_movie)) elif "trakt" in method: check_map(self.config.Trakt.get_items(method, value, self.library.is_movie))
else: logger.error(f"Collection Error: {method} method not supported") else: logger.error(f"Collection Error: {method} method not supported")
def tmdb_filter(self, item_id, is_movie, item=None):
filter_missing = False
if self.tmdb_filters or self.details["released_missing_only"]:
try:
if item is None:
item = self.config.TMDb.get_movie(item_id) if is_movie else self.config.TMDb.get_movie(self.config.Convert.tvdb_to_tmdb(item_id))
if self.details["released_missing_only"]:
if util.validate_date(item.release_date if is_movie else item.first_air_date, "") > self.current_time:
return True
for filter_method, filter_data in self.tmdb_filters:
if (filter_method == "original_language" and item.original_language not in filter_data) \
or (filter_method == "original_language.not" and item.original_language in filter_data) \
or (filter_method == "tmdb_vote_count.gt" and item.vote_count <= filter_data) \
or (filter_method == "tmdb_vote_count.gte" and item.vote_count < filter_data) \
or (filter_method == "tmdb_vote_count.lt" and item.vote_count >= filter_data) \
or (filter_method == "tmdb_vote_count.lte" and item.vote_count > filter_data) \
or (filter_method == "year.gt" and item.year <= filter_data) \
or (filter_method == "year.gte" and item.year < filter_data) \
or (filter_method == "year.lt" and item.year >= filter_data) \
or (filter_method == "year.lte" and item.year > filter_data):
return True
except Failed:
return True
return filter_missing
def build_filter(self, method, plex_filter, smart=False): def build_filter(self, method, plex_filter, smart=False):
if smart: if smart:
logger.info("") logger.info("")
@ -1500,10 +1513,6 @@ class CollectionBuilder:
return True return True
def run_missing(self): def run_missing(self):
arr_filters = []
for filter_method, filter_data in self.filters:
if (filter_method.startswith("original_language") and self.library.is_movie) or filter_method.startswith("tmdb_vote_count"):
arr_filters.append((filter_method, filter_data))
if len(self.missing_movies) > 0: if len(self.missing_movies) > 0:
missing_movies_with_names = [] missing_movies_with_names = []
for missing_id in self.missing_movies: for missing_id in self.missing_movies:
@ -1512,23 +1521,14 @@ class CollectionBuilder:
except Failed as e: except Failed as e:
logger.error(e) logger.error(e)
continue continue
match = True
for filter_method, filter_data in arr_filters:
if (filter_method == "original_language" and movie.original_language not in filter_data) \
or (filter_method == "original_language.not" and movie.original_language in filter_data) \
or (filter_method == "tmdb_vote_count.gt" and movie.vote_count <= filter_data) \
or (filter_method == "tmdb_vote_count.gte" and movie.vote_count < filter_data) \
or (filter_method == "tmdb_vote_count.lt" and movie.vote_count >= filter_data) \
or (filter_method == "tmdb_vote_count.lte" and movie.vote_count > filter_data):
match = False
break
current_title = f"{movie.title} ({util.validate_date(movie.release_date, 'test').year})" if movie.release_date else movie.title current_title = f"{movie.title} ({util.validate_date(movie.release_date, 'test').year})" if movie.release_date else movie.title
if match: if self.tmdb_filter(missing_id, True, item=movie):
if self.details["show_filtered"] is True and self.details["show_missing"] is True:
logger.info(f"{self.name} Collection | X | {current_title} (TMDb: {missing_id})")
else:
missing_movies_with_names.append((current_title, missing_id)) missing_movies_with_names.append((current_title, missing_id))
if self.details["show_missing"] is True: if self.details["show_missing"] is True:
logger.info(f"{self.name} Collection | ? | {current_title} (TMDb: {missing_id})") logger.info(f"{self.name} Collection | ? | {current_title} (TMDb: {missing_id})")
elif self.details["show_filtered"] is True:
logger.info(f"{self.name} Collection | X | {current_title} (TMDb: {missing_id})")
logger.info("") logger.info("")
logger.info(f"{len(missing_movies_with_names)} Movie{'s' if len(missing_movies_with_names) > 1 else ''} Missing") logger.info(f"{len(missing_movies_with_names)} Movie{'s' if len(missing_movies_with_names) > 1 else ''} Missing")
if self.details["save_missing"] is True: if self.details["save_missing"] is True:
@ -1546,26 +1546,18 @@ class CollectionBuilder:
missing_shows_with_names = [] missing_shows_with_names = []
for missing_id in self.missing_shows: for missing_id in self.missing_shows:
try: try:
title = str(self.config.TVDb.get_series(self.language, missing_id).title.encode("ascii", "replace").decode()) show = self.config.TVDb.get_series(self.language, missing_id)
except Failed as e: except Failed as e:
logger.error(e) logger.error(e)
continue continue
match = True current_title = str(show.title.encode("ascii", "replace").decode())
if arr_filters: if self.tmdb_filter(missing_id, False):
show = self.config.TMDb.get_show(self.config.Convert.tvdb_to_tmdb(missing_id)) if self.details["show_filtered"] is True and self.details["show_missing"] is True:
for filter_method, filter_data in arr_filters: logger.info(f"{self.name} Collection | X | {current_title} (TVDb: {missing_id})")
if (filter_method == "tmdb_vote_count.gt" and show.vote_count <= filter_data) \ else:
or (filter_method == "tmdb_vote_count.gte" and show.vote_count < filter_data) \ missing_shows_with_names.append((current_title, missing_id))
or (filter_method == "tmdb_vote_count.lt" and show.vote_count >= filter_data) \
or (filter_method == "tmdb_vote_count.lte" and show.vote_count > filter_data):
match = False
break
if match:
missing_shows_with_names.append((title, missing_id))
if self.details["show_missing"] is True: if self.details["show_missing"] is True:
logger.info(f"{self.name} Collection | ? | {title} (TVDB: {missing_id})") logger.info(f"{self.name} Collection | ? | {current_title} (TVDB: {missing_id})")
elif self.details["show_filtered"] is True:
logger.info(f"{self.name} Collection | X | {title} (TVDb: {missing_id})")
logger.info("") logger.info("")
logger.info(f"{len(missing_shows_with_names)} Show{'s' if len(missing_shows_with_names) > 1 else ''} Missing") logger.info(f"{len(missing_shows_with_names)} Show{'s' if len(missing_shows_with_names) > 1 else ''} Missing")
if self.details["save_missing"] is True: if self.details["save_missing"] is True:

@ -108,7 +108,7 @@ class Cache:
row = cursor.fetchone() row = cursor.fetchone()
if row: if row:
time_between_insertion = datetime.now() - datetime.strptime(row["expiration_date"], "%Y-%m-%d") time_between_insertion = datetime.now() - datetime.strptime(row["expiration_date"], "%Y-%m-%d")
id_to_return = row["t_id"] id_to_return = int(row["t_id"])
media_type = row["media_type"] media_type = row["media_type"]
expired = time_between_insertion.days > self.expiration expired = time_between_insertion.days > self.expiration
return id_to_return, media_type, expired return id_to_return, media_type, expired

@ -315,6 +315,7 @@ class Convert:
update_cache(tmdb_id, "TMDb", "show_movie") update_cache(tmdb_id, "TMDb", "show_movie")
return "movie", tmdb_id return "movie", tmdb_id
else: else:
logger.debug(f"TMDb: {tmdb_id}, IMDb: {imdb_id}, TVDb: {tvdb_id}")
raise Failed(f"No ID to convert") raise Failed(f"No ID to convert")
except Failed as e: except Failed as e:
logger.info(util.adjust_space(f"Mapping Error | {item.guid:<46} | {e} for {item.title}")) logger.info(util.adjust_space(f"Mapping Error | {item.guid:<46} | {e} for {item.title}"))

@ -67,7 +67,7 @@ class Metadata:
else: else:
return self.collections return self.collections
def update_metadata(self, TMDb, test): def update_metadata(self):
if not self.metadata: if not self.metadata:
return None return None
logger.info("") logger.info("")
@ -75,7 +75,7 @@ class Metadata:
logger.info("") logger.info("")
for mapping_name, meta in self.metadata.items(): for mapping_name, meta in self.metadata.items():
methods = {mm.lower(): mm for mm in meta} methods = {mm.lower(): mm for mm in meta}
if test and ("test" not in methods or meta[methods["test"]] is not True): if self.config.test and ("test" not in methods or meta[methods["test"]] is not True):
continue continue
updated = False updated = False
@ -212,13 +212,13 @@ class Metadata:
logger.error("Metadata Error: tmdb_show attribute is blank") logger.error("Metadata Error: tmdb_show attribute is blank")
else: else:
tmdb_is_movie = False tmdb_is_movie = False
tmdb_item = TMDb.get_show(util.regex_first_int(data, "Show")) tmdb_item = self.config.TMDb.get_show(util.regex_first_int(data, "Show"))
elif "tmdb_movie" in methods: elif "tmdb_movie" in methods:
if meta[methods["tmdb_movie"]] is None: if meta[methods["tmdb_movie"]] is None:
logger.error("Metadata Error: tmdb_movie attribute is blank") logger.error("Metadata Error: tmdb_movie attribute is blank")
else: else:
tmdb_is_movie = True tmdb_is_movie = True
tmdb_item = TMDb.get_movie(util.regex_first_int(meta[methods["tmdb_movie"]], "Movie")) tmdb_item = self.config.TMDb.get_movie(util.regex_first_int(meta[methods["tmdb_movie"]], "Movie"))
except Failed as e: except Failed as e:
logger.error(e) logger.error(e)

@ -132,14 +132,17 @@ show_only_searches = [
"episode_user_rating.gt", "episode_user_rating.gte", "episode_user_rating.lt", "episode_user_rating.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" "episode_year", "episode_year.not", "episode_year.gt", "episode_year.gte", "episode_year.lt", "episode_year.lte"
] ]
number_attributes = ["plays", "episode_plays", "added", "episode_added", "release", "episode_air_date", "duration", "tmdb_vote_count"] number_attributes = [
"plays", "episode_plays", "duration", "tmdb_vote_count", "last_episode_aired"
"added", "episode_added", "release", "episode_air_date", "last_played", "episode_last_played"
]
float_attributes = ["user_rating", "episode_user_rating", "critic_rating", "audience_rating"] float_attributes = ["user_rating", "episode_user_rating", "critic_rating", "audience_rating"]
boolean_attributes = [ boolean_attributes = [
"hdr", "unmatched", "duplicate", "unplayed", "progress", "trash", "hdr", "unmatched", "duplicate", "unplayed", "progress", "trash",
"unplayed_episodes", "episode_unplayed", "episode_duplicate", "episode_progress", "episode_unmatched", "unplayed_episodes", "episode_unplayed", "episode_duplicate", "episode_progress", "episode_unmatched",
] ]
tmdb_attributes = ["actor", "director", "producer", "writer"] tmdb_attributes = ["actor", "director", "producer", "writer"]
date_attributes = ["added", "episode_added", "release", "episode_air_date", "last_played", "episode_last_played"] date_attributes = ["added", "episode_added", "release", "episode_air_date", "last_played", "episode_last_played", "last_episode_aired"]
search_display = {"added": "Date Added", "release": "Release Date", "hdr": "HDR", "progress": "In Progress", "episode_progress": "Episode In Progress"} search_display = {"added": "Date Added", "release": "Release Date", "hdr": "HDR", "progress": "In Progress", "episode_progress": "Episode In Progress"}
sorts = { sorts = {
None: None, None: None,

@ -152,7 +152,7 @@ def update_libraries(config):
util.separator(f"Running Metadata File\n{metadata.path}") util.separator(f"Running Metadata File\n{metadata.path}")
if not config.test_mode and not config.resume_from and not collection_only: if not config.test_mode and not config.resume_from and not collection_only:
try: try:
metadata.update_metadata(config.TMDb, config.test_mode) metadata.update_metadata()
except Failed as e: except Failed as e:
logger.error(e) logger.error(e)
collections_to_run = metadata.get_collections(config.requested_collections) collections_to_run = metadata.get_collections(config.requested_collections)

Loading…
Cancel
Save