Merge pull request #494 from meisnate12/develop

v1.13.3
pull/544/head v1.13.3
meisnate12 3 years ago committed by GitHub
commit c23ce430e8
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -1 +1 @@
1.13.2 1.13.3

@ -66,7 +66,7 @@ modifier_alias = {".greater": ".gt", ".less": ".lt"}
all_builders = anidb.builders + anilist.builders + flixpatrol.builders + icheckmovies.builders + imdb.builders + \ all_builders = anidb.builders + anilist.builders + flixpatrol.builders + icheckmovies.builders + imdb.builders + \
letterboxd.builders + mal.builders + plex.builders + stevenlu.builders + tautulli.builders + \ letterboxd.builders + mal.builders + plex.builders + stevenlu.builders + tautulli.builders + \
tmdb.builders + trakt.builders + tvdb.builders tmdb.builders + trakt.builders + tvdb.builders
show_only_builders = ["tmdb_network", "tmdb_show", "tmdb_show_details", "tvdb_show", "tvdb_show_details", "collection_level"] show_only_builders = ["tmdb_network", "tmdb_show", "tmdb_show_details", "tvdb_show", "tvdb_show_details", "collection_level", "item_tmdb_season_titles"]
movie_only_builders = [ movie_only_builders = [
"letterboxd_list", "letterboxd_list_details", "icheckmovies_list", "icheckmovies_list_details", "stevenlu_popular", "letterboxd_list", "letterboxd_list_details", "icheckmovies_list", "icheckmovies_list_details", "stevenlu_popular",
"tmdb_collection", "tmdb_collection_details", "tmdb_movie", "tmdb_movie_details", "tmdb_now_playing", "tmdb_collection", "tmdb_collection_details", "tmdb_movie", "tmdb_movie_details", "tmdb_now_playing",
@ -91,7 +91,7 @@ details = ["ignore_ids", "ignore_imdb_ids", "server_preroll", "collection_change
"collection_level", "collection_minimum", "label"] + boolean_details + string_details "collection_level", "collection_minimum", "label"] + boolean_details + string_details
collectionless_details = ["collection_order", "plex_collectionless", "label", "label_sync_mode", "test"] + \ collectionless_details = ["collection_order", "plex_collectionless", "label", "label_sync_mode", "test"] + \
poster_details + background_details + summary_details + string_details poster_details + background_details + summary_details + string_details
item_bool_details = ["item_assets", "revert_overlay", "item_lock_background", "item_lock_poster", "item_lock_title", "item_refresh"] item_bool_details = ["item_tmdb_season_titles", "item_assets", "revert_overlay", "item_lock_background", "item_lock_poster", "item_lock_title", "item_refresh"]
item_details = ["item_label", "item_radarr_tag", "item_sonarr_tag", "item_overlay"] + item_bool_details + list(plex.item_advance_keys.keys()) item_details = ["item_label", "item_radarr_tag", "item_sonarr_tag", "item_overlay"] + item_bool_details + list(plex.item_advance_keys.keys())
none_details = ["label.sync", "item_label.sync"] none_details = ["label.sync", "item_label.sync"]
radarr_details = ["radarr_add", "radarr_add_existing", "radarr_folder", "radarr_monitor", "radarr_search", "radarr_availability", "radarr_quality", "radarr_tag"] radarr_details = ["radarr_add", "radarr_add_existing", "radarr_folder", "radarr_monitor", "radarr_search", "radarr_availability", "radarr_quality", "radarr_tag"]
@ -99,6 +99,11 @@ sonarr_details = [
"sonarr_add", "sonarr_add_existing", "sonarr_folder", "sonarr_monitor", "sonarr_language", "sonarr_series", "sonarr_add", "sonarr_add_existing", "sonarr_folder", "sonarr_monitor", "sonarr_language", "sonarr_series",
"sonarr_quality", "sonarr_season", "sonarr_search", "sonarr_cutoff_search", "sonarr_tag" "sonarr_quality", "sonarr_season", "sonarr_search", "sonarr_cutoff_search", "sonarr_tag"
] ]
parts_collection_valid = [
"plex_search", "trakt_list", "trakt_list_details", "collection_mode", "label", "visible_library", "collection_changes_webhooks"
"visible_home", "visible_shared", "show_missing", "save_missing", "missing_only_released", "server_preroll",
"item_lock_background", "item_lock_poster", "item_lock_title", "item_refresh"
] + summary_details + poster_details + background_details + string_details
all_filters = [ all_filters = [
"actor", "actor.not", "actor", "actor.not",
"audio_language", "audio_language.not", "audio_language", "audio_language.not",
@ -160,10 +165,6 @@ custom_sort_builders = [
"mal_all", "mal_airing", "mal_upcoming", "mal_tv", "mal_movie", "mal_ova", "mal_special", "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_studio" "mal_popular", "mal_favorite", "mal_suggested", "mal_userlist", "mal_season", "mal_genre", "mal_studio"
] ]
parts_collection_valid = [
"plex_search", "trakt_list", "trakt_list_details", "collection_mode", "label", "visible_library",
"visible_home", "visible_shared", "show_missing", "save_missing", "missing_only_released"
] + summary_details + poster_details + background_details + string_details
class CollectionBuilder: class CollectionBuilder:
def __init__(self, config, library, metadata, name, no_missing, data): def __init__(self, config, library, metadata, name, no_missing, data):
@ -213,6 +214,7 @@ class CollectionBuilder:
self.current_year = self.current_time.year self.current_year = self.current_time.year
self.exists = False self.exists = False
self.created = False self.created = False
self.deleted = False
methods = {m.lower(): m for m in self.data} methods = {m.lower(): m for m in self.data}
@ -416,11 +418,19 @@ class CollectionBuilder:
if not match: if not match:
logger.error(f"Collection Error: range schedule attribute {schedule} invalid must be in the MM/DD-MM/DD format i.e. range(12/01-12/25)") logger.error(f"Collection Error: range schedule attribute {schedule} invalid must be in the MM/DD-MM/DD format i.e. range(12/01-12/25)")
continue continue
month_start = int(match.group(1)) def check_day(_m, _d):
day_start = int(match.group(2)) if _m in [1, 3, 5, 7, 8, 10, 12] and _d > 31:
month_end = int(match.group(3)) return _m, 31
day_end = int(match.group(4)) elif _m in [4, 6, 9, 11] and _d > 30:
check = datetime.strptime(f"{self.current_time.month}/{self.current_time.day}", "%m/%d") return _m, 30
elif _m == 2 and _d > 28:
return _m, 28
else:
return _m, _d
month_start, day_start = check_day(int(match.group(1)), int(match.group(2)))
month_end, day_end = check_day(int(match.group(3)), int(match.group(4)))
month_check, day_check = check_day(self.current_time.month, self.current_time.day)
check = datetime.strptime(f"{month_check}/{day_check}", "%m/%d")
start = datetime.strptime(f"{month_start}/{day_start}", "%m/%d") start = datetime.strptime(f"{month_start}/{day_start}", "%m/%d")
end = datetime.strptime(f"{month_end}/{day_end}", "%m/%d") end = datetime.strptime(f"{month_end}/{day_end}", "%m/%d")
self.schedule += f"\nScheduled between {util.pretty_months[month_start]} {util.make_ordinal(day_start)} and {util.pretty_months[month_end]} {util.make_ordinal(day_end)}" self.schedule += f"\nScheduled between {util.pretty_months[month_start]} {util.make_ordinal(day_start)} and {util.pretty_months[month_end]} {util.make_ordinal(day_end)}"
@ -436,6 +446,7 @@ class CollectionBuilder:
try: try:
self.obj = self.library.get_collection(self.name) self.obj = self.library.get_collection(self.name)
self.delete_collection() self.delete_collection()
self.deleted = True
suffix = f" and was deleted" suffix = f" and was deleted"
except Failed: except Failed:
suffix = f" and could not be found to delete" suffix = f" and could not be found to delete"
@ -496,8 +507,10 @@ class CollectionBuilder:
if "collection_level" in methods: if "collection_level" in methods:
logger.debug("") logger.debug("")
logger.debug("Validating Method: collection_level") logger.debug("Validating Method: collection_level")
if self.data[methods["collection_level"]] is None: if self.library.is_movie:
raise Failed(f"Collection Warning: collection_level attribute is blank") raise Failed(f"Collection Error: collection_level attribute only works for show libraries")
elif self.data[methods["collection_level"]] is None:
raise Failed(f"Collection Error: collection_level attribute is blank")
else: else:
logger.debug(f"Value: {self.data[methods['collection_level']]}") logger.debug(f"Value: {self.data[methods['collection_level']]}")
if self.data[methods["collection_level"]].lower() in plex.collection_level_options: if self.data[methods["collection_level"]].lower() in plex.collection_level_options:
@ -1932,9 +1945,13 @@ class CollectionBuilder:
self.library.edit_tags("label", item, add_tags=add_tags, remove_tags=remove_tags, sync_tags=sync_tags) self.library.edit_tags("label", item, add_tags=add_tags, remove_tags=remove_tags, sync_tags=sync_tags)
path = os.path.dirname(str(item.locations[0])) if self.library.is_movie else str(item.locations[0]) path = os.path.dirname(str(item.locations[0])) if self.library.is_movie else str(item.locations[0])
if self.library.Radarr and item.ratingKey in self.library.movie_rating_key_map: if self.library.Radarr and item.ratingKey in self.library.movie_rating_key_map:
tmdb_paths.append((self.library.movie_rating_key_map[item.ratingKey], f"{path.replace(self.library.Radarr.plex_path, self.library.Radarr.radarr_path)}/")) path = path.replace(self.library.Radarr.plex_path, self.library.Radarr.radarr_path)
path = path[:-1] if path.endswith(('/', '\\')) else path
tmdb_paths.append((self.library.movie_rating_key_map[item.ratingKey], path))
if self.library.Sonarr and item.ratingKey in self.library.show_rating_key_map: if self.library.Sonarr and item.ratingKey in self.library.show_rating_key_map:
tvdb_paths.append((self.library.show_rating_key_map[item.ratingKey], f"{path.replace(self.library.Sonarr.plex_path, self.library.Sonarr.sonarr_path)}/")) path = path.replace(self.library.Sonarr.plex_path, self.library.Sonarr.sonarr_path)
path = path[:-1] if path.endswith(('/', '\\')) else path
tvdb_paths.append((self.library.show_rating_key_map[item.ratingKey], path))
advance_edits = {} advance_edits = {}
for method_name, method_data in self.item_details.items(): for method_name, method_data in self.item_details.items():
if method_name in plex.item_advance_keys: if method_name in plex.item_advance_keys:
@ -1943,16 +1960,26 @@ class CollectionBuilder:
advance_edits[key] = options[method_data] advance_edits[key] = options[method_data]
self.library.edit_item(item, item.title, self.collection_level.capitalize(), advance_edits, advanced=True) self.library.edit_item(item, item.title, self.collection_level.capitalize(), advance_edits, advanced=True)
if "item_tmdb_season_titles" in self.item_details and item.ratingKey in self.library.show_rating_key_map:
try:
tmdb_id = self.config.Convert.tvdb_to_tmdb(self.library.show_rating_key_map[item.ratingKey])
names = {str(s.season_number): s.name for s in self.config.TMDb.get_show(tmdb_id).seasons}
for season in self.library.query(item.seasons):
if str(season.index) in names:
self.library.edit_query(season, {"title.locked": 1, "title.value": names[str(season.index)]})
except Failed as e:
logger.error(e)
# Locking should come before refreshing since refreshing can change metadata (i.e. if specified to both lock # Locking should come before refreshing since refreshing can change metadata (i.e. if specified to both lock
# background/poster and also refreshing, assume that the current background/poster should be kept) # background/poster and also refreshing, assume that the current background/poster should be kept)
if "item_lock_background" in self.item_details: if "item_lock_background" in self.item_details:
item.lockArt() self.library.query(item.lockArt)
if "item_lock_poster" in self.item_details: if "item_lock_poster" in self.item_details:
item.lockPoster() self.library.query(item.lockPoster)
if "item_lock_title" in self.item_details: if "item_lock_title" in self.item_details:
item.edit(**{"title.locked": 1}) self.library.edit_query(item, {"title.locked": 1})
if "item_refresh" in self.item_details: if "item_refresh" in self.item_details:
item.refresh() self.library.query(item.refresh)
if self.library.Radarr and tmdb_paths: if self.library.Radarr and tmdb_paths:
if "item_radarr_tag" in self.item_details: if "item_radarr_tag" in self.item_details:
@ -2172,6 +2199,7 @@ class CollectionBuilder:
self.details["collection_changes_webhooks"], self.details["collection_changes_webhooks"],
self.obj, self.obj,
created=self.created, created=self.created,
deleted=self.deleted,
additions=self.notification_additions, additions=self.notification_additions,
removals=self.notification_removals removals=self.notification_removals
) )

