final cleanup for v1.12.0

This commit is contained in:
meisnate12 2021-08-16 01:41:04 -04:00
parent ae34662ad7
commit 1e2fc34911
11 changed files with 146 additions and 132 deletions

View file

@ -89,6 +89,6 @@ mal:
token_type:
expires_in:
refresh_token:
anidb:
username: ###### - optional
anidb: # Optional
username: ######
password: ######

View file

@ -4,10 +4,7 @@ from modules.util import Failed
logger = logging.getLogger("Plex Meta Manager")
builders = [
"anilist_genre", "anilist_id", "anilist_popular", "anilist_relations",
"anilist_season", "anilist_studio", "anilist_tag", "anilist_top_rated", "anilist_search"
]
builders = ["anilist_id", "anilist_popular", "anilist_relations", "anilist_studio", "anilist_top_rated", "anilist_search"]
pretty_names = {"score": "Average Score", "popular": "Popularity"}
attr_translation = {"year": "seasonYear", "adult": "isAdult", "start": "startDate", "end": "endDate", "tag_category": "tagCategory", "score": "averageScore", "min_tag_percent": "minimumTagRank"}
mod_translation = {"": "in", "not": "not_in", "before": "greater", "after": "lesser", "gt": "greater", "gte": "greater", "lt": "lesser", "lte": "lesser"}
@ -17,12 +14,13 @@ mod_searches = [
"episodes.gt", "episodes.gte", "episodes.lt", "episodes.lte", "duration.gt", "duration.gte", "duration.lt", "duration.lte",
"score.gt", "score.gte", "score.lt", "score.lte", "popularity.gt", "popularity.gte", "popularity.lt", "popularity.lte"
]
no_mod_searches = ["season", "year", "adult", "min_tag_percent"]
no_mod_searches = ["search", "season", "year", "adult", "min_tag_percent"]
searches = mod_searches + no_mod_searches
search_types = {
"season": "MediaSeason", "seasonYear": "Int", "isAdult": "Boolean", "startDate": "FuzzyDateInt", "endDate": "FuzzyDateInt",
"format": "[MediaFormat]", "status": "[MediaStatus]", "genre": "[String]", "tag": "[String]", "tagCategory": "[String]",
"episodes": "Int", "duration": "Int", "averageScore": "Int", "popularity": "Int", "minimumTagRank": "Int"
"search": "String", "season": "MediaSeason", "seasonYear": "Int", "isAdult": "Boolean", "minimumTagRank": "Int",
"startDate": "FuzzyDateInt", "endDate": "FuzzyDateInt", "format": "[MediaFormat]", "status": "[MediaStatus]",
"genre": "[String]", "tag": "[String]", "tagCategory": "[String]",
"episodes": "Int", "duration": "Int", "averageScore": "Int", "popularity": "Int"
}
media_season = {"winter": "WINTER", "spring": "SPRING", "summer": "SUMMER", "fall": "FALL"}
media_format = {"tv": "TV", "short": "TV_SHORT", "movie": "MOVIE", "special": "SPECIAL", "ova": "OVA", "ona": "ONA", "music": "MUSIC"}

View file

