mirror of
https://github.com/meisnate12/Plex-Meta-Manager
synced 2024-11-22 12:33:10 +00:00
[10] builder_level
This commit is contained in:
parent
ff14c2d80f
commit
f44589e853
14 changed files with 84 additions and 76 deletions
2
VERSION
2
VERSION
|
@ -1 +1 @@
|
|||
1.17.2-develop9
|
||||
1.17.2-develop10
|
||||
|
|
|
@ -112,7 +112,7 @@ You can also find episodes using `imdb_list` like so.
|
|||
collections:
|
||||
The Simpsons Top 100 Episodes:
|
||||
collection_order: custom
|
||||
collection_level: episode
|
||||
builder_level: episode
|
||||
sync_mode: sync
|
||||
imdb_list:
|
||||
url: https://www.imdb.com/search/title/?series=tt0096697&sort=user_rating,desc
|
||||
|
|
|
@ -27,12 +27,12 @@ collections:
|
|||
|
||||
## Plex Pilots
|
||||
|
||||
Gets the first episode of every show in your library. This Only works with `collection_level: episode`
|
||||
Gets the first episode of every show in your library. This only works with `builder_level: episode`
|
||||
|
||||
```yaml
|
||||
collection:
|
||||
Pilots:
|
||||
collection_level: episode
|
||||
builder_level: episode
|
||||
plex_pilots: true
|
||||
```
|
||||
|
||||
|
@ -77,7 +77,7 @@ like Plex's [Advanced Filters](https://support.plex.tv/articles/201273953-collec
|
|||
|
||||
Inside the base attribute you can use any search below or nest more `any` or `all`. You can have as many nested `any` or `all` next to each other as you want. If using multiple `any` or `all` you will have to do so in the form of a list.
|
||||
|
||||
**Note: To search by `season`, `episode`, `album`, or `track` you must use the `collection_level` [Detail](../details/metadata) to change the type of items the collection holds.**
|
||||
**Note: To search by `season`, `episode`, `album`, or `track` you must use the `builder_level` [Detail](../details/metadata) to change the type of items the collection holds.**
|
||||
|
||||
There are a couple other attributes you can have at the top level only along with the base attribute are:
|
||||
|
||||
|
@ -383,7 +383,7 @@ Here's an example of an episode collection using `plex_search`.
|
|||
collections:
|
||||
Top 100 Simpsons Episodes:
|
||||
collection_order: custom
|
||||
collection_level: episode
|
||||
builder_level: episode
|
||||
plex_search:
|
||||
type: episodes
|
||||
sort_by: audience_rating.desc
|
||||
|
|
|
@ -46,7 +46,7 @@ like Plex's [Advanced Filters](https://support.plex.tv/articles/201273953-collec
|
|||
|
||||
Inside the base attribute you can use any filter below or nest more `any` or `all`. You can have as many nested `any` or `all` next to each other as you want. If using multiple `any` or `all` you will have to do so in the form of a list.
|
||||
|
||||
**Note: To search by `season`, `episode`, `album`, or `track` you must use the `collection_level` [Detail](../details/metadata) to change the type of items the collection holds.**
|
||||
**Note: To search by `season`, `episode`, `album`, or `track` you must use the `builder_level` [Detail](../details/metadata) to change the type of items the collection holds.**
|
||||
|
||||
There are a couple other attributes you can have at the top level only along with the base attribute are:
|
||||
|
||||
|
|
|
@ -17,7 +17,7 @@ Only `tmdb_person` works with Playlists.
|
|||
| `collection_mode` | **Description:** Changes the Collection Mode<br>**Normal Collections Only**<br>**Values:**<table class="clearTable"><tr><td>`default`</td><td>Library default</td></tr><tr><td>`hide`</td><td>Hide Collection</td></tr><tr><td>`hide_items`</td><td>Hide Items in this Collection</td></tr><tr><td>`show_items`</td><td>Show this Collection and its Items</td></tr></table> |
|
||||
| `collection_order` | **Description:** Changes the Collection Order<br>**Normal Collections Only**<br>When using `custom` you can only have a single builder in the collection.<br>**Values:**<table class="clearTable"><tr><td>`release`</td><td>Order Collection by Release Dates</td></tr><tr><td>`alpha`</td><td>Order Collection Alphabetically</td></tr><tr><td>`custom`</td><td>Order Collection Via the Builder Order</td></tr><tr><td>[Any `plex_search` Sort Option](../builders/plex.md#sort-options)</td><td>Order Collection by any `plex_search` Sort Option</td></tr></table> |
|
||||
| `collection_filtering` | **Description:** Changes the Collection Filtering<br>**Smart Collections Only**<br>**Values:**<table class="clearTable"><tr><td>`admin`</td><td>Always the server admin user</td></tr><tr><td>`user`</td><td>User currently viewing the content</td></tr></table> |
|
||||
| `collection_level` | **Description:** Make season, episode, album or track collections from `plex_all`, `plex_search`, `trakt_list`, or `imdb_list` Builders and Filters<br>**Values:**<table class="clearTable"><tr><td>`season`</td><td>Collection contains seasons</td></tr><tr><td>`episode`</td><td>Collection contains episodes</td></tr><tr><td>`album`</td><td>Collection contains albums</td></tr><tr><td>`track`</td><td>Collection contains tracks</td></tr></table> |
|
||||
| `builder_level` | **Description:** Make season, episode, album or track collections/overlays from `plex_all`, `plex_search`, `trakt_list`, or `imdb_list` Builders and Filters<br>**Values:**<table class="clearTable"><tr><td>`season`</td><td>Collection contains seasons</td></tr><tr><td>`episode`</td><td>Collection contains episodes</td></tr><tr><td>`album`</td><td>Collection contains albums</td></tr><tr><td>`track`</td><td>Collection contains tracks</td></tr></table> |
|
||||
| `visible_library` | **Description:** Changes collection visible on Library (Only works with Plex Pass)<br>**Values:**<table class="clearTable"><tr><td>`true`</td><td>Visible</td></tr><tr><td>`false`</td><td>Not Visible</td></tr><tr><td>[Any `schedule` Option](schedule)</td><td>Visible When Scheduled</td></tr></table> |
|
||||
| `visible_home` | **Description:** Changes collection visible on Home (Only works with Plex Pass)<br>**Values:**<table class="clearTable"><tr><td>`true`</td><td>Visible</td></tr><tr><td>`false`</td><td>Not Visible</td></tr><tr><td>[Any `schedule` Option](schedule)</td><td>Visible When Scheduled</td></tr></table> |
|
||||
| `visible_shared` | **Description:** Changes collection visible on Shared Users' Home (Only works with Plex Pass)<br>**Values:**<table class="clearTable"><tr><td>`true`</td><td>Visible</td></tr><tr><td>`false`</td><td>Not Visible</td></tr><tr><td>[Any `schedule` Option](schedule)</td><td>Visible When Scheduled</td></tr></table> |
|
||||
|
|
|
@ -1614,7 +1614,7 @@ default_template:
|
|||
```yaml
|
||||
templates:
|
||||
style collection:
|
||||
collection_level: album
|
||||
builder_level: album
|
||||
smart_filter:
|
||||
limit: 10
|
||||
sort_by: plays.desc
|
||||
|
|
|
@ -133,7 +133,7 @@ overlays:
|
|||
blur:
|
||||
overlay:
|
||||
name: blur(50)
|
||||
collection_level: episode
|
||||
builder_level: episode
|
||||
plex_search:
|
||||
all:
|
||||
resolution: 4K
|
||||
|
@ -177,12 +177,12 @@ The final text can be formatted using the `text_format` attribute and the format
|
|||
|
||||
The available options are:
|
||||
|
||||
| Attribute | Requirements | Format Variables |
|
||||
| Attribute | Notes | Format Variables |
|
||||
|:---------------------------|:-------------------------------------|:-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
|
||||
| text(audience_rating) | Doesnt work with Seasons | `<<value>>` -> ratings (`8.7`, `9.0`)<br>`<<value%>>` -> rating out of 100 (`87`, `90`)<br>`<<value#>>` -> rating removing `.0` as needed (`8.7`, `9`) |
|
||||
| text(critic_rating) | Doesnt work with Seasons | `<<value>>` -> ratings (`8.7`, `9.0`)<br>`<<value%>>` -> rating out of 100 (`87`, `90`)<br>`<<value#>>` -> rating removing `.0` as needed (`8.7`, `9`) |
|
||||
| text(user_rating) | | `<<value>>` -> ratings (`8.7`, `9.0`)<br>`<<value%>>` -> rating out of 100 (`87`, `90`)<br>`<<value#>>` -> rating removing `.0` as needed (`8.7`, `9`) |
|
||||
| text(title) | ✅ | `<<value>>` -> Title of the Item |
|
||||
| text(title) | | `<<value>>` -> Title of the Item |
|
||||
| text(show_title) | Doesnt work with Movies and Shows | `<<value>>` -> Title of the Item's Show |
|
||||
| text(season_title) | Only works with Episodes | `<<value>>` -> Title of the Item's Season |
|
||||
| text(original_title) | Only works with Movies and Shows | `<<value>>` -> Original Title of the Item |
|
||||
|
|
|
@ -18,7 +18,7 @@ all_builders = anidb.builders + anilist.builders + flixpatrol.builders + icheckm
|
|||
tmdb.builders + trakt.builders + tvdb.builders + mdblist.builders + radarr.builders + sonarr.builders
|
||||
show_only_builders = [
|
||||
"tmdb_network", "tmdb_show", "tmdb_show_details", "tvdb_show", "tvdb_show_details", "tmdb_airing_today",
|
||||
"tmdb_on_the_air", "collection_level", "item_tmdb_season_titles", "sonarr_all", "sonarr_taglist"
|
||||
"tmdb_on_the_air", "builder_level", "item_tmdb_season_titles", "sonarr_all", "sonarr_taglist"
|
||||
]
|
||||
movie_only_builders = [
|
||||
"letterboxd_list", "letterboxd_list_details", "icheckmovies_list", "icheckmovies_list_details", "stevenlu_popular",
|
||||
|
@ -40,7 +40,7 @@ scheduled_boolean = ["visible_library", "visible_home", "visible_shared"]
|
|||
string_details = ["sort_title", "content_rating", "name_mapping"]
|
||||
ignored_details = [
|
||||
"smart_filter", "smart_label", "smart_url", "run_again", "schedule", "sync_mode", "template", "test", "suppress_overlays",
|
||||
"delete_not_scheduled", "tmdb_person", "build_collection", "collection_order", "collection_level", "overlay",
|
||||
"delete_not_scheduled", "tmdb_person", "build_collection", "collection_order", "builder_level", "overlay",
|
||||
"validate_builders", "libraries", "sync_to_users", "collection_name", "playlist_name", "name", "blank_collection",
|
||||
"allowed_library_types", "delete_playlist", "ignore_blank_results"
|
||||
]
|
||||
|
@ -137,7 +137,7 @@ number_attributes = plex.number_attributes + ["channels", "height", "width"]
|
|||
tag_attributes = plex.tag_attributes + ["audio_codec", "audio_profile", "video_codec", "video_profile"]
|
||||
float_attributes = plex.float_attributes + ["aspect"]
|
||||
boolean_attributes = plex.boolean_attributes + boolean_filters
|
||||
smart_invalid = ["collection_order", "collection_level"]
|
||||
smart_invalid = ["collection_order", "builder_level"]
|
||||
smart_only = ["collection_filtering"]
|
||||
smart_url_invalid = ["filters", "run_again", "sync_mode", "show_filtered", "show_missing", "save_report", "smart_label"] + radarr_details + sonarr_details
|
||||
custom_sort_builders = [
|
||||
|
@ -245,28 +245,36 @@ class CollectionBuilder:
|
|||
if not found_type:
|
||||
raise NotScheduled(f"Skipped because allowed_library_types {self.data[methods['allowed_library_types']]} doesn't match the library type: {self.library.Plex.type}")
|
||||
|
||||
if self.playlist: self.collection_level = "item"
|
||||
elif self.library.is_show: self.collection_level = "show"
|
||||
elif self.library.is_music: self.collection_level = "artist"
|
||||
else: self.collection_level = "movie"
|
||||
if "collection_level" in methods and not self.library.is_movie and not self.playlist:
|
||||
if self.playlist: self.builder_level = "item"
|
||||
elif self.library.is_show: self.builder_level = "show"
|
||||
elif self.library.is_music: self.builder_level = "artist"
|
||||
else: self.builder_level = "movie"
|
||||
level = None
|
||||
for level_attr in ["builder_level", "collection_level", "overlay_level"]:
|
||||
if level_attr in methods:
|
||||
level = self.data[methods[level_attr]]
|
||||
if level_attr != "builder_level":
|
||||
logger.warning(f"Collection Warning: {level_attr} attribute will run as builder_level")
|
||||
break
|
||||
|
||||
if level and not self.library.is_movie and not self.playlist:
|
||||
logger.debug("")
|
||||
logger.debug("Validating Method: collection_level")
|
||||
level = self.data[methods["collection_level"]]
|
||||
logger.debug("Validating Method: builder_level")
|
||||
level = self.data[methods["builder_level"]]
|
||||
if level is None:
|
||||
logger.error(f"{self.Type} Error: collection_level attribute is blank")
|
||||
logger.error(f"{self.Type} Error: builder_level attribute is blank")
|
||||
else:
|
||||
logger.debug(f"Value: {level}")
|
||||
level = level.lower()
|
||||
if (self.library.is_show and level in plex.collection_level_show_options) or (self.library.is_music and level in plex.collection_level_music_options):
|
||||
self.collection_level = level
|
||||
if (self.library.is_show and level in plex.builder_level_show_options) or (self.library.is_music and level in plex.builder_level_music_options):
|
||||
self.builder_level = level
|
||||
elif (self.library.is_show and level != "show") or (self.library.is_music and level != "artist"):
|
||||
if self.library.is_show:
|
||||
options = "\n\tseason (Collection at the Season Level)\n\tepisode (Collection at the Episode Level)"
|
||||
else:
|
||||
options = "\n\talbum (Collection at the Album Level)\n\ttrack (Collection at the Track Level)"
|
||||
raise Failed(f"{self.Type} Error: {self.data[methods['collection_level']]} collection_level invalid{options}")
|
||||
self.parts_collection = self.collection_level in plex.collection_level_options
|
||||
raise Failed(f"{self.Type} Error: {self.data[methods['builder_level']]} builder_level invalid{options}")
|
||||
self.parts_collection = self.builder_level in plex.builder_level_options
|
||||
|
||||
if self.overlay:
|
||||
if "overlay" in methods:
|
||||
|
@ -283,7 +291,7 @@ class CollectionBuilder:
|
|||
suppress = util.get_list(data[methods["suppress_overlays"]])
|
||||
else:
|
||||
logger.error(f"Overlay Error: suppress_overlays attribute is blank")
|
||||
self.overlay = Overlay(config, library, str(self.mapping_name), overlay_data, suppress, self.collection_level)
|
||||
self.overlay = Overlay(config, library, str(self.mapping_name), overlay_data, suppress, self.builder_level)
|
||||
|
||||
self.sync_to_users = None
|
||||
self.valid_users = []
|
||||
|
@ -581,7 +589,7 @@ class CollectionBuilder:
|
|||
raise Failed(f"{self.Type} Error: smart_filter is not compatible with smart_label")
|
||||
|
||||
if self.parts_collection and "smart_url" in methods:
|
||||
raise Failed(f"{self.Type} Error: smart_url is not compatible with collection_level: {self.collection_level}")
|
||||
raise Failed(f"{self.Type} Error: smart_url is not compatible with builder_level: {self.builder_level}")
|
||||
|
||||
self.smart = self.smart_url or self.smart_label_collection
|
||||
|
||||
|
@ -650,14 +658,14 @@ class CollectionBuilder:
|
|||
raise Failed(f"{self.Type} Error: {method_final} plex search only allowed for show libraries")
|
||||
elif self.library.is_music and method_name not in music_attributes:
|
||||
raise Failed(f"{self.Type} Error: {method_final} attribute not allowed for music libraries")
|
||||
elif self.library.is_music and method_name in album_details and self.collection_level != "album":
|
||||
elif self.library.is_music and method_name in album_details and self.builder_level != "album":
|
||||
raise Failed(f"{self.Type} Error: {method_final} attribute only allowed for album collections")
|
||||
elif not self.library.is_music and method_name in music_only_builders:
|
||||
raise Failed(f"{self.Type} Error: {method_final} attribute only allowed for music libraries")
|
||||
elif not self.playlist and self.collection_level != "episode" and method_name in episode_parts_only:
|
||||
elif not self.playlist and self.builder_level != "episode" and method_name in episode_parts_only:
|
||||
raise Failed(f"{self.Type} Error: {method_final} attribute only allowed with Collection Level: episode")
|
||||
elif self.parts_collection and method_name not in parts_collection_valid:
|
||||
raise Failed(f"{self.Type} Error: {method_final} attribute not allowed with Collection Level: {self.collection_level.capitalize()}")
|
||||
raise Failed(f"{self.Type} Error: {method_final} attribute not allowed with Collection Level: {self.builder_level.capitalize()}")
|
||||
elif self.smart and method_name in smart_invalid:
|
||||
raise Failed(f"{self.Type} Error: {method_final} attribute only allowed with normal collections")
|
||||
elif not self.smart and method_name in smart_only:
|
||||
|
@ -1258,7 +1266,7 @@ class CollectionBuilder:
|
|||
|
||||
def _plex(self, method_name, method_data):
|
||||
if method_name in ["plex_all", "plex_pilots"]:
|
||||
self.builders.append((method_name, self.collection_level))
|
||||
self.builders.append((method_name, self.builder_level))
|
||||
elif method_name in ["plex_search", "plex_collectionless"]:
|
||||
for dict_data in util.parse(self.Type, method_name, method_data, datatype="listdict"):
|
||||
dict_methods = {dm.lower(): dm for dm in dict_data}
|
||||
|
@ -1455,16 +1463,16 @@ class CollectionBuilder:
|
|||
message = None
|
||||
if filter_final not in all_filters:
|
||||
message = f"{self.Type} Error: {filter_final} is not a valid filter attribute"
|
||||
elif self.collection_level in filters and filter_attr not in filters[self.collection_level]:
|
||||
message = f"{self.Type} Error: {filter_final} is not a valid {self.collection_level} filter attribute"
|
||||
elif self.builder_level in filters and filter_attr not in filters[self.builder_level]:
|
||||
message = f"{self.Type} Error: {filter_final} is not a valid {self.builder_level} filter attribute"
|
||||
elif filter_final is None:
|
||||
message = f"{self.Type} Error: {filter_final} filter attribute is blank"
|
||||
else:
|
||||
final_data = self.validate_attribute(filter_attr, modifier, f"{filter_final} filter", filter_data, validate)
|
||||
if filter_attr in tmdb_filters:
|
||||
self.tmdb_filters.append((filter_final, final_data))
|
||||
elif self.collection_level in ["show", "season", "artist", "album"] and filter_attr in sub_filters:
|
||||
self.filters.append(("episodes" if self.collection_level in ["show", "season"] else "tracks", {filter_final: final_data, "percentage": self.default_percent}))
|
||||
elif self.builder_level in ["show", "season", "artist", "album"] and filter_attr in sub_filters:
|
||||
self.filters.append(("episodes" if self.builder_level in ["show", "season"] else "tracks", {filter_final: final_data, "percentage": self.default_percent}))
|
||||
else:
|
||||
self.filters.append((filter_final, final_data))
|
||||
if message:
|
||||
|
@ -1547,10 +1555,10 @@ class CollectionBuilder:
|
|||
found = True
|
||||
rating_keys = pl_library.imdb_map[input_id]
|
||||
break
|
||||
if not found and (self.collection_level == "episode" or self.playlist or self.do_missing):
|
||||
if not found and (self.builder_level == "episode" or self.playlist or self.do_missing):
|
||||
try:
|
||||
_id, tmdb_type = self.config.Convert.imdb_to_tmdb(input_id, fail=True)
|
||||
if tmdb_type == "episode" and (self.collection_level == "episode" or self.playlist):
|
||||
if tmdb_type == "episode" and (self.builder_level == "episode" or self.playlist):
|
||||
try:
|
||||
tmdb_id, season_num, episode_num = _id.split("_")
|
||||
tvdb_id = self.config.Convert.tmdb_to_tvdb(tmdb_id, fail=True)
|
||||
|
@ -1619,7 +1627,7 @@ class CollectionBuilder:
|
|||
break
|
||||
if not found and tvdb_id not in self.missing_shows:
|
||||
self.missing_shows.append(tvdb_id)
|
||||
elif id_type == "tvdb_season" and (self.collection_level == "season" or self.playlist):
|
||||
elif id_type == "tvdb_season" and (self.builder_level == "season" or self.playlist):
|
||||
tvdb_id, season_num = input_id.split("_")
|
||||
tvdb_id = int(tvdb_id)
|
||||
found = False
|
||||
|
@ -1638,7 +1646,7 @@ class CollectionBuilder:
|
|||
break
|
||||
if not found and tvdb_id not in self.missing_shows:
|
||||
self.missing_shows.append(tvdb_id)
|
||||
elif id_type == "tvdb_episode" and (self.collection_level == "episode" or self.playlist):
|
||||
elif id_type == "tvdb_episode" and (self.builder_level == "episode" or self.playlist):
|
||||
tvdb_id, season_num, episode_num = input_id.split("_")
|
||||
tvdb_id = int(tvdb_id)
|
||||
found = False
|
||||
|
@ -1712,7 +1720,7 @@ class CollectionBuilder:
|
|||
if "any" in filter_alias and "all" in filter_alias:
|
||||
raise Failed(f"{self.Type} Error: Cannot have more then one base")
|
||||
|
||||
if self.collection_level == "item":
|
||||
if self.builder_level == "item":
|
||||
if self.library.is_show:
|
||||
sort_type = "show"
|
||||
elif self.library.is_music:
|
||||
|
@ -1720,7 +1728,7 @@ class CollectionBuilder:
|
|||
else:
|
||||
sort_type = "movie"
|
||||
else:
|
||||
sort_type = self.collection_level
|
||||
sort_type = self.builder_level
|
||||
|
||||
ms = method.split("_")
|
||||
filter_details = f"{ms[0].capitalize()} {sort_type.capitalize()} {ms[1].capitalize()}\n"
|
||||
|
@ -2077,7 +2085,7 @@ class CollectionBuilder:
|
|||
self.library.add_additions(self.name, [(i.title, self.library.get_id_from_maps(i.ratingKey)) for i in items_added], self.library.is_movie)
|
||||
logger.exorcise()
|
||||
logger.info("")
|
||||
logger.info(f"{total} {self.collection_level.capitalize()}{'s' if total > 1 else ''} Processed")
|
||||
logger.info(f"{total} {self.builder_level.capitalize()}{'s' if total > 1 else ''} Processed")
|
||||
return amount_added, amount_unchanged
|
||||
|
||||
def sync_collection(self):
|
||||
|
@ -2105,7 +2113,7 @@ class CollectionBuilder:
|
|||
if self.details["save_report"] is True and items_removed:
|
||||
self.library.add_removed(self.name, [(i.title, self.library.get_id_from_maps(i.ratingKey)) for i in items_removed], self.library.is_movie)
|
||||
logger.info("")
|
||||
logger.info(f"{amount_removed} {self.collection_level.capitalize()}{'s' if amount_removed == 1 else ''} Removed")
|
||||
logger.info(f"{amount_removed} {self.builder_level.capitalize()}{'s' if amount_removed == 1 else ''} Removed")
|
||||
return amount_removed
|
||||
|
||||
def check_tmdb_filter(self, item_id, is_movie, item=None, check_released=False):
|
||||
|
@ -2322,7 +2330,7 @@ class CollectionBuilder:
|
|||
|
||||
if "non_item_remove_label" in self.item_details:
|
||||
rk_compare = [item.ratingKey for item in self.items]
|
||||
for non_item in self.library.search(label=self.item_details["non_item_remove_label"], libtype=self.collection_level):
|
||||
for non_item in self.library.search(label=self.item_details["non_item_remove_label"], libtype=self.builder_level):
|
||||
if non_item.ratingKey not in rk_compare:
|
||||
self.library.edit_tags("label", non_item, remove_tags=self.item_details["non_item_remove_label"])
|
||||
|
||||
|
@ -2578,9 +2586,9 @@ class CollectionBuilder:
|
|||
items = self.added_items
|
||||
else:
|
||||
plex_search = {"sort_by": self.custom_sort}
|
||||
if self.collection_level in ["season", "episode"]:
|
||||
plex_search["type"] = f"{self.collection_level}s"
|
||||
plex_search["any"] = {f"{self.collection_level}_collection": self.name}
|
||||
if self.builder_level in ["season", "episode"]:
|
||||
plex_search["type"] = f"{self.builder_level}s"
|
||||
plex_search["any"] = {f"{self.builder_level}_collection": self.name}
|
||||
else:
|
||||
plex_search["any"] = {"collection": self.name}
|
||||
search_data = self.build_filter("plex_search", plex_search)
|
||||
|
@ -2712,7 +2720,7 @@ class CollectionBuilder:
|
|||
add_id = None
|
||||
self.notification_additions.append(util.item_set(current, add_id))
|
||||
self.send_notifications()
|
||||
logger.info(f"{len(rating_keys)} {self.collection_level.capitalize()}{'s' if len(rating_keys) > 1 else ''} Processed")
|
||||
logger.info(f"{len(rating_keys)} {self.builder_level.capitalize()}{'s' if len(rating_keys) > 1 else ''} Processed")
|
||||
|
||||
if len(self.run_again_movies) > 0:
|
||||
logger.info("")
|
||||
|
|
|
@ -229,7 +229,7 @@ class Library(ABC):
|
|||
pass
|
||||
|
||||
@abstractmethod
|
||||
def get_all(self, collection_level=None, load=False):
|
||||
def get_all(self, builder_level=None, load=False):
|
||||
pass
|
||||
|
||||
def add_additions(self, collection, items, is_movie):
|
||||
|
|
|
@ -495,7 +495,7 @@ class MetadataFile(DataFile):
|
|||
final_var = auto_type if auto_type.startswith("album") else f"artist_{auto_type}"
|
||||
default_template = {"smart_filter": {"limit": 50, "sort_by": "plays.desc", "any": {final_var: f"<<value>>"}}}
|
||||
if auto_type.startswith("album"):
|
||||
default_template["collection_level"] = "album"
|
||||
default_template["builder_level"] = "album"
|
||||
default_title_format = f"Most Played <<key_name>> {'Albums' if auto_type.startswith('album') else '<<library_type>>'}s"
|
||||
elif auto_type == "resolution":
|
||||
default_template = {"smart_filter": {"sort_by": "title.asc", "any": {auto_type: f"<<value>>"}}}
|
||||
|
|
|
@ -55,7 +55,7 @@ class Operations:
|
|||
logger.info(f"{item.title[:25]:<25} | Splitting")
|
||||
|
||||
if self.library.update_blank_track_titles:
|
||||
tracks = self.library.get_all(collection_level="track")
|
||||
tracks = self.library.get_all(builder_level="track")
|
||||
num_edited = 0
|
||||
for i, track in enumerate(tracks, 1):
|
||||
logger.ghost(f"Processing Track: {i}/{len(tracks)} {track.title}")
|
||||
|
|
|
@ -252,21 +252,21 @@ class Overlay:
|
|||
|
||||
if self.name in all_special_text:
|
||||
if self.name.startswith("text(critic") and self.level == "season":
|
||||
raise Failed("Overlay Error: collection_level season doesn't have critic_ratings")
|
||||
raise Failed("Overlay Error: builder_level season doesn't have critic_ratings")
|
||||
elif self.name.startswith("text(audience") and self.level == "season":
|
||||
raise Failed("Overlay Error: collection_level season doesn't have audience_ratings")
|
||||
raise Failed("Overlay Error: builder_level season doesn't have audience_ratings")
|
||||
elif self.name in ["text(season_episode)", "text(show_title)"] and self.level not in ["season", "episode"]:
|
||||
raise Failed(f"Overlay Error: {self.name[5:-1]} only works with collection_level season and episode")
|
||||
raise Failed(f"Overlay Error: {self.name[5:-1]} only works with builder_level season and episode")
|
||||
elif self.name == "text(runtime)" and self.level not in ["movie", "episode"]:
|
||||
raise Failed("Overlay Error: runtime only works with movies and collection_level: episode")
|
||||
raise Failed("Overlay Error: runtime only works with movies and builder_level: episode")
|
||||
elif self.name == "text(season_title)" and self.level != "episode":
|
||||
raise Failed("Overlay Error: season_title only works with collection_level: episode")
|
||||
raise Failed("Overlay Error: season_title only works with builder_level: episode")
|
||||
elif self.name == "text(original_title)" and self.level not in ["movie", "show"]:
|
||||
raise Failed("Overlay Error: original_title only works with movies and shows")
|
||||
elif self.name == "text(episode_count)" and self.level not in ["show", "season"]:
|
||||
raise Failed("Overlay Error: episode_count only works with shows and collection_level: season")
|
||||
raise Failed("Overlay Error: episode_count only works with shows and builder_level: season")
|
||||
elif self.name == ["text(content_rating)", "text(originally_available)"] and self.level == "season":
|
||||
raise Failed(f"Overlay Error: {self.name[5:-1]} only works with movies, shows, and collection_level: episode")
|
||||
raise Failed(f"Overlay Error: {self.name[5:-1]} only works with movies, shows, and builder_level: episode")
|
||||
elif self.name in old_special_text:
|
||||
self.text_overlay_format = "<<value#>>" if self.name[-2] == "#" else f"<<value%>>{'' if self.name[-2] == '0' else '%'}"
|
||||
self.name = f"{self.name[:-2]})"
|
||||
|
|
|
@ -204,7 +204,7 @@ class Overlays:
|
|||
actual_attr = "seasonNumber"
|
||||
elif full_text == "show_title":
|
||||
actual_attr = "parentTitle" if text_overlay.level == "season" else "grandparentTitle"
|
||||
elif full_text in plex.attribute_translation[full_text]:
|
||||
elif full_text in plex.attribute_translation:
|
||||
actual_attr = plex.attribute_translation[full_text]
|
||||
else:
|
||||
actual_attr = full_text
|
||||
|
@ -241,7 +241,7 @@ class Overlays:
|
|||
season = actual_value
|
||||
episode = None
|
||||
else:
|
||||
season, episode = actual_value[1:].split("E")
|
||||
season, episode = actual_value.upper()[1:].split("E")
|
||||
for attr, attr_val in [("season", season), ("episode", episode)]:
|
||||
if attr_val and f"<<{attr}>>" in full_text:
|
||||
full_text = full_text.replace(f"<<{attr}>>", attr_val)
|
||||
|
|
|
@ -216,9 +216,9 @@ collection_mode_options = {
|
|||
"hide_items": "hideItems", "hideitems": "hideItems",
|
||||
"show_items": "showItems", "showitems": "showItems"
|
||||
}
|
||||
collection_level_show_options = ["episode", "season"]
|
||||
collection_level_music_options = ["album", "track"]
|
||||
collection_level_options = collection_level_show_options + collection_level_music_options
|
||||
builder_level_show_options = ["episode", "season"]
|
||||
builder_level_music_options = ["album", "track"]
|
||||
builder_level_options = builder_level_show_options + builder_level_music_options
|
||||
collection_mode_keys = {-1: "default", 0: "hide", 1: "hideItems", 2: "showItems"}
|
||||
collection_order_keys = {0: "release", 1: "alpha", 2: "custom"}
|
||||
item_advance_keys = {
|
||||
|
@ -490,16 +490,16 @@ class Plex(Library):
|
|||
def fetchItem(self, data):
|
||||
return self.PlexServer.fetchItem(data)
|
||||
|
||||
def get_all(self, collection_level=None, load=False):
|
||||
if load and collection_level in [None, "show", "artist", "movie"]:
|
||||
def get_all(self, builder_level=None, load=False):
|
||||
if load and builder_level in [None, "show", "artist", "movie"]:
|
||||
self._all_items = []
|
||||
if self._all_items and collection_level in [None, "show", "artist", "movie"]:
|
||||
if self._all_items and builder_level in [None, "show", "artist", "movie"]:
|
||||
return self._all_items
|
||||
collection_type = collection_level if collection_level else self.Plex.TYPE
|
||||
if not collection_level:
|
||||
collection_level = self.type
|
||||
logger.info(f"Loading All {collection_level.capitalize()}s from Library: {self.name}")
|
||||
key = f"/library/sections/{self.Plex.key}/all?includeGuids=1&type={utils.searchType(collection_type)}"
|
||||
builder_type = builder_level if builder_level else self.Plex.TYPE
|
||||
if not builder_level:
|
||||
builder_level = self.type
|
||||
logger.info(f"Loading All {builder_level.capitalize()}s from Library: {self.name}")
|
||||
key = f"/library/sections/{self.Plex.key}/all?includeGuids=1&type={utils.searchType(builder_type)}"
|
||||
container_start = 0
|
||||
container_size = plexapi.X_PLEX_CONTAINER_SIZE
|
||||
results = []
|
||||
|
@ -507,8 +507,8 @@ class Plex(Library):
|
|||
results.extend(self.fetchItems(key, container_start, container_size))
|
||||
logger.ghost(f"Loaded: {container_start}/{self.Plex._totalViewSize}")
|
||||
container_start += container_size
|
||||
logger.info(f"Loaded {self.Plex._totalViewSize} {collection_level.capitalize()}s")
|
||||
if collection_level in [None, "show", "artist", "movie"]:
|
||||
logger.info(f"Loaded {self.Plex._totalViewSize} {builder_level.capitalize()}s")
|
||||
if builder_level in [None, "show", "artist", "movie"]:
|
||||
self._all_items = results
|
||||
return results
|
||||
|
||||
|
@ -802,7 +802,7 @@ class Plex(Library):
|
|||
items = []
|
||||
if method == "plex_all":
|
||||
logger.info(f"Processing Plex All {data.capitalize()}s")
|
||||
items = self.get_all(collection_level=data)
|
||||
items = self.get_all(builder_level=data)
|
||||
elif method == "plex_pilots":
|
||||
logger.info(f"Processing Plex Pilot {data.capitalize()}s")
|
||||
items = []
|
||||
|
|
Loading…
Reference in a new issue