@ -100,7 +100,9 @@ class Config:
changes = [] changes = []
def hooks(attr): def hooks(attr):
if attr in temp: if attr in temp:
changes.extend([w for w in util.get_list(temp.pop(attr), split=False) if w not in changes]) items = util.get_list(temp.pop(attr), split=False)
if items:
changes.extend([w for w in items if w not in changes])
hooks("collection_creation") hooks("collection_creation")
hooks("collection_addition") hooks("collection_addition")
hooks("collection_removal") hooks("collection_removal")

@ -58,8 +58,10 @@ class Radarr:
arr_ids = {} arr_ids = {}
for movie in self.api.all_movies(): for movie in self.api.all_movies():
if movie.path: if movie.path:
arr_paths[movie.path] = movie.tmdbId arr_paths[movie.path[:-1] if movie.path.endswith(("/", "\\")) else movie.path] = movie.tmdbId
arr_ids[movie.tmdbId] = movie arr_ids[movie.tmdbId] = movie
logger.debug(arr_paths)
logger.debug(arr_ids)
added = [] added = []
exists = [] exists = []

@ -84,8 +84,10 @@ class Sonarr:
arr_ids = {} arr_ids = {}
for series in self.api.all_series(): for series in self.api.all_series():
if series.path: if series.path:
arr_paths[series.path] = series.tvdbId arr_paths[series.path[:-1] if series.path.endswith(("/", "\\")) else series.path] = series.tvdbId
arr_paths[series.tvdbId] = series arr_paths[series.tvdbId] = series
logger.debug(arr_paths)
logger.debug(arr_ids)
added = [] added = []
exists = [] exists = []

