[61] #738 Expand Summary

This commit is contained in:
meisnate12 2022-05-04 12:27:17 -04:00
parent e66793511f
commit d8d1730fc8
7 changed files with 122 additions and 89 deletions

View file

@ -1 +1 @@
1.16.5-develop60
1.16.5-develop61

View file

@ -27,8 +27,8 @@ Set the attribute to the tag you want to search for. Multiple values are support
```yaml
collections:
Radarr Movies Without Tags:
radarr_taglist: action, drama
Radarr Tag1 and Tag2 Movies:
radarr_taglist: tag1, tag2
```
If no tag is specified then it gets every Movie without a tag.

View file

@ -27,8 +27,8 @@ Set the attribute to the tag you want to search for. Multiple values are support
```yaml
collections:
Sonarr Series Without Tags:
sonarr_taglist: action, drama
Sonarr Tag1 and Tag2 Series:
sonarr_taglist: tag1, tag2
```
If no tag is specified then it gets every Movie without a tag.

View file

@ -2438,45 +2438,44 @@ class CollectionBuilder:
self.created = True
def update_details(self):
updated_details = []
logger.info("")
logger.separator(f"Updating Details of {self.name} {self.Type}", space=False, border=False)
logger.info("")
if self.smart_url and self.smart_url != self.library.smart_filter(self.obj):
self.library.update_smart_collection(self.obj, self.smart_url)
logger.info(f"Detail: Smart Filter updated to {self.smart_url}")
def get_summary(summary_method, summaries):
logger.info(f"Detail: {summary_method} will update {self.Type} Summary")
return summaries[summary_method]
if "summary" in self.summaries: summary = get_summary("summary", self.summaries)
elif "tmdb_description" in self.summaries: summary = get_summary("tmdb_description", self.summaries)
elif "letterboxd_description" in self.summaries: summary = get_summary("letterboxd_description", self.summaries)
elif "tmdb_summary" in self.summaries: summary = get_summary("tmdb_summary", self.summaries)
elif "tvdb_summary" in self.summaries: summary = get_summary("tvdb_summary", self.summaries)
elif "tmdb_biography" in self.summaries: summary = get_summary("tmdb_biography", self.summaries)
elif "tmdb_person" in self.summaries: summary = get_summary("tmdb_person", self.summaries)
elif "tmdb_collection_details" in self.summaries: summary = get_summary("tmdb_collection_details", self.summaries)
elif "trakt_list_details" in self.summaries: summary = get_summary("trakt_list_details", self.summaries)
elif "tmdb_list_details" in self.summaries: summary = get_summary("tmdb_list_details", self.summaries)
elif "letterboxd_list_details" in self.summaries: summary = get_summary("letterboxd_list_details", self.summaries)
elif "icheckmovies_list_details" in self.summaries: summary = get_summary("icheckmovies_list_details", self.summaries)
elif "tmdb_actor_details" in self.summaries: summary = get_summary("tmdb_actor_details", self.summaries)
elif "tmdb_crew_details" in self.summaries: summary = get_summary("tmdb_crew_details", self.summaries)
elif "tmdb_director_details" in self.summaries: summary = get_summary("tmdb_director_details", self.summaries)
elif "tmdb_producer_details" in self.summaries: summary = get_summary("tmdb_producer_details", self.summaries)
elif "tmdb_writer_details" in self.summaries: summary = get_summary("tmdb_writer_details", self.summaries)
elif "tmdb_movie_details" in self.summaries: summary = get_summary("tmdb_movie_details", self.summaries)
elif "tvdb_movie_details" in self.summaries: summary = get_summary("tvdb_movie_details", self.summaries)
elif "tvdb_show_details" in self.summaries: summary = get_summary("tvdb_show_details", self.summaries)
elif "tmdb_show_details" in self.summaries: summary = get_summary("tmdb_show_details", self.summaries)
updated_details.append("Smart Filter")
if "summary" in self.summaries: summary = ("summary", self.summaries["summary"])
elif "tmdb_description" in self.summaries: summary = ("tmdb_description", self.summaries["tmdb_description"])
elif "letterboxd_description" in self.summaries: summary = ("letterboxd_description", self.summaries["letterboxd_description"])
elif "tmdb_summary" in self.summaries: summary = ("tmdb_summary", self.summaries["tmdb_summary"])
elif "tvdb_summary" in self.summaries: summary = ("tvdb_summary", self.summaries["tvdb_summary"])
elif "tmdb_biography" in self.summaries: summary = ("tmdb_biography", self.summaries["tmdb_biography"])
elif "tmdb_person" in self.summaries: summary = ("tmdb_person", self.summaries["tmdb_person"])
elif "tmdb_collection_details" in self.summaries: summary = ("tmdb_collection_details", self.summaries["tmdb_collection_details"])
elif "trakt_list_details" in self.summaries: summary = ("trakt_list_details", self.summaries["trakt_list_details"])
elif "tmdb_list_details" in self.summaries: summary = ("tmdb_list_details", self.summaries["tmdb_list_details"])
elif "letterboxd_list_details" in self.summaries: summary = ("letterboxd_list_details", self.summaries["letterboxd_list_details"])
elif "icheckmovies_list_details" in self.summaries: summary = ("icheckmovies_list_details", self.summaries["icheckmovies_list_details"])
elif "tmdb_actor_details" in self.summaries: summary = ("tmdb_actor_details", self.summaries["tmdb_actor_details"])
elif "tmdb_crew_details" in self.summaries: summary = ("tmdb_crew_details", self.summaries["tmdb_crew_details"])
elif "tmdb_director_details" in self.summaries: summary = ("tmdb_director_details", self.summaries["tmdb_director_details"])
elif "tmdb_producer_details" in self.summaries: summary = ("tmdb_producer_details", self.summaries["tmdb_producer_details"])
elif "tmdb_writer_details" in self.summaries: summary = ("tmdb_writer_details", self.summaries["tmdb_writer_details"])
elif "tmdb_movie_details" in self.summaries: summary = ("tmdb_movie_details", self.summaries["tmdb_movie_details"])
elif "tvdb_movie_details" in self.summaries: summary = ("tvdb_movie_details", self.summaries["tvdb_movie_details"])
elif "tvdb_show_details" in self.summaries: summary = ("tvdb_show_details", self.summaries["tvdb_show_details"])
elif "tmdb_show_details" in self.summaries: summary = ("tmdb_show_details", self.summaries["tmdb_show_details"])
else: summary = None
if self.playlist:
if summary and str(summary) != str(self.obj.summary):
if summary and str(summary[1]) != str(self.obj.summary):
try:
self.obj.edit(summary=str(summary))
logger.info(f"Summary | {summary:<25}")
self.obj.edit(summary=str(summary[1]))
logger.info(f"Summary ({summary[0]}) | {summary[1]:<25}")
logger.info("Details: have been updated")
updated_details.append("Metadata")
except NotFound:
logger.error("Details: Failed to Update Please delete the collection and run again")
logger.info("")
@ -2484,9 +2483,9 @@ class CollectionBuilder:
self.obj.batchEdits()
batch_display = "Collection Metadata Edits"
if summary and str(summary) != str(self.obj.summary):
self.obj.editSummary(summary)
batch_display += f"\nSummary | {summary:<25}"
if summary and str(summary[1]) != str(self.obj.summary):
self.obj.editSummary(summary[1])
batch_display += f"\nSummary ({summary[0]}) | {summary[1]:<25}"
if "sort_title" in self.details and str(self.details["sort_title"]) != str(self.obj.titleSort):
self.obj.editSortTitle(self.details["sort_title"])
@ -2506,21 +2505,29 @@ class CollectionBuilder:
try:
self.obj.saveEdits()
logger.info("Details: have been updated")
updated_details.append("Metadata")
except NotFound:
logger.error("Details: Failed to Update Please delete the collection and run again")
logger.info("")
advance_update = False
if "collection_mode" in self.details:
self.library.collection_mode_query(self.obj, self.details["collection_mode"])
if int(self.obj.collectionMode) not in plex.collection_mode_keys \
or plex.collection_mode_keys[int(self.obj.collectionMode)] != self.details["collection_mode"]:
self.library.collection_mode_query(self.obj, self.details["collection_mode"])
logger.info(f"Collection Mode | {self.details['collection_mode']}")
advance_update = True
if "collection_filtering" in self.details:
self.library.edit_query(self.obj, {"collectionFilterBasedOnUser": 0 if self.details["collection_filtering"] == "admin" else 1}, advanced=True)
advance_update = True
if "collection_order" in self.details:
if int(self.obj.collectionSort) not in plex.collection_order_keys\
if int(self.obj.collectionSort) not in plex.collection_order_keys \
or plex.collection_order_keys[int(self.obj.collectionSort)] != self.details["collection_order"]:
self.library.collection_order_query(self.obj, self.details["collection_order"])
logger.info(f"Collection Order | {self.details['collection_order']}")
advance_update = True
if "visible_library" in self.details or "visible_home" in self.details or "visible_shared" in self.details:
visibility = self.library.collection_visibility(self.obj)
@ -2539,8 +2546,12 @@ class CollectionBuilder:
if visible_library is not None or visible_home is not None or visible_shared is not None:
self.library.collection_visibility_update(self.obj, visibility=visibility, library=visible_library, home=visible_home, shared=visible_shared)
advance_update = True
logger.info("Collection Visibility Updated")
if advance_update and "Metadata" not in updated_details:
updated_details.append("Metadata")
poster_image = None
background_image = None
asset_location = None
@ -2633,12 +2644,15 @@ class CollectionBuilder:
logger.info(f"No background {self.type} detail or asset folder found")
if self.collection_poster or self.collection_background:
self.library.upload_images(self.obj, poster=self.collection_poster, background=self.collection_background)
pu, bu = self.library.upload_images(self.obj, poster=self.collection_poster, background=self.collection_background)
if pu or bu:
updated_details.append("Image")
if self.url_theme:
if self.url_theme: # TODO: cache theme path to not constantly upload
self.library.upload_theme(self.obj, url=self.url_theme)
elif self.file_theme:
self.library.upload_theme(self.obj, filepath=self.file_theme)
return updated_details
def sort_collection(self):
logger.info("")

