diff --git a/VERSION b/VERSION index 0a647bfb..cb1d0e2c 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -1.17.3-develop29 +1.17.3-develop30 diff --git a/docs/metadata/details/metadata.md b/docs/metadata/details/metadata.md index 9f1b5b55..6be7d634 100644 --- a/docs/metadata/details/metadata.md +++ b/docs/metadata/details/metadata.md @@ -17,7 +17,7 @@ Only `tmdb_person` works with Playlists. | `collection_mode` | **Description:** Changes the Collection Mode
**Normal Collections Only**
**Values:**
`default`Library default
`hide`Hide Collection
`hide_items`Hide Items in this Collection
`show_items`Show this Collection and its Items
| | `collection_order` | **Description:** Changes the Collection Order
**Normal Collections Only**
When using `custom` you can only have a single builder in the collection.
**Values:**
`release`Order Collection by Release Dates
`alpha`Order Collection Alphabetically
`custom`Order Collection Via the Builder Order
[Any `plex_search` Sort Option](../builders/plex.md#sort-options)Order Collection by any `plex_search` Sort Option
| | `collection_filtering` | **Description:** Changes the Collection Filtering
**Smart Collections Only**
**Values:**
`admin`Always the server admin user
`user`User currently viewing the content
| -| `builder_level` | **Description:** Make season, episode, album or track collections/overlays from `plex_all`, `plex_search`, `trakt_list`, or `imdb_list` Builders and Filters
**Values:**
`season`Collection contains seasons
`episode`Collection contains episodes
`album`Collection contains albums
`track`Collection contains tracks
| +| `builder_level` | **Description:** Make season, episode, album or track collections/overlays from `plex_all`, `plex_search`, `trakt_list`, or `imdb_list` Builders and Filters
**Values:**
`season`Collection contains seasons
`episode`Collection contains episodes
`album`Collection contains albums
`track`Collection contains tracks
| | `visible_library` | **Description:** Changes collection visible on Library (Only works with Plex Pass)
**Values:**
`true`Visible
`false`Not Visible
[Any `schedule` Option](schedule)Visible When Scheduled
| | `visible_home` | **Description:** Changes collection visible on Home (Only works with Plex Pass)
**Values:**
`true`Visible
`false`Not Visible
[Any `schedule` Option](schedule)Visible When Scheduled
| | `visible_shared` | **Description:** Changes collection visible on Shared Users' Home (Only works with Plex Pass)
**Values:**
`true`Visible
`false`Not Visible
[Any `schedule` Option](schedule)Visible When Scheduled
| @@ -44,6 +44,7 @@ None of these details work with Playlists. | `item_genre` | **Description:** Appends new genres to every movie/show in the collection
**Values:** Comma-separated string of genres to append | | `item_genre.remove` | **Description:** Removes existing genres from every movie/show in the collection
**Values:** Comma-separated string of genres to remove | | `item_genre.sync` | **Description:** Matches the genres of every movie/show in the collection to the genres provided (Leave blank to remove all genres)
**Values:** Comma-separated string of genres to sync | +| `item_edition` | **Description:** Replaced the edition of every movie in the collection
**Values:** Edition Name | | `non_item_remove_label` | **Description:** Matches every movie/show that has the given label and is not in the collection and removes the label
**Values:** Comma-separated string of labels to remove | | `item_lock_poster` | **Description:** Locks/Unlocks the poster of every movie/show in the collection
**Default:** `None`
**Values:**
`true`Lock
`false`Unlock
| | `item_lock_background` | **Description:** Locks/Unlocks the background of every movie/show in the collection
**Default:** `None`
**Values:**
`true`Lock
`false`Unlock
| diff --git a/docs/metadata/dynamic.md b/docs/metadata/dynamic.md index 2de3a0bd..54218ade 100644 --- a/docs/metadata/dynamic.md +++ b/docs/metadata/dynamic.md @@ -127,6 +127,7 @@ Depending on the `type` of dynamic collection, `data` is used to specify the opt | [`subtitle_language`](#subtitle-language) | Create a collection for each subtitle language found in the library | ❌ | ✅ | ✅ | ❌ | ❌ | | [`audio_language`](#audio-language) | Create a collection for each audio language found in the library | ❌ | ✅ | ✅ | ❌ | ❌ | | [`studio`](#studio) | Create a collection for each studio found in the library | ❌ | ✅ | ✅ | ❌ | ❌ | +| [`edition`](#edition) | Create a collection for each edition found in the library | ❌ | ✅ | ❌ | ❌ | ❌ | | [`network`](#network) | Create a collection for each network found in the library | ❌ | ❌ | ✅ | ❌ | ❌ | | [`mood`](#mood) | Create a collection for each mood found in the library | ❌ | ❌ | ❌ | ✅ | ❌ | | [`style`](#style) | Create a collection for each artist style found in the library | ❌ | ❌ | ❌ | ✅ | ❌ | @@ -1378,6 +1379,67 @@ dynamic_collections: template: studio collection ``` +### Edition + +Create a collection for each edition found in the library. + + + + + + + + + + + + + + + + + + + + + + + + + + +
type Optionedition
data ValueNot Used
KeysEditions
Key NamesEdition
Default title_formatTop <<key_name>> <<library_type>>s
Default Template + +```yaml +default_template: + smart_filter: + limit: 50 + sort_by: critic_rating.desc + any: + edition: <> +``` + +
+ + +#### Example: + +* Create a collection for each edition found in a Movies library + +```yaml +templates: + edition collection: + smart_filter: + sort_by: critic_rating.desc + all: + edition: <> +dynamic_collections: + Sditions: # mapping name does not matter just needs to be unique + type: edition + title_format: <> + template: edition collection +``` + ### Network Create a collection for each network found in the library. diff --git a/docs/metadata/metadata/movie.md b/docs/metadata/metadata/movie.md index e95c440b..42e387fc 100644 --- a/docs/metadata/metadata/movie.md +++ b/docs/metadata/metadata/movie.md @@ -116,6 +116,7 @@ The available attributes for editing movies are as follows | Attribute | Allowed Values | |:-----------------------|:--------------------------------------------------------------| | `sort_title` | Text to change Sort Title | +| `edition` | Text to change Edition | | `original_title` | Text to change Original Title | | `originally_available` | Date to change Originally Available
**Format:** YYYY-MM-DD | | `content_rating` | Text to change Content Rating | diff --git a/docs/metadata/overlay.md b/docs/metadata/overlay.md index 25780a94..9811081b 100644 --- a/docs/metadata/overlay.md +++ b/docs/metadata/overlay.md @@ -201,6 +201,7 @@ There are multiple Special Text Variables that can be used when formatting the t | `<>`: Title of the Item's Show
`<>`: Uppercase Title of the Item's Show
`<>`Lowercase Title of the Item's Show
`<>`Proper Title of the Item's Show | ❌ | ❌ | ✅ | ✅ | | `<>`: Title of the Item's Season
`<>`: Uppercase Title of the Item's Season
`<>`Lowercase title of the Item's Season
`<>`Proper title of the Item's Season | ❌ | ❌ | ❌ | ✅ | | `<>`: Original Title of the Item
`<>`: Original Title of the Item
`<>`Lowercase Original Title of the Item
`<>`Proper Original Title of the Item | ✅ | ✅ | ❌ | ❌ | +| `<>`: Edition of the Item
`<>`: Edition of the Item
`<>`Lowercase Edition of the Item
`<>`Proper Edition of the Item | ✅ | ❌ | ❌ | ❌ | | `<>`: Content Rating of the Item
`<>`: Uppercase Content Rating of the Item
`<>`Lowercase Content Rating of the Item
`<>`Proper Content Rating of the Item | ✅ | ✅ | ❌ | ✅ | | `<>`: Number of Episodes (`1`)
`<>`: Number of Episodes As Words (`One`)
`<>`: Number of Episodes With 10s Padding (`01`)
`<>`: Number of Episodes With 100s Padding (`001`) | ❌ | ✅ | ✅ | ❌ | | `<>`: Season Number (`1`)
`<>`: Season Number As Words (`One`)
`<>`: Season Number With 10s Padding (`01`)
`<>`: Season Number With 100s Padding (`001`) | ❌ | ❌ | ✅ | ✅ | diff --git a/modules/builder.py b/modules/builder.py index 9aa29c35..8fb70d09 100644 --- a/modules/builder.py +++ b/modules/builder.py @@ -22,7 +22,7 @@ show_only_builders = [ ] movie_only_builders = [ "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", "item_edition", "tvdb_movie", "tvdb_movie_details", "tmdb_upcoming", "trakt_boxoffice", "reciperr_list", "radarr_all", "radarr_taglist" ] music_only_builders = ["item_album_sorting"] @@ -52,8 +52,8 @@ collectionless_details = ["collection_order", "plex_collectionless", "label", "l poster_details + background_details + summary_details + string_details item_false_details = ["item_lock_background", "item_lock_poster", "item_lock_title"] item_bool_details = ["item_tmdb_season_titles", "revert_overlay", "item_assets", "item_refresh"] + item_false_details -item_details = ["non_item_remove_label", "item_label", "item_genre", "item_radarr_tag", "item_sonarr_tag", "item_refresh_delay"] + item_bool_details + list(plex.item_advance_keys.keys()) -none_details = ["label.sync", "item_label.sync", "item_genre.sync", "radarr_taglist", "sonarr_taglist"] +item_details = ["non_item_remove_label", "item_label", "item_genre", "item_edition", "item_radarr_tag", "item_sonarr_tag", "item_refresh_delay"] + item_bool_details + list(plex.item_advance_keys.keys()) +none_details = ["label.sync", "item_label.sync", "item_genre.sync", "radarr_taglist", "sonarr_taglist", "item_edition"] radarr_details = [ "radarr_add_missing", "radarr_add_existing", "radarr_upgrade_existing", "radarr_folder", "radarr_monitor", "radarr_search", "radarr_availability", "radarr_quality", "radarr_tag", "item_radarr_tag" @@ -936,6 +936,8 @@ class CollectionBuilder: if "item_genre.remove" in methods and "item_genre.sync" in methods: raise Failed(f"{self.Type} Error: Cannot use item_genre.remove and item_genre.sync together") self.item_details[method_final] = util.get_list(method_data) if method_data else [] + elif method_name == "item_edition": + self.item_details[method_final] = str(method_data) if method_data else "" elif method_name == "non_item_remove_label": if not method_data: raise Failed(f"{self.Type} Error: non_item_remove_label is blank") @@ -2388,6 +2390,9 @@ class CollectionBuilder: self.library.find_and_upload_assets(item, current_labels) self.library.edit_tags("label", item, add_tags=add_tags, remove_tags=remove_tags, sync_tags=sync_tags) self.library.edit_tags("genre", item, add_tags=add_genres, remove_tags=remove_genres, sync_tags=sync_genres) + if "item_edition" in self.item_details and item.editionTitle != self.item_details["item_edition"]: + self.library.query_data(item.editEditionTitle, self.item_details["item_edition"]) + logger.info(f"{item.title[:25]:<25} | Edition | {self.item_details['item_edition']}") 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: path = path.replace(self.library.Radarr.plex_path, self.library.Radarr.radarr_path) diff --git a/modules/meta.py b/modules/meta.py index 495cd92d..daf72108 100644 --- a/modules/meta.py +++ b/modules/meta.py @@ -12,7 +12,7 @@ ms_auto = [ "trakt_liked_lists", "trakt_people_list", "subtitle_language", "audio_language", "resolution", "decade" ] auto = { - "Movie": ["tmdb_collection", "country", "director", "producer", "writer"] + all_auto + ms_auto, + "Movie": ["tmdb_collection", "edition", "country", "director", "producer", "writer"] + all_auto + ms_auto, "Show": ["network", "origin_country"] + all_auto + ms_auto, "Artist": ["mood", "style", "country"] + all_auto, "Video": ["country", "content_rating"] + all_auto @@ -23,7 +23,7 @@ dynamic_attributes = [ ] auto_type_translation = { "content_rating": "contentRating", "subtitle_language": "subtitleLanguage", "audio_language": "audioLanguage", - "album_style": "album.style" + "album_style": "album.style", "edition": "editionTitle" } default_templates = { "original_language": {"plex_all": True, "filters": {"original_language": "<>"}}, @@ -466,7 +466,7 @@ class MetadataFile(DataFile): auto_list = {str(k): f"{k}s" for k in addons if str(k) not in exclude and f"{k}s" not in exclude} default_template = {"smart_filter": {"limit": 50, "sort_by": "critic_rating.desc", "any": {"year": f"<>"}}} default_title_format = "Best <>s of <>" - elif auto_type in ["genre", "mood", "style", "album_style", "country", "studio", "network", "year", "decade", "content_rating", "subtitle_language", "audio_language", "resolution"]: + elif auto_type in ["genre", "mood", "style", "album_style", "country", "studio", "edition", "network", "year", "decade", "content_rating", "subtitle_language", "audio_language", "resolution"]: search_tag = auto_type_translation[auto_type] if auto_type in auto_type_translation else auto_type if library.is_show and auto_type in ["resolution", "subtitle_language", "audio_language"]: tags = library.get_tags(f"episode.{search_tag}") @@ -1003,6 +1003,8 @@ class MetadataFile(DataFile): if title: add_edit("title", item, meta, methods, value=title) add_edit("sort_title", item, meta, methods, key="titleSort") + if self.library.is_movie: + add_edit("edition", item, meta, methods, key="editionTitle") add_edit("user_rating", item, meta, methods, key="userRating", var_type="float") if not self.library.is_music: add_edit("originally_available", item, meta, methods, key="originallyAvailableAt", value=originally_available, var_type="date") diff --git a/modules/overlay.py b/modules/overlay.py index 1d6b202d..f1b62f09 100644 --- a/modules/overlay.py +++ b/modules/overlay.py @@ -20,12 +20,14 @@ types_for_var = { "movie_episode": ["runtime", "versions", "bitrate"], "season_episode": ["show_title", "season_number"], "show_season": ["episode_count"], + "movie": ["edition"], "episode": ["season_title", "episode_number"] } var_mods = { "title": ["", "U", "L", "P"], "content_rating": ["", "U", "L", "P"], "original_title": ["", "U", "L", "P"], + "edition": ["", "U", "L", "P"], "show_title": ["", "U", "L", "P"], "season_title": ["", "U", "L", "P"], "bitrate": ["", "H", "L"], diff --git a/modules/overlays.py b/modules/overlays.py index ec164d12..64f106a9 100644 --- a/modules/overlays.py +++ b/modules/overlays.py @@ -343,7 +343,7 @@ class Overlays: else: overlay_box = current_overlay.get_coordinates((canvas_width, canvas_height), box=current_overlay.image.size, new_cords=cord) new_poster.paste(current_overlay.image, overlay_box, current_overlay.image) - temp = os.path.join(self.library.overlay_folder, f"temp.jpg") + temp = os.path.join(self.library.overlay_folder, "temp.jpg") new_poster.save(temp) self.library.upload_poster(item, temp) self.library.edit_tags("label", item, add_tags=["Overlay"], do_print=False) diff --git a/modules/plex.py b/modules/plex.py index fe138619..205aac6d 100644 --- a/modules/plex.py +++ b/modules/plex.py @@ -151,6 +151,7 @@ attribute_translation = { "episode_number": "episodeNumber", "season_number": "seasonNumber", "original_title": "originalTitle", + "edition": "editionTitle", "runtime": "duration", "season_title": "parentTitle", "episode_count": "leafCount",