@ -70,7 +70,7 @@ class Webhooks:
json["collection"] = str(collection) json["collection"] = str(collection)
self._request(self.error_webhooks, json) self._request(self.error_webhooks, json)
def collection_hooks(self, webhooks, collection, created=False, additions=None, removals=None): def collection_hooks(self, webhooks, collection, created=False, deleted=False, additions=None, removals=None):
if self.library: if self.library:
thumb = None thumb = None
if collection.thumb and next((f for f in collection.fields if f.name == "thumb"), None): if collection.thumb and next((f for f in collection.fields if f.name == "thumb"), None):
@ -84,6 +84,7 @@ class Webhooks:
"type": "movie" if self.library.is_movie else "show", "type": "movie" if self.library.is_movie else "show",
"collection": collection.title, "collection": collection.title,
"created": created, "created": created,
"deleted": deleted,
"poster": thumb, "poster": thumb,
"background": art "background": art
} }

@ -410,9 +410,13 @@ def library_operations(config, library):
path = os.path.dirname(str(item.locations[0])) if library.is_movie else str(item.locations[0]) path = os.path.dirname(str(item.locations[0])) if library.is_movie else str(item.locations[0])
if library.Radarr and library.radarr_add_all and tmdb_id: if library.Radarr and library.radarr_add_all and tmdb_id:
radarr_adds.append((tmdb_id, f"{path.replace(library.Radarr.plex_path, library.Radarr.radarr_path)}/")) path = path.replace(library.Radarr.plex_path, library.Radarr.radarr_path)
path = path[:-1] if path.endswith(('/', '\\')) else path
radarr_adds.append((tmdb_id, path))
if library.Sonarr and library.sonarr_add_all and tvdb_id: if library.Sonarr and library.sonarr_add_all and tvdb_id:
sonarr_adds.append((tvdb_id, f"{path.replace(library.Sonarr.plex_path, library.Sonarr.sonarr_path)}/")) path = path.replace(library.Sonarr.plex_path, library.Sonarr.sonarr_path)
path = path[:-1] if path.endswith(('/', '\\')) else path
sonarr_adds.append((tvdb_id, path))
tmdb_item = None tmdb_item = None
if library.tmdb_collections or library.mass_genre_update == "tmdb" or library.mass_audience_rating_update == "tmdb" or library.mass_critic_rating_update == "tmdb": if library.tmdb_collections or library.mass_genre_update == "tmdb" or library.mass_audience_rating_update == "tmdb" or library.mass_critic_rating_update == "tmdb":
@ -679,7 +683,7 @@ def run_collection(config, library, metadata, requested_collections):
logger.info(f"Collection Minimum: {builder.minimum} not met for {mapping_name} Collection") logger.info(f"Collection Minimum: {builder.minimum} not met for {mapping_name} Collection")
if builder.details["delete_below_minimum"] and builder.obj: if builder.details["delete_below_minimum"] and builder.obj:
builder.delete_collection() builder.delete_collection()
stats["deleted"] += 1 builder.deleted = True
logger.info("") logger.info("")
logger.info(f"Collection {builder.obj.title} deleted") logger.info(f"Collection {builder.obj.title} deleted")
@ -711,6 +715,9 @@ def run_collection(config, library, metadata, requested_collections):
library.run_sort.append(builder) library.run_sort.append(builder)
# builder.sort_collection() # builder.sort_collection()
if builder.deleted:
stats["deleted"] += 1
if builder.server_preroll is not None: if builder.server_preroll is not None:
library.set_server_preroll(builder.server_preroll) library.set_server_preroll(builder.server_preroll)
logger.info("") logger.info("")

Loading…
Cancel
Save