@ -39,7 +39,8 @@ method_alias = {
"years": "year", "show_year": "year", "show_years": "year",
"show_title": "title",
"seasonyear": "year", "isadult": "adult", "startdate": "start", "enddate": "end", "averagescore": "score",
"minimum_tag_percentage": "min_tag_percent", "minimumtagrank": "min_tag_percent", "minimum_tag_rank": "min_tag_percent"
"minimum_tag_percentage": "min_tag_percent", "minimumtagrank": "min_tag_percent", "minimum_tag_rank": "min_tag_percent",
"anilist_tag": "anilist_search", "anilist_genre": "anilist_search", "anilist_season": "anilist_search"
}
filter_translation = {
"actor": "actors",
@ -74,15 +75,15 @@ summary_details = [
]
poster_details = ["url_poster", "tmdb_poster", "tmdb_profile", "tvdb_poster", "file_poster"]
background_details = ["url_background", "tmdb_background", "tvdb_background", "file_background"]
boolean_details = ["visible_library", "visible_home", "visible_shared", "show_filtered", "show_missing", "save_missing", "item_assets", "create_asset_folders", "released_missing_only"]
boolean_details = ["visible_library", "visible_home", "visible_shared", "show_filtered", "show_missing", "save_missing", "item_assets", "missing_only_released"]
string_details = ["sort_title", "content_rating", "name_mapping"]
ignored_details = ["smart_filter", "smart_label", "smart_url", "run_again", "schedule", "sync_mode", "template", "test", "tmdb_person", "build_collection", "collection_order", "validate_builders"]
details = ["collection_mode", "collection_order", "label"] + boolean_details + string_details
collectionless_details = ["collection_order", "plex_collectionless", "label", "label_sync_mode", "test"] + \
poster_details + background_details + summary_details + string_details
item_details = ["item_label", "item_radarr_tag", "item_sonarr_tag", "item_overlay"] + list(plex.item_advance_keys.keys())
radarr_details = ["radarr_add", "radarr_folder", "radarr_monitor", "radarr_search", "radarr_availability", "radarr_quality", "radarr_tag"]
sonarr_details = ["sonarr_add", "sonarr_folder", "sonarr_monitor", "sonarr_language", "sonarr_series", "sonarr_quality", "sonarr_season", "sonarr_search", "sonarr_cutoff_search", "sonarr_tag"]
radarr_details = ["radarr_add", "radarr_add_existing", "radarr_folder", "radarr_monitor", "radarr_search", "radarr_availability", "radarr_quality", "radarr_tag"]
sonarr_details = ["sonarr_add", "sonarr_add_existing", "sonarr_folder", "sonarr_monitor", "sonarr_language", "sonarr_series", "sonarr_quality", "sonarr_season", "sonarr_search", "sonarr_cutoff_search", "sonarr_tag"]
all_filters = [
"actor", "actor.not",
"audio_language", "audio_language.not",
@ -133,35 +134,34 @@ smart_url_invalid = ["filters", "run_again", "sync_mode", "show_filtered", "show
custom_sort_builders = [
"tmdb_list", "tmdb_popular", "tmdb_now_playing", "tmdb_top_rated",
"tmdb_trending_daily", "tmdb_trending_weekly", "tmdb_discover",
"tvdb_list",
"imdb_list",
"tvdb_list", "imdb_list", "stevenlu_popular", "anidb_popular",
"trakt_list", "trakt_trending", "trakt_popular", "trakt_recommended", "trakt_watched", "trakt_collected",
"tautulli_popular", "tautulli_watched", "letterboxd_list", "icheckmovies_list",
"anidb_popular",
"anilist_top_rated", "anilist_popular", "anilist_season", "anilist_studio", "anilist_genre", "anilist_tag",
"anilist_top_rated", "anilist_popular", "anilist_season", "anilist_studio", "anilist_genre", "anilist_tag", "anilist_search",
"mal_all", "mal_airing", "mal_upcoming", "mal_tv", "mal_movie", "mal_ova", "mal_special",
"mal_popular", "mal_favorite", "mal_suggested", "mal_userlist", "mal_season", "mal_genre", "mal_producer"
]
class CollectionBuilder:
def __init__(self, config, library, metadata, name, data):
def __init__(self, config, library, metadata, name, no_missing, data):
self.config = config
self.library = library
self.metadata = metadata
self.name = name
self.no_missing = no_missing
self.data = data
self.language = self.library.Plex.language
self.details = {
"show_filtered": self.library.show_filtered,
"show_missing": self.library.show_missing,
"save_missing": self.library.save_missing,
"released_missing_only": self.library.released_missing_only,
"missing_only_released": self.library.missing_only_released,
"create_asset_folders": self.library.create_asset_folders,
"item_assets": False
}
self.item_details = {}
self.radarr_options = {}
self.sonarr_options = {}
self.radarr_details = {}
self.sonarr_details = {}
self.missing_movies = []
self.missing_shows = []
self.builders = []
@ -175,8 +175,6 @@ class CollectionBuilder:
self.backgrounds = {}
self.summaries = {}
self.schedule = ""
self.add_to_radarr = None
self.add_to_sonarr = None
self.current_time = datetime.now()
self.current_year = self.current_time.year
@ -538,21 +536,30 @@ class CollectionBuilder:
if self.custom_sort and self.builders[0][0] not in custom_sort_builders:
raise Failed(f"Collection Error: collection_order: custom cannot be used with {self.builders[0][0]}")
if self.add_to_radarr is None:
self.add_to_radarr = self.library.Radarr.add if self.library.Radarr else False
if self.add_to_sonarr is None:
self.add_to_sonarr = self.library.Sonarr.add if self.library.Sonarr else False
if "add" not in self.radarr_details:
self.radarr_details["add"] = self.library.Radarr.add if self.library.Radarr else False
if "add_existing" not in self.radarr_details:
self.radarr_details["add_existing"] = self.library.Radarr.add_existing if self.library.Radarr else False
if "add" not in self.sonarr_details:
self.sonarr_details["add"] = self.library.Sonarr.add if self.library.Sonarr else False
if "add_existing" not in self.sonarr_details:
self.sonarr_details["add_existing"] = self.library.Sonarr.add_existing if self.library.Sonarr else False
if self.smart_url:
self.add_to_radarr = False
self.add_to_sonarr = False
if self.smart_url or self.collectionless:
self.radarr_details["add"] = False
self.radarr_details["add_existing"] = False
self.sonarr_details["add"] = False
self.sonarr_details["add_existing"] = False
if self.collectionless:
self.add_to_radarr = False
self.add_to_sonarr = False
self.details["collection_mode"] = "hide"
self.sync = True
self.do_missing = not self.no_missing and (self.details["show_missing"] or self.details["save_missing"]
or (self.library.Radarr and self.radarr_details["add"])
or (self.library.Sonarr and self.sonarr_details["add"]))
if self.build_collection:
try:
self.obj = self.library.get_collection(self.name)
@ -684,48 +691,44 @@ class CollectionBuilder:
self.item_details[method_name] = str(method_data).lower()
def _radarr(self, method_name, method_data):
if method_name == "radarr_add":
self.add_to_radarr = util.parse(method_name, method_data, datatype="bool")
if method_name in ["radarr_add", "radarr_add_existing", "radarr_monitor", "radarr_search"]:
self.radarr_details[method_name[7:]] = util.parse(method_name, method_data, datatype="bool")
elif method_name == "radarr_folder":
self.radarr_options["folder"] = method_data
elif method_name in ["radarr_monitor", "radarr_search"]:
self.radarr_options[method_name[7:]] = util.parse(method_name, method_data, datatype="bool")
self.radarr_details["folder"] = method_data
elif method_name == "radarr_availability":
if str(method_data).lower() in radarr.availability_translation:
self.radarr_options["availability"] = str(method_data).lower()
self.radarr_details["availability"] = str(method_data).lower()
else:
raise Failed(f"Collection Error: {method_name} attribute must be either announced, cinemas, released or db")
elif method_name == "radarr_quality":
self.library.Radarr.get_profile_id(method_data)
self.radarr_options["quality"] = method_data
self.radarr_details["quality"] = method_data
elif method_name == "radarr_tag":
self.radarr_options["tag"] = util.get_list(method_data)
self.radarr_details["tag"] = util.get_list(method_data)
def _sonarr(self, method_name, method_data):
if method_name == "sonarr_add":
self.add_to_sonarr = util.parse(method_name, method_data, datatype="bool")
if method_name in ["sonarr_add", "sonarr_add_existing", "sonarr_season", "sonarr_search", "sonarr_cutoff_search"]:
self.sonarr_details[method_name[7:]] = util.parse(method_name, method_data, datatype="bool")
elif method_name == "sonarr_folder":
self.sonarr_options["folder"] = method_data
self.sonarr_details["folder"] = method_data
elif method_name == "sonarr_monitor":
if str(method_data).lower() in sonarr.monitor_translation:
self.sonarr_options["monitor"] = str(method_data).lower()
self.sonarr_details["monitor"] = str(method_data).lower()
else:
raise Failed(f"Collection Error: {method_name} attribute must be either all, future, missing, existing, pilot, first, latest or none")
elif method_name == "sonarr_quality":
self.library.Sonarr.get_profile_id(method_data, "quality_profile")
self.sonarr_options["quality"] = method_data
self.sonarr_details["quality"] = method_data
elif method_name == "sonarr_language":
self.library.Sonarr.get_profile_id(method_data, "language_profile")
self.sonarr_options["language"] = method_data
self.sonarr_details["language"] = method_data
elif method_name == "sonarr_series":
if str(method_data).lower() in sonarr.series_type:
self.sonarr_options["series"] = str(method_data).lower()
self.sonarr_details["series"] = str(method_data).lower()
else:
raise Failed(f"Collection Error: {method_name} attribute must be either standard, daily, or anime")
elif method_name in ["sonarr_season", "sonarr_search", "sonarr_cutoff_search"]:
self.sonarr_options[method_name[7:]] = util.parse(method_name, method_data, datatype="bool")
elif method_name == "sonarr_tag":
self.sonarr_options["tag"] = util.get_list(method_data)
self.sonarr_details["tag"] = util.get_list(method_data)
def _anidb(self, method_name, method_data):
if method_name == "anidb_popular":
@ -751,55 +754,47 @@ class CollectionBuilder:
self.builders.append((method_name, anilist_id))
elif method_name in ["anilist_popular", "anilist_top_rated"]:
self.builders.append((method_name, util.parse(method_name, method_data, datatype="int", default=10)))
elif method_name in ["anilist_season", "anilist_genre", "anilist_tag"]:
elif method_name == "anilist_search":
if self.current_time.month in [12, 1, 2]: current_season = "winter"
elif self.current_time.month in [3, 4, 5]: current_season = "spring"
elif self.current_time.month in [6, 7, 8]: current_season = "summer"
else: current_season = "fall"
for dict_data, dict_methods in util.parse(method_name, method_data, datatype="dictlist"):
new_dictionary = {}
if method_name == "anilist_season":
if self.current_time.month in [12, 1, 2]: new_dictionary["season"] = "winter"
elif self.current_time.month in [3, 4, 5]: new_dictionary["season"] = "spring"
elif self.current_time.month in [6, 7, 8]: new_dictionary["season"] = "summer"
elif self.current_time.month in [9, 10, 11]: new_dictionary["season"] = "fall"
new_dictionary["season"] = util.parse("season", dict_data, methods=dict_methods, parent=method_name, default=new_dictionary["season"], options=util.seasons)
new_dictionary["year"] = util.parse("year", dict_data, datatype="int", methods=dict_methods, default=self.current_year, parent=method_name, minimum=1917, maximum=self.current_year + 1)
elif method_name == "anilist_genre":
new_dictionary["genre"] = self.config.AniList.validate("Genre", util.parse("genre", dict_data, methods=dict_methods, parent=method_name))
elif method_name == "anilist_tag":
new_dictionary["tag"] = self.config.AniList.validate("Tag", util.parse("tag", dict_data, methods=dict_methods, parent=method_name))
elif method_name == "anilist_search":
for search_method, search_data in dict_data.items():
search_attr, modifier, search_final = self._split(search_method)
if search_data is None:
raise Failed(f"Collection Error: {method_name} {search_final} attribute is blank")
elif search_final not in anilist.searches:
raise Failed(f"Collection Error: {method_name} {search_final} attribute not supported")
elif search_attr == "season":
if self.current_time.month in [12, 1, 2]: new_dictionary["season"] = "winter"
elif self.current_time.month in [3, 4, 5]: new_dictionary["season"] = "spring"
elif self.current_time.month in [6, 7, 8]: new_dictionary["season"] = "summer"
elif self.current_time.month in [9, 10, 11]: new_dictionary["season"] = "fall"
new_dictionary["season"] = util.parse("season", dict_data, parent=method_name, default=new_dictionary["season"], options=util.seasons)
if "year" not in dict_methods:
logger.warning(f"Collection Warning: {method_name} {search_final} attribute must be used with the year attribute using this year by default")
elif search_attr == "year":
if "season" not in dict_methods:
raise Failed(f"Collection Error: {method_name} {search_final} attribute must be used with the season attribute")
new_dictionary[search_attr] = util.parse(search_attr, search_data, datatype="int", parent=method_name, default=self.current_year, minimum=1917, maximum=self.current_year + 1)
elif search_attr == "adult":
new_dictionary[search_attr] = util.parse(search_attr, search_data, datatype="bool", parent=method_name)
elif search_attr in ["episodes", "duration", "score", "popularity"]:
new_dictionary[search_final] = util.parse(search_final, search_data, datatype="int", parent=method_name)
elif search_attr in ["format", "status", "genre", "tag", "tag_category"]:
new_dictionary[search_final] = self.config.AniList.validate(search_attr.replace("_", " ").title(), util.parse(search_final, search_data))
elif search_attr in ["start", "end"]:
new_dictionary[search_final] = util.validate_date(search_data, f"{method_name} {search_final} attribute", return_as="%m/%d/%Y")
elif search_attr == "min_tag_percent":
new_dictionary[search_attr] = util.parse(search_attr, search_data, datatype="int", parent=method_name, minimum=0, maximum=100)
elif search_final not in ["sort_by", "limit"]:
raise Failed(f"Collection Error: {method_name} {search_final} attribute not supported")
if len(new_dictionary) > 0:
raise Failed(f"Collection Error: {method_name} must have at least one valid search option")
for search_method, search_data in dict_data.items():
search_attr, modifier, search_final = self._split(search_method)
if search_data is None:
raise Failed(f"Collection Error: {method_name} {search_final} attribute is blank")
elif search_final not in anilist.searches:
raise Failed(f"Collection Error: {method_name} {search_final} attribute not supported")
elif search_attr == "season":
new_dictionary[search_attr] = util.parse(search_attr, search_data, parent=method_name, default=current_season, options=util.seasons)
if "year" not in dict_methods:
logger.warning(f"Collection Warning: {method_name} year attribute not found using this year: {self.current_year} by default")
new_dictionary["year"] = self.current_year
elif search_attr == "year":
new_dictionary[search_attr] = util.parse(search_attr, search_data, datatype="int", parent=method_name, default=self.current_year, minimum=1917, maximum=self.current_year + 1)
if "season" not in dict_methods:
logger.warning(f"Collection Warning: {method_name} season attribute not found using this season: {current_season} by default")
new_dictionary["season"] = current_season
elif search_attr == "adult":
new_dictionary[search_attr] = util.parse(search_attr, search_data, datatype="bool", parent=method_name)
elif search_attr in ["episodes", "duration", "score", "popularity"]:
new_dictionary[search_final] = util.parse(search_final, search_data, datatype="int", parent=method_name)
elif search_attr in ["format", "status", "genre", "tag", "tag_category"]:
new_dictionary[search_final] = self.config.AniList.validate(search_attr.replace("_", " ").title(), util.parse(search_final, search_data))
elif search_attr in ["start", "end"]:
new_dictionary[search_final] = util.validate_date(search_data, f"{method_name} {search_final} attribute", return_as="%m/%d/%Y")
elif search_attr == "min_tag_percent":
new_dictionary[search_attr] = util.parse(search_attr, search_data, datatype="int", parent=method_name, minimum=0, maximum=100)
elif search_attr == "search":
new_dictionary[search_attr] = str(search_data)
elif search_final not in ["sort_by", "limit"]:
raise Failed(f"Collection Error: {method_name} {search_final} attribute not supported")
if len(new_dictionary) > 0:
raise Failed(f"Collection Error: {method_name} must have at least one valid search option")
new_dictionary["sort_by"] = util.parse("sort_by", dict_data, methods=dict_methods, parent=method_name, default="score", options=["score", "popular"])
new_dictionary["limit"] = util.parse("limit", dict_data, datatype="int", methods=dict_methods, default=0, parent=method_name, maximum=500)
new_dictionary["limit"] = util.parse("limit", dict_data, datatype="int", methods=dict_methods, default=0, parent=method_name)
self.builders.append((method_name, new_dictionary))
def _icheckmovies(self, method_name, method_data):
@ -1029,7 +1024,7 @@ class CollectionBuilder:
else:
logger.error(message)
def find_rating_keys(self, no_missing):
def find_rating_keys(self):
for method, value in self.builders:
ids = []
rating_keys = []
@ -1094,9 +1089,7 @@ class CollectionBuilder:
if input_id in self.library.imdb_map:
rating_keys.append(self.library.imdb_map[input_id][0])
else:
if (self.details["show_missing"] or self.details["save_missing"]
or (self.library.Radarr and self.add_to_radarr)
or (self.library.Sonarr and self.add_to_sonarr)) and not no_missing:
if self.do_missing:
try:
tmdb_id, tmdb_type = self.config.Convert.imdb_to_tmdb(input_id)
if tmdb_type == "movie":
@ -1553,7 +1546,7 @@ class CollectionBuilder:
logger.error(e)
continue
current_title = f"{movie.title} ({util.validate_date(movie.release_date, 'test').year})" if movie.release_date else movie.title
if self.check_tmdb_filter(missing_id, True, item=movie, check_released=self.details["released_missing_only"]):
if self.check_tmdb_filter(missing_id, True, item=movie, check_released=self.details["missing_only_released"]):
missing_movies_with_names.append((current_title, missing_id))
if self.details["show_missing"] is True:
logger.info(f"{self.name} Collection | ? | {current_title} (TMDb: {missing_id})")
@ -1565,12 +1558,12 @@ class CollectionBuilder:
if len(missing_movies_with_names) > 0:
if self.details["save_missing"] is True:
self.library.add_missing(self.name, missing_movies_with_names, True)
if self.run_again or (self.library.Radarr and (self.add_to_radarr or "item_radarr_tag" in self.item_details)):
if self.run_again or (self.library.Radarr and (self.radarr_details["add"] or "item_radarr_tag" in self.item_details)):
missing_tmdb_ids = [missing_id for title, missing_id in missing_movies_with_names]
if self.library.Radarr:
if self.add_to_radarr:
if self.radarr_details["add"]:
try:
self.library.Radarr.add_tmdb(missing_tmdb_ids, **self.radarr_options)
self.library.Radarr.add_tmdb(missing_tmdb_ids, **self.radarr_details)
except Failed as e:
logger.error(e)
if "item_radarr_tag" in self.item_details:
@ -1589,7 +1582,7 @@ class CollectionBuilder:
logger.error(e)
continue
current_title = str(show.title.encode("ascii", "replace").decode())
if self.check_tmdb_filter(missing_id, False, check_released=self.details["released_missing_only"]):
if self.check_tmdb_filter(missing_id, False, check_released=self.details["missing_only_released"]):
missing_shows_with_names.append((current_title, missing_id))
if self.details["show_missing"] is True:
logger.info(f"{self.name} Collection | ? | {current_title} (TVDB: {missing_id})")
@ -1601,12 +1594,12 @@ class CollectionBuilder:
if len(missing_shows_with_names) > 0:
if self.details["save_missing"] is True:
self.library.add_missing(self.name, missing_shows_with_names, False)
if self.run_again or (self.library.Sonarr and (self.add_to_sonarr or "item_sonarr_tag" in self.item_details)):
if self.run_again or (self.library.Sonarr and (self.sonarr_details["add"] or "item_sonarr_tag" in self.item_details)):
missing_tvdb_ids = [missing_id for title, missing_id in missing_shows_with_names]
if self.library.Sonarr:
if self.add_to_sonarr:
if self.sonarr_details["add"]:
try:
self.library.Sonarr.add_tvdb(missing_tvdb_ids, **self.sonarr_options)
self.library.Sonarr.add_tvdb(missing_tvdb_ids, **self.sonarr_details)
except Failed as e:
logger.error(e)
if "item_sonarr_tag" in self.item_details:
@ -1693,9 +1686,9 @@ class CollectionBuilder:
except Failed as e:
logger.error(e)
self.library.edit_tags("label", item, add_tags=add_tags, remove_tags=remove_tags, sync_tags=sync_tags)
if "item_radarr_tag" in self.item_details and item.ratingKey in self.library.movie_rating_key_map:
if item.ratingKey in self.library.movie_rating_key_map:
tmdb_ids.append(self.library.movie_rating_key_map[item.ratingKey])
if "item_sonarr_tag" in self.item_details and item.ratingKey in self.library.show_rating_key_map:
if item.ratingKey in self.library.show_rating_key_map:
tvdb_ids.append(self.library.show_rating_key_map[item.ratingKey])
advance_edits = {}
for method_name, method_data in self.item_details.items():
@ -1706,10 +1699,16 @@ class CollectionBuilder:
self.library.edit_item(item, item.title, "Movie" if self.library.is_movie else "Show", advance_edits, advanced=True)
if len(tmdb_ids) > 0:
self.library.Radarr.edit_tags(tmdb_ids, self.item_details["item_radarr_tag"], self.item_details["apply_tags"])
if "item_radarr_tag" in self.item_details:
self.library.Radarr.edit_tags(tmdb_ids, self.item_details["item_radarr_tag"], self.item_details["apply_tags"])
if self.radarr_details["add_existing"]:
self.library.Radarr.add_tmdb(tmdb_ids, **self.radarr_details)
if len(tvdb_ids) > 0:
self.library.Sonarr.edit_tags(tvdb_ids, self.item_details["item_sonarr_tag"], self.item_details["apply_tags"])
if "item_sonarr_tag" in self.item_details:
self.library.Sonarr.edit_tags(tvdb_ids, self.item_details["item_sonarr_tag"], self.item_details["apply_tags"])
if self.sonarr_details["add_existing"]:
self.library.Sonarr.add_tvdb(tvdb_ids, **self.sonarr_details)
for rating_key in rating_keys:
try:

View file

@ -183,7 +183,7 @@ class Config:
"show_filtered": check_for_attribute(self.data, "show_filtered", parent="settings", var_type="bool", default=False),
"show_missing": check_for_attribute(self.data, "show_missing", parent="settings", var_type="bool", default=True),
"save_missing": check_for_attribute(self.data, "save_missing", parent="settings", var_type="bool", default=True),
"released_missing_only": check_for_attribute(self.data, "released_missing_only", parent="settings", var_type="bool", default=False),
"missing_only_released": check_for_attribute(self.data, "missing_only_released", parent="settings", var_type="bool", default=False),
"create_asset_folders": check_for_attribute(self.data, "create_asset_folders", parent="settings", var_type="bool", default=False)
}
if self.general["cache"]:
@ -295,6 +295,7 @@ class Config:
"url": check_for_attribute(self.data, "url", parent="radarr", var_type="url", default_is_none=True),
"token": check_for_attribute(self.data, "token", parent="radarr", default_is_none=True),
"add": check_for_attribute(self.data, "add", parent="radarr", var_type="bool", default=False),
"add_existing": check_for_attribute(self.data, "add_existing", parent="radarr", var_type="bool", default=False),
"root_folder_path": check_for_attribute(self.data, "root_folder_path", parent="radarr", default_is_none=True),
"monitor": check_for_attribute(self.data, "monitor", parent="radarr", var_type="bool", default=True),
"availability": check_for_attribute(self.data, "availability", parent="radarr", test_list=radarr.availability_descriptions, default="announced"),
@ -306,6 +307,7 @@ class Config:
"url": check_for_attribute(self.data, "url", parent="sonarr", var_type="url", default_is_none=True),
"token": check_for_attribute(self.data, "token", parent="sonarr", default_is_none=True),
"add": check_for_attribute(self.data, "add", parent="sonarr", var_type="bool", default=False),
"add_existing": check_for_attribute(self.data, "add_existing", parent="sonarr", var_type="bool", default=False),
"root_folder_path": check_for_attribute(self.data, "root_folder_path", parent="sonarr", default_is_none=True),
"monitor": check_for_attribute(self.data, "monitor", parent="sonarr", test_list=sonarr.monitor_descriptions, default="all"),
"quality_profile": check_for_attribute(self.data, "quality_profile", parent="sonarr", default_is_none=True),
@ -349,7 +351,7 @@ class Config:
params["show_filtered"] = check_for_attribute(lib, "show_filtered", parent="settings", var_type="bool", default=self.general["show_filtered"], do_print=False, save=False)
params["show_missing"] = check_for_attribute(lib, "show_missing", parent="settings", var_type="bool", default=self.general["show_missing"], do_print=False, save=False)
params["save_missing"] = check_for_attribute(lib, "save_missing", parent="settings", var_type="bool", default=self.general["save_missing"], do_print=False, save=False)
params["released_missing_only"] = check_for_attribute(lib, "released_missing_only", parent="settings", var_type="bool", default=self.general["released_missing_only"], do_print=False, save=False)
params["missing_only_released"] = check_for_attribute(lib, "missing_only_released", parent="settings", var_type="bool", default=self.general["missing_only_released"], do_print=False, save=False)
params["create_asset_folders"] = check_for_attribute(lib, "create_asset_folders", parent="settings", var_type="bool", default=self.general["create_asset_folders"], do_print=False, save=False)
params["mass_genre_update"] = check_for_attribute(lib, "mass_genre_update", test_list=mass_update_options, default_is_none=True, save=False, do_print=lib and "mass_genre_update" in lib)
@ -427,6 +429,7 @@ class Config:
"url": check_for_attribute(lib, "url", parent="radarr", var_type="url", default=self.general["radarr"]["url"], req_default=True, save=False),
"token": check_for_attribute(lib, "token", parent="radarr", default=self.general["radarr"]["token"], req_default=True, save=False),
"add": check_for_attribute(lib, "add", parent="radarr", var_type="bool", default=self.general["radarr"]["add"], save=False),
"add_existing": check_for_attribute(lib, "add_existing", parent="radarr", var_type="bool", default=self.general["radarr"]["add_existing"], save=False),
"root_folder_path": check_for_attribute(lib, "root_folder_path", parent="radarr", default=self.general["radarr"]["root_folder_path"], req_default=True, save=False),
"monitor": check_for_attribute(lib, "monitor", parent="radarr", var_type="bool", default=self.general["radarr"]["monitor"], save=False),
"availability": check_for_attribute(lib, "availability", parent="radarr", test_list=radarr.availability_descriptions, default=self.general["radarr"]["availability"], save=False),
@ -451,6 +454,7 @@ class Config:
"url": check_for_attribute(lib, "url", parent="sonarr", var_type="url", default=self.general["sonarr"]["url"], req_default=True, save=False),
"token": check_for_attribute(lib, "token", parent="sonarr", default=self.general["sonarr"]["token"], req_default=True, save=False),
"add": check_for_attribute(lib, "add", parent="sonarr", var_type="bool", default=self.general["sonarr"]["add"], save=False),
"add_existing": check_for_attribute(lib, "add_existing", parent="sonarr", var_type="bool", default=self.general["sonarr"]["add_existing"], save=False),
"root_folder_path": check_for_attribute(lib, "root_folder_path", parent="sonarr", default=self.general["sonarr"]["root_folder_path"], req_default=True, save=False),
"monitor": check_for_attribute(lib, "monitor", parent="sonarr", test_list=sonarr.monitor_descriptions, default=self.general["sonarr"]["monitor"], save=False),
"quality_profile": check_for_attribute(lib, "quality_profile", parent="sonarr", default=self.general["sonarr"]["quality_profile"], req_default=True, save=False),

View file

@ -85,7 +85,7 @@ class Convert:
if tvdb_id:
ids.append((tvdb_id, "tvdb"))
if tmdb_ids:
ids.extend((tmdb_ids, "tmdb"))
ids.extend([(t, "tmdb") for t in tmdb_ids])
except Failed as e:
logger.error(e)
return ids

View file

@ -1,4 +1,4 @@
import logging, re, secrets, time, webbrowser
import logging, math, re, secrets, time, webbrowser
from modules import util
from modules.util import Failed, TimeoutExpired
from ruamel import yaml
@ -169,12 +169,26 @@ class MyAnimeList:
if total_items < limit or limit <= 0:
limit = total_items
mal_ids = []
for i in range(1, int(((total_items - 1) / 100) + 2)):
if i > 1:
data = self._jiken_request(f"/genre/anime/{genre_id}/{i}")
mal_ids.extend([anime["mal_id"] for anime in data["anime"]])
if len(mal_ids) > limit:
return mal_ids[:limit]
num_of_pages = math.ceil(int(limit) / 100)
current_page = 1
chances = 0
while current_page <= num_of_pages:
if chances > 6:
logger.debug(data)
raise Failed("AniList Error: Connection Failed")
start_num = (current_page - 1) * 100 + 1
util.print_return(f"Parsing Page {current_page}/{num_of_pages} {start_num}-{limit if current_page == num_of_pages else current_page * 100}")
if current_page > 1:
data = self._jiken_request(f"/genre/anime/{genre_id}/{current_page}")
if "anime" in data:
chances = 0
mal_ids.extend([anime["mal_id"] for anime in data["anime"]])
if len(mal_ids) > limit:
return mal_ids[:limit]
current_page += 1
else:
chances += 1
util.print_end()
return mal_ids
def _producer(self, producer_id, limit):

View file

@ -288,7 +288,7 @@ class Plex:
self.show_filtered = params["show_filtered"]
self.show_missing = params["show_missing"]
self.save_missing = params["save_missing"]
self.released_missing_only = params["released_missing_only"]
self.missing_only_released = params["missing_only_released"]
self.create_asset_folders = params["create_asset_folders"]
self.mass_genre_update = params["mass_genre_update"]
self.mass_audience_rating_update = params["mass_audience_rating_update"]

View file

@ -20,6 +20,7 @@ class Radarr:
except ArrException as e:
raise Failed(e)
self.add = params["add"]
self.add_existing = params["add_existing"]
self.root_folder_path = params["root_folder_path"]
self.monitor = params["monitor"]
self.availability = params["availability"]

View file

@ -38,6 +38,7 @@ class Sonarr:
except ArrException as e:
raise Failed(e)
self.add = params["add"]
self.add_existing = params["add_existing"]
self.root_folder_path = params["root_folder_path"]
self.monitor = params["monitor"]
self.quality_profile = params["quality_profile"]

View file

@ -108,7 +108,7 @@ def start(config_path, is_test=False, time_scheduled=None, requested_collections
logger.info(util.centered("| __/| | __/> < | | | | __/ || (_| | | | | | (_| | | | | (_| | (_| | __/ | "))
logger.info(util.centered("|_| |_|\\___/_/\\_\\ |_| |_|\\___|\\__\\__,_| |_| |_|\\__,_|_| |_|\\__,_|\\__, |\\___|_| "))
logger.info(util.centered(" |___/ "))
logger.info(util.centered(" Version: 1.11.3-beta5 "))
logger.info(util.centered(" Version: 1.12.0 "))
if time_scheduled: start_type = f"{time_scheduled} "
elif is_test: start_type = "Test "
elif requested_collections: start_type = "Collections "
@ -474,7 +474,7 @@ def run_collection(config, library, metadata, requested_collections):
util.separator(f"Validating {mapping_name} Attributes", space=False, border=False)
builder = CollectionBuilder(config, library, metadata, mapping_name, collection_attrs)
builder = CollectionBuilder(config, library, metadata, mapping_name, no_missing, collection_attrs)
logger.info("")
util.separator(f"Building {mapping_name} Collection", space=False, border=False)
@ -495,16 +495,14 @@ def run_collection(config, library, metadata, requested_collections):
for filter_key, filter_value in builder.filters:
logger.info(f"Collection Filter {filter_key}: {filter_value}")
builder.find_rating_keys(no_missing)
builder.find_rating_keys()
if len(builder.rating_keys) > 0 and builder.build_collection:
logger.info("")
util.separator(f"Adding to {mapping_name} Collection", space=False, border=False)
logger.info("")
builder.add_to_collection()
if (builder.details["show_missing"] or builder.details["save_missing"]
or (library.Radarr and builder.add_to_radarr) or (library.Sonarr and builder.add_to_sonarr)) \
and (len(builder.missing_movies) > 0 or len(builder.missing_shows) > 0) and not no_missing:
if builder.do_missing and (len(builder.missing_movies) > 0 or len(builder.missing_shows) > 0):
if builder.details["show_missing"] is True:
logger.info("")
util.separator(f"Missing from Library", space=False, border=False)

View file

@ -7,5 +7,4 @@ ruamel.yaml==0.17.10
schedule==1.1.0
retrying==1.3.3
pathvalidate==2.4.1
pillow==8.3.1
python-slugify==5.0.2
pillow==8.3.1