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:** |
| `item_lock_background` | **Description:** Locks/Unlocks the background of every movie/show in the collection
**Default:** `None`
**Values:** |
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 Option |
+ edition |
+
+
+ data Value |
+ Not Used |
+
+
+ Keys |
+ Editions |
+
+
+ Key Names |
+ Edition |
+
+
+ Default title_format |
+ Top <<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",