View file

@ -184,6 +184,8 @@ class Library(ABC):
if background_uploaded:
self.config.Cache.update_image_map(item.ratingKey, f"{self.image_table_name}_backgrounds", item.art, background.compare)
return poster_uploaded, background_uploaded
@abstractmethod
def notify(self, text, collection=None, critical=True):
pass

View file

@ -1,5 +1,5 @@
import os, re
from modules import util
from modules import plex, util
from modules.util import Failed
from plexapi.audio import Artist
from plexapi.video import Show
@ -439,10 +439,13 @@ class Operations:
if self.library.mass_collection_mode:
logger.info("")
logger.separator(f"Unmanaged Mass Collection Mode for {self.library.name} Library", space=False, border=False)
logger.separator(f"Unmanaged Mass Collection Mode to {self.library.mass_collection_mode} for {self.library.name} Library", space=False, border=False)
logger.info("")
for col in unmanaged_collections:
self.library.collection_mode_query(col, self.library.mass_collection_mode)
if int(col.collectionMode) not in plex.collection_mode_keys \
or plex.collection_mode_keys[int(col.collectionMode)] != self.library.mass_collection_mode:
self.library.collection_mode_query(col, self.library.mass_collection_mode)
logger.info(f"{col.title} Collection Mode Updated")
if self.library.metadata_backup:
logger.info("")

View file

@ -396,11 +396,11 @@ def update_libraries(config):
logger.info("")
logger.separator(f"{section} Summary", space=False, border=False)
logger.info("")
logger.info(f"{'Title':^{longest}} | + | = | - | {'Status':^13}")
logger.info(f"{'Title':^{longest}} | + | = | - | Run Time | {'Status'}")
breaker = f"{logger.separating_character * longest}|{logger.separating_character * 5}|{logger.separating_character * 5}|{logger.separating_character * 5}|"
logger.separator(breaker, space=False, border=False, side_space=False, left=True)
for name, data in status.items():
logger.info(f"{name:<{longest}} | {data['added']:^3} | {data['unchanged']:^3} | {data['removed']:^3} | {data['status']}")
logger.info(f"{name:<{longest}} | {data['added']:^3} | {data['unchanged']:^3} | {data['removed']:^3} | {data['run_time']:>8} | {data['status']}")
if data["errors"]:
for error in data["errors"]:
logger.info(error)
@ -467,7 +467,7 @@ def run_collection(config, library, metadata, requested_collections):
else:
collection_log_name, output_str = util.validate_filename(mapping_name)
logger.add_collection_handler(library.mapping_name, collection_log_name)
library.status[mapping_name] = {"status": "", "errors": [], "created": False, "modified": False, "deleted": False, "added": 0, "unchanged": 0, "removed": 0, "radarr": 0, "sonarr": 0}
library.status[mapping_name] = {"status": "Unchanged", "errors": [], "added": 0, "unchanged": 0, "removed": 0, "radarr": 0, "sonarr": 0}
try:
builder = CollectionBuilder(config, metadata, mapping_name, collection_attrs, library=library, extra=output_str)
@ -528,11 +528,14 @@ def run_collection(config, library, metadata, requested_collections):
):
logger.info("")
logger.info(f"Collection Minimum: {builder.minimum} not met for {mapping_name} Collection")
delete_status = f"Minimum {builder.minimum} Not Met"
valid = False
if builder.details["delete_below_minimum"] and builder.obj:
logger.info("")
logger.info(builder.delete())
builder.deleted = True
library.stats["deleted"] += 1
delete_status = f"Deleted; {delete_status}"
library.status[mapping_name]["status"] = delete_status
run_item_details = True
if valid and builder.build_collection and (builder.builders or builder.smart_url or builder.blank_collection):
@ -540,28 +543,29 @@ def run_collection(config, library, metadata, requested_collections):
builder.load_collection()
if builder.created:
library.stats["created"] += 1
library.status[mapping_name]["created"] = True
library.status[mapping_name]["status"] = "Created"
elif items_added > 0 or items_removed > 0:
library.stats["modified"] += 1
library.status[mapping_name]["modified"] = True
library.status[mapping_name]["status"] = "Modified"
except Failed:
logger.stacktrace()
run_item_details = False
logger.info("")
logger.separator("No Collection to Update", space=False, border=False)
else:
builder.update_details()
if builder.deleted:
library.stats["deleted"] += 1
library.status[mapping_name]["deleted"] = True
details_list = builder.update_details()
if details_list:
pre = ""
if library.status[mapping_name]["status"] != "Unchanged":
pre = f"{library.status[mapping_name]['status']} and "
library.status[mapping_name]["status"] = f"{pre}Updated {', '.join(details_list)}"
if builder.server_preroll is not None:
library.set_server_preroll(builder.server_preroll)
logger.info("")
logger.info(f"Plex Server Movie pre-roll video updated to {builder.server_preroll}")
if (builder.item_details or builder.custom_sort) and run_item_details and builder.builders:
if valid and run_item_details and builder.builders and (builder.item_details or builder.custom_sort):
try:
builder.load_collection_items()
except Failed:
@ -578,17 +582,13 @@ def run_collection(config, library, metadata, requested_collections):
if builder.run_again and (len(builder.run_again_movies) > 0 or len(builder.run_again_shows) > 0):
library.run_again.append(builder)
if library.status[mapping_name]["created"]:
library.status[mapping_name]["status"] = "Created"
elif library.status[mapping_name]["deleted"]:
library.status[mapping_name]["status"] = "Deleted"
elif library.status[mapping_name]["modified"]:
library.status[mapping_name]["status"] = "Modified"
else:
library.status[mapping_name]["status"] = "Unchanged"
except NotScheduled as e:
logger.info(e)
library.status[mapping_name]["status"] = "Not Scheduled"
if str(e).endswith("and was deleted"):
library.stats["deleted"] += 1
library.status[mapping_name]["status"] = "Deleted Not Scheduled"
else:
library.status[mapping_name]["status"] = "Not Scheduled"
except Failed as e:
library.notify(e, collection=mapping_name)
logger.stacktrace()
@ -601,8 +601,10 @@ def run_collection(config, library, metadata, requested_collections):
logger.error(f"Unknown Error: {e}")
library.status[mapping_name]["status"] = "Unknown Error"
library.status[mapping_name]["errors"].append(e)
collection_run_time = str(datetime.now() - collection_start).split('.')[0]
library.status[mapping_name]["run_time"] = collection_run_time
logger.info("")
logger.separator(f"Finished {mapping_name} Collection\nCollection Run Time: {str(datetime.now() - collection_start).split('.')[0]}")
logger.separator(f"Finished {mapping_name} Collection\nCollection Run Time: {collection_run_time}")
logger.remove_collection_handler(library.mapping_name, collection_log_name)
def run_playlists(config):
@ -634,7 +636,7 @@ def run_playlists(config):
else:
playlist_log_name, output_str = util.validate_filename(mapping_name)
logger.add_playlist_handler(playlist_log_name)
status[mapping_name] = {"status": "", "errors": [], "created": False, "modified": False, "deleted": False, "added": 0, "unchanged": 0, "removed": 0, "radarr": 0, "sonarr": 0}
status[mapping_name] = {"status": "Unchanged", "errors": [], "added": 0, "unchanged": 0, "removed": 0, "radarr": 0, "sonarr": 0}
server_name = None
library_names = None
try:
@ -677,7 +679,7 @@ def run_playlists(config):
for filter_key, filter_value in builder.tmdb_filters:
logger.info(f"Playlist Filter {filter_key}: {filter_value}")
if len(builder.added_items) >= builder.minimum:
if len(builder.added_items) > 0 and len(builder.added_items) + builder.beginning_count >= builder.minimum:
items_added, items_unchanged = builder.add_to_collection()
stats["added"] += items_added
status[mapping_name]["added"] += items_added
@ -691,11 +693,14 @@ def run_playlists(config):
elif len(builder.added_items) < builder.minimum:
logger.info("")
logger.info(f"Playlist Minimum: {builder.minimum} not met for {mapping_name} Playlist")
delete_status = f"Minimum {builder.minimum} Not Met"
valid = False
if builder.details["delete_below_minimum"] and builder.obj:
logger.info("")
logger.info(builder.delete())
builder.deleted = True
stats["deleted"] += 1
delete_status = f"Deleted; {delete_status}"
status[mapping_name]["status"] = delete_status
if builder.do_missing and (len(builder.missing_movies) > 0 or len(builder.missing_shows) > 0):
radarr_add, sonarr_add = builder.run_missing()
@ -705,25 +710,27 @@ def run_playlists(config):
status[mapping_name]["sonarr"] += sonarr_add
run_item_details = True
try:
builder.load_collection()
if builder.created:
stats["created"] += 1
status[mapping_name]["created"] = True
elif items_added > 0 or items_removed > 0:
stats["modified"] += 1
status[mapping_name]["modified"] = True
except Failed:
logger.stacktrace()
run_item_details = False
logger.info("")
logger.separator("No Playlist to Update", space=False, border=False)
else:
builder.update_details()
if builder.deleted:
stats["deleted"] += 1
status[mapping_name]["deleted"] = True
if valid and builder.builders:
try:
builder.load_collection()
if builder.created:
stats["created"] += 1
status[mapping_name]["status"] = "Created"
elif items_added > 0 or items_removed > 0:
stats["modified"] += 1
status[mapping_name]["status"] = "Modified"
except Failed:
logger.stacktrace()
run_item_details = False
logger.info("")
logger.separator("No Playlist to Update", space=False, border=False)
else:
details_list = builder.update_details()
if details_list:
pre = ""
if status[mapping_name]["status"] != "Unchanged":
pre = f"{status[mapping_name]['status']} and "
status[mapping_name]["status"] = f"{pre}Updated {', '.join(details_list)}"
if valid and run_item_details and builder.builders and (builder.item_details or builder.custom_sort):
try:
@ -744,7 +751,11 @@ def run_playlists(config):
except NotScheduled as e:
logger.info(e)
status[mapping_name]["status"] = "Not Scheduled"
if str(e).endswith("and was deleted"):
stats["deleted"] += 1
status[mapping_name]["status"] = "Deleted Not Scheduled"
else:
status[mapping_name]["status"] = "Not Scheduled"
except Failed as e:
config.notify(e, server=server_name, library=library_names, playlist=mapping_name)
logger.stacktrace()
@ -758,7 +769,10 @@ def run_playlists(config):
status[mapping_name]["status"] = "Unknown Error"
status[mapping_name]["errors"].append(e)
logger.info("")
logger.separator(f"Finished {mapping_name} Playlist\nPlaylist Run Time: {str(datetime.now() - playlist_start).split('.')[0]}")
playlist_run_time = str(datetime.now() - playlist_start).split('.')[0]
status[mapping_name]["run_time"] = playlist_run_time
logger.info("")
logger.separator(f"Finished {mapping_name} Playlist\nPlaylist Run Time: {playlist_run_time}")
logger.remove_playlist_handler(playlist_log_name)
return status, stats