[9] more overlay updates

pull/858/head
meisnate12 3 years ago
parent ff0ee3dce2
commit 33709b28ee

@ -1 +1 @@
1.16.5-develop8 1.16.5-develop9

@ -141,6 +141,22 @@ libraries:
- file: config/Overlays.yml - file: config/Overlays.yml
``` ```
### Remove Overlays
You can remove overlays from a library by adding `remove_overlays: true` to overlay_path
```yaml
libraries:
TV Shows:
metadata_path:
- file: config/TV Shows.yml
overlay_path:
- file: config/Overlays.yml
- remove_overlays: ture
```
* This will remove all overlays when run and not generate new ones.
### Missing Path ### Missing Path
The `missing_path` attribute is used to define where to save the "missing items" YAML file. This file is used to store information about media which is missing from the Plex library compared to what is expected from the Metadata file. The `missing_path` attribute is used to define where to save the "missing items" YAML file. This file is used to store information about media which is missing from the Plex library compared to what is expected from the Metadata file.

@ -30,7 +30,6 @@ The available attributes for the operations attribute are as follows
| `mass_collection_mode` | Updates every Collection in your library to the specified Collection Mode<br>**Values:** `default`: Library default<br>`hide`: Hide Collection<br>`hide_items`: Hide Items in this Collection<br>`show_items`: Show this Collection and its Items<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> | | `mass_collection_mode` | Updates every Collection in your library to the specified Collection Mode<br>**Values:** `default`: Library default<br>`hide`: Hide Collection<br>`hide_items`: Hide Items in this Collection<br>`show_items`: Show this Collection and its Items<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> |
| `update_blank_track_titles` | Search though every track in a music library and replace any blank track titles with the tracks sort title<br>**Values:** `true` or `false` | | `update_blank_track_titles` | Search though every track in a music library and replace any blank track titles with the tracks sort title<br>**Values:** `true` or `false` |
| `remove_title_parentheses` | Search through every title and remove all ending parentheses in an items title if the title isn not locked.<br>**Values:** `true` or `false` | | `remove_title_parentheses` | Search through every title and remove all ending parentheses in an items title if the title isn not locked.<br>**Values:** `true` or `false` |
| `remove_overlays` | Search through every title and removes all overlays.<br>**Values:** `true` or `false` |
| `split_duplicates` | Splits all duplicate movies/shows found in this library<br>**Values:** `true` or `false` | | `split_duplicates` | Splits all duplicate movies/shows found in this library<br>**Values:** `true` or `false` |
| `radarr_add_all` | Adds every item in the library to Radarr. The existing paths in plex will be used as the root folder of each item, if the paths in Plex are not the same as your Radarr paths you can use the `plex_path` and `radarr_path` [Radarr](radarr) details to convert the paths.<br>**Values:** `true` or `false` | | `radarr_add_all` | Adds every item in the library to Radarr. The existing paths in plex will be used as the root folder of each item, if the paths in Plex are not the same as your Radarr paths you can use the `plex_path` and `radarr_path` [Radarr](radarr) details to convert the paths.<br>**Values:** `true` or `false` |
| `radarr_remove_by_tag` | Removes every item from Radarr with the Tags given<br>**Values:** List or comma separated string of tags | | `radarr_remove_by_tag` | Removes every item from Radarr with the Tags given<br>**Values:** List or comma separated string of tags |

Binary file not shown.

Before

Width:  |  Height:  |  Size: 265 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.1 MiB

@ -1,175 +0,0 @@
# Image Overlay Detail
In order to add an overlay to a set of items you must add `item_overlay: OVERLAY_NAME` to the collection config, where `OVERLAY_NAME` matches the exact name of a folder in your `overlays` directory.
Your `overlays` directory must be inside your config folder structured like below:
```
config
├── overlays
│ ├── OVERLAY_NAME
│ ├── overlay.png
```
* `OVERLAY_NAME` is the folder contacting your `overlay.png` and its name is what you give `item_overlay` to refer to this specific overlay.
* `overlay.png` is the overlay file with the banner. You can create you're own with this [PSD](https://github.com/meisnate12/Plex-Meta-Manager/blob/master/overlays.psd). The font can be found [here](https://www.dafontfree.net/freefonts-eurostile-extended-f123859.htm).
* An item can only be in one overlay search so make sure you exclude other searches when using multiple overlays.
* Posters will be backed up in the overlay director and if an item is removed from the search the original poster should be added back.
* `revert_overlay` can be added to an overlay collection configuration to revert all movies changed by that overlay back to their original posters.
## Examples
### Example Folder Structure
This is an example of the default set found [here](https://github.com/meisnate12/Plex-Meta-Manager/tree/master/config/overlays) which would have 5 overlay options `4K`, `4K-Dolby`, `4K-HDR`, `Dolby`, and `HDR` and have a directory structured like below:
```
config
├── config.yml
├── Movies.yml
├── TV Shows.yml
├── overlays
│ ├── 4K
│ ├── overlay.png
│ ├── 4K-Dolby
│ ├── overlay.png
│ ├── 4K-HDR
│ ├── overlay.png
│ ├── Dolby
│ ├── overlay.png
│ ├── HDR
│ ├── overlay.png
```
### Alternative URL Images
The alternative way to specify your overlay image is do use the `name` and either `url` or `git` attributes like so.
```yaml
collections:
4K Overlay:
plex_search:
all:
resolution: 4K
item_overlay:
name: 4K
url: https://raw.githubusercontent.com/wiki/meisnate12/Plex-Meta-Manager/overlay.png
build_collection: false
```
```yaml
collections:
4K Overlay:
plex_search:
all:
resolution: 4K
item_overlay:
name: 4K
git: yozora/Overlays/4K/overlay
build_collection: false
```
### Examples Collection Configs
#### 4K Overlay Only
![4K Overlay](overlay-4k.png)
Add a 4K overlay to all 4K Movies
```yaml
collections:
4K Overlay:
plex_search:
all:
resolution: 4K
item_overlay: 4K
build_collection: false
```
#### 4K and HDR Overlays
Here's an example of how you could add `4K`, `4K-HDR`, and `HDR` overlays
```yaml
collections:
4K Overlay:
plex_search:
all:
resolution: 4K
hdr: false
item_overlay: 4K
build_collection: false
4K-HDR Overlay:
plex_search:
all:
resolution: 4K
hdr: true
item_overlay: 4K-HDR
build_collection: false
HDR Overlay:
plex_search:
all:
hdr: true
filters:
resolution.not: 4K
item_overlay: HDR
build_collection: false
```
#### 4K, HDR, Dolby Overlays
Here's an example of how you could add `4K`, `4K-HDR`, `4K-Dolby`, `Dolby`, and `HDR` overlays
**Note: This only works is your filenames have a tag in them for Dolby files as Plex cannot detect dolby yet**
```yaml
collections:
4K:
plex_search:
all:
resolution: 4K
hdr: false
filters:
filepath.not: DoVi
item_overlay: 4K
build_collection: false
4K-HDR:
plex_search:
all:
resolution: 4K
hdr: true
filters:
filepath.not: DoVi
item_overlay: 4K-HDR
build_collection: false
4K-Dolby:
plex_search:
all:
resolution: 4K
filters:
filepath: DoVi
item_overlay: 4K-Dolby
build_collection: false
HDR:
plex_search:
all:
hdr: true
filters:
filepath.not: DoVi
resolution.not: 4K
item_overlay: HDR
build_collection: false
Dolby:
plex_all: true
filters:
filepath: DoVi
resolution.not: 4K
item_overlay: Dolby
build_collection: false
```
## User Generated Overlays
![Language Overlay](overlay-language.png)

@ -4,7 +4,7 @@ Overlay files are used to create and maintain overlays within the Plex libraries
Overlays and templates are defined within one or more Overlay files, which are linked to libraries in the [Libraries Attribute](../config/libraries.md#overlay-path) within the [Configuration File](../config/configuration.md). Overlays and templates are defined within one or more Overlay files, which are linked to libraries in the [Libraries Attribute](../config/libraries.md#overlay-path) within the [Configuration File](../config/configuration.md).
**To remove all overlays use the `remove_overlays` library operation.** **To remove all overlays add `remove_overlays: true` to the `overlay_path` [Libraries Attribute](../config/libraries.md#remove-overlays).**
**To change a single overlay original image either replace the image in the assets folder or remove the `Overlay` shared label and then PMM will overlay the new image** **To change a single overlay original image either replace the image in the assets folder or remove the `Overlay` shared label and then PMM will overlay the new image**
@ -73,9 +73,11 @@ overlays:
imdb_chart: top_movies imdb_chart: top_movies
``` ```
### Remove Overlay ### Supress Overlays
You can add `remove_overlay` to an overlay definition and give it a list or comma separated string of overlay names you want removed from this item if this overlay is attached to the item. You can add `supress_overlays` to an overlay definition and give it a list or comma separated string of overlay names you want suppressed from this item if this overlay is attached to the item.
So in this example if the `4K-HDR` overlay matches an item then the `4K` and `HDR` overlays will also match. The `supress_overlays` attribute on `4K-HDR` will stop the overlays specified (`4K` and `HDR`) from also being applied.
```yaml ```yaml
overlays: overlays:
@ -88,7 +90,7 @@ overlays:
all: all:
hdr: true hdr: true
4K-HDR: 4K-HDR:
remove_overlay: supress_overlays:
- 4K - 4K
- HDR - HDR
plex_search: plex_search:
@ -129,7 +131,9 @@ These filter media items added to the collection by any of the Builders.
* [Filters](filters) * [Filters](filters)
## Examples ## Example
### Example Overlay File
```yaml ```yaml
overlays: overlays:
@ -153,4 +157,18 @@ overlays:
plex_all: true plex_all: true
filters: filters:
has_dolby_vision: true has_dolby_vision: true
``` ```
### Example Folder Structure
```
config
├── config.yml
├── Movies.yml
├── TV Shows.yml
├── Overlays.yml
├── overlays
│ ├── 4K.png
│ ├── Dolby.png
│ ├── HDR.png
```

@ -97,7 +97,7 @@ boolean_details = [
scheduled_boolean = ["visible_library", "visible_home", "visible_shared"] scheduled_boolean = ["visible_library", "visible_home", "visible_shared"]
string_details = ["sort_title", "content_rating", "name_mapping"] string_details = ["sort_title", "content_rating", "name_mapping"]
ignored_details = [ ignored_details = [
"smart_filter", "smart_label", "smart_url", "run_again", "schedule", "sync_mode", "template", "test", "remove_overlay", "smart_filter", "smart_label", "smart_url", "run_again", "schedule", "sync_mode", "template", "test", "supress_overlays",
"delete_not_scheduled", "tmdb_person", "build_collection", "collection_order", "collection_level", "overlay", "delete_not_scheduled", "tmdb_person", "build_collection", "collection_order", "collection_level", "overlay",
"validate_builders", "libraries", "sync_to_users", "collection_name", "playlist_name", "name", "blank_collection" "validate_builders", "libraries", "sync_to_users", "collection_name", "playlist_name", "name", "blank_collection"
] ]
@ -190,7 +190,7 @@ custom_sort_builders = [
"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"
] ]
episode_parts_only = ["plex_pilots"] episode_parts_only = ["plex_pilots"]
overlay_only = ["overlay", "remove_overlay"] overlay_only = ["overlay", "supress_overlays"]
overlay_attributes = [ overlay_attributes = [
"filters", "limit", "show_missing", "save_missing", "missing_only_released", "minimum_items", "cache_builders", "tmdb_region" "filters", "limit", "show_missing", "save_missing", "missing_only_released", "minimum_items", "cache_builders", "tmdb_region"
] + all_builders + overlay_only ] + all_builders + overlay_only
@ -264,7 +264,7 @@ class CollectionBuilder:
self.data[attr] = new_attributes[attr] self.data[attr] = new_attributes[attr]
methods[attr.lower()] = attr methods[attr.lower()] = attr
self.remove_overlays = [] self.supress_overlays = []
if self.overlay: if self.overlay:
if "overlay" in methods: if "overlay" in methods:
logger.debug("") logger.debug("")
@ -308,14 +308,14 @@ class CollectionBuilder:
if not os.path.exists(overlay_path): if not os.path.exists(overlay_path):
raise Failed(f"{self.Type} Error: Overlay Image not found at: {overlay_path}") raise Failed(f"{self.Type} Error: Overlay Image not found at: {overlay_path}")
if "remove_overlay" in methods: if "supress_overlays" in methods:
logger.debug("") logger.debug("")
logger.debug("Validating Method: remove_overlay") logger.debug("Validating Method: supress_overlays")
logger.debug(f"Value: {data[methods['remove_overlay']]}") logger.debug(f"Value: {data[methods['supress_overlays']]}")
if data[methods["remove_overlay"]]: if data[methods["supress_overlays"]]:
self.remove_overlays = util.get_list(data[methods["remove_overlay"]]) self.supress_overlays = util.get_list(data[methods["supress_overlays"]])
else: else:
logger.error(f"{self.Type} Error: remove_overlay attribute is blank") logger.error(f"{self.Type} Error: supress_overlays attribute is blank")
if self.playlist: if self.playlist:
if "libraries" in methods: if "libraries" in methods:

@ -577,7 +577,6 @@ class ConfigFile:
"mass_originally_available_update": None, "mass_originally_available_update": None,
"mass_imdb_parental_labels": None, "mass_imdb_parental_labels": None,
"remove_title_parentheses": None, "remove_title_parentheses": None,
"remove_overlays": None
} }
display_name = f"{params['name']} ({params['mapping_name']})" if lib and "library_name" in lib and lib["library_name"] else params["mapping_name"] display_name = f"{params['name']} ({params['mapping_name']})" if lib and "library_name" in lib and lib["library_name"] else params["mapping_name"]
@ -671,8 +670,6 @@ class ConfigFile:
params["update_blank_track_titles"] = check_for_attribute(lib["operations"], "update_blank_track_titles", var_type="bool", default=False, save=False) params["update_blank_track_titles"] = check_for_attribute(lib["operations"], "update_blank_track_titles", var_type="bool", default=False, save=False)
if "remove_title_parentheses" in lib["operations"]: if "remove_title_parentheses" in lib["operations"]:
params["remove_title_parentheses"] = check_for_attribute(lib["operations"], "remove_title_parentheses", var_type="bool", default=False, save=False) params["remove_title_parentheses"] = check_for_attribute(lib["operations"], "remove_title_parentheses", var_type="bool", default=False, save=False)
if "remove_overlays" in lib["operations"]:
params["remove_overlays"] = check_for_attribute(lib["operations"], "remove_overlays", var_type="bool", default=False, save=False)
if "mass_collection_mode" in lib["operations"]: if "mass_collection_mode" in lib["operations"]:
try: try:
params["mass_collection_mode"] = util.check_collection_mode(lib["operations"]["mass_collection_mode"]) params["mass_collection_mode"] = util.check_collection_mode(lib["operations"]["mass_collection_mode"])
@ -753,12 +750,16 @@ class ConfigFile:
params["skip_library"] = True params["skip_library"] = True
params["overlay_path"] = [] params["overlay_path"] = []
params["remove_overlays"] = False
if lib and "overlay_path" in lib: if lib and "overlay_path" in lib:
if not lib["overlay_path"]: if not lib["overlay_path"]:
raise Failed("Config Error: overlay_path attribute is blank") raise Failed("Config Error: overlay_path attribute is blank")
files = util.load_files(lib["overlay_path"], "overlay_path") files = util.load_files(lib["overlay_path"], "overlay_path")
if not files: if not files:
raise Failed("Config Error: No Paths Found for overlay_path") raise Failed("Config Error: No Paths Found for overlay_path")
for file in util.get_list(lib["overlay_path"], split=False):
if isinstance(file, dict) and "remove_overlays" in file and file["remove_overlays"] is True:
params["remove_overlays"] = True
params["overlay_path"] = files params["overlay_path"] = files
logger.info("") logger.info("")

@ -3,7 +3,7 @@ from modules import util
from modules.builder import CollectionBuilder from modules.builder import CollectionBuilder
from modules.util import Failed from modules.util import Failed
from plexapi.exceptions import BadRequest from plexapi.exceptions import BadRequest
from plexapi.video import Show, Season, Episode from plexapi.video import Movie, Show, Season, Episode
from PIL import Image from PIL import Image
logger = util.logger logger = util.logger
@ -18,12 +18,12 @@ class Overlays:
logger.info("") logger.info("")
logger.separator(f"{self.library.name} Library Overlays") logger.separator(f"{self.library.name} Library Overlays")
logger.info("") logger.info("")
overlay_rating_keys = {} overlay_to_keys = {}
item_keys = {} key_to_item = {}
os.makedirs(self.library.overlay_backup, exist_ok=True) os.makedirs(self.library.overlay_backup, exist_ok=True)
overlay_updated = {} overlay_updated = {}
overlay_images = {} overlay_images = {}
item_overlays = {} key_to_overlays = {}
if self.library.remove_overlays: if self.library.remove_overlays:
logger.info("") logger.info("")
logger.separator(f"Removing Overlays for the {self.library.name} Library") logger.separator(f"Removing Overlays for the {self.library.name} Library")
@ -37,8 +37,8 @@ class Overlays:
logger.separator(f"Gathering Items for {k} Overlay", space=False, border=False) logger.separator(f"Gathering Items for {k} Overlay", space=False, border=False)
if builder.overlay not in overlay_rating_keys: if builder.overlay not in overlay_to_keys:
overlay_rating_keys[builder.overlay] = [] overlay_to_keys[builder.overlay] = []
if builder.filters or builder.tmdb_filters: if builder.filters or builder.tmdb_filters:
logger.info("") logger.info("")
@ -54,19 +54,19 @@ class Overlays:
builder.filter_and_save_items(builder.gather_ids(method, value)) builder.filter_and_save_items(builder.gather_ids(method, value))
if builder.added_items: if builder.added_items:
for item in builder.added_items: for item in builder.added_items:
item_keys[item.ratingKey] = item key_to_item[item.ratingKey] = item
if item.ratingKey not in overlay_rating_keys[builder.overlay]: if item.ratingKey not in overlay_to_keys[builder.overlay]:
overlay_rating_keys[builder.overlay].append(item.ratingKey) overlay_to_keys[builder.overlay].append(item.ratingKey)
if builder.remove_overlays: if builder.supress_overlays:
for rk in overlay_rating_keys[builder.overlay]: for rk in overlay_to_keys[builder.overlay]:
for remove_overlay in builder.remove_overlays: for supress_overlay in builder.supress_overlays:
if remove_overlay in overlay_rating_keys and rk in overlay_rating_keys[remove_overlay]: if supress_overlay in overlay_to_keys and rk in overlay_to_keys[supress_overlay]:
overlay_rating_keys[remove_overlay].remove(rk) overlay_to_keys[supress_overlay].remove(rk)
except Failed as e: except Failed as e:
logger.error(e) logger.error(e)
for overlay_name, over_keys in overlay_rating_keys.items(): for overlay_name, over_keys in overlay_to_keys.items():
clean_name, _ = util.validate_filename(overlay_name) clean_name, _ = util.validate_filename(overlay_name)
image_compare = None image_compare = None
if self.config.Cache: if self.config.Cache:
@ -76,17 +76,17 @@ class Overlays:
overlay_updated[overlay_name] = not image_compare or str(overlay_size) != str(image_compare) overlay_updated[overlay_name] = not image_compare or str(overlay_size) != str(image_compare)
overlay_images[overlay_name] = Image.open(overlay_file).convert("RGBA") overlay_images[overlay_name] = Image.open(overlay_file).convert("RGBA")
for over_key in over_keys: for over_key in over_keys:
if over_key not in item_overlays: if over_key not in key_to_overlays:
item_overlays[over_key] = [] key_to_overlays[over_key] = (key_to_item[over_key], [])
item_overlays[over_key].append(overlay_name) key_to_overlays[over_key][1].append(overlay_name)
if self.config.Cache: if self.config.Cache:
self.config.Cache.update_image_map(overlay_name, f"{self.library.image_table_name}_overlays", overlay_name, overlay_size) self.config.Cache.update_image_map(overlay_name, f"{self.library.image_table_name}_overlays", overlay_name, overlay_size)
def find_poster_url(plex_item): def find_poster_url(plex_item):
if self.library.is_movie: if isinstance(plex_item, Movie):
if plex_item.ratingKey in self.library.movie_rating_key_map: if plex_item.ratingKey in self.library.movie_rating_key_map:
return self.config.TMDb.get_movie(self.library.movie_rating_key_map[plex_item.ratingKey]).poster_url return self.config.TMDb.get_movie(self.library.movie_rating_key_map[plex_item.ratingKey]).poster_url
elif self.library.is_show: elif isinstance(plex_item, (Show, Season, Episode)):
check_key = plex_item.ratingKey if isinstance(plex_item, Show) else plex_item.show().ratingKey check_key = plex_item.ratingKey if isinstance(plex_item, Show) else plex_item.show().ratingKey
tmdb_id = self.config.Convert.tvdb_to_tmdb(self.library.show_rating_key_map[check_key]) tmdb_id = self.config.Convert.tvdb_to_tmdb(self.library.show_rating_key_map[check_key])
if isinstance(plex_item, Show) and plex_item.ratingKey in self.library.show_rating_key_map: if isinstance(plex_item, Show) and plex_item.ratingKey in self.library.show_rating_key_map:
@ -97,7 +97,7 @@ class Overlays:
return self.config.TMDb.get_episode(tmdb_id, plex_item.seasonNumber, plex_item.episodeNumber).still_url return self.config.TMDb.get_episode(tmdb_id, plex_item.seasonNumber, plex_item.episodeNumber).still_url
def get_overlay_items(libtype=None): def get_overlay_items(libtype=None):
return [o for o in self.library.search(label="Overlay", libtype=libtype) if o.ratingKey not in item_overlays] return [o for o in self.library.search(label="Overlay", libtype=libtype) if o.ratingKey not in key_to_overlays]
remove_overlays = get_overlay_items() remove_overlays = get_overlay_items()
if self.library.is_show: if self.library.is_show:
@ -129,102 +129,99 @@ class Overlays:
poster_location = find_poster_url(item) poster_location = find_poster_url(item)
if poster_location: if poster_location:
self.library.upload_poster(item, poster_location, url=is_url) self.library.upload_poster(item, poster_location, url=is_url)
self.library.edit_tags("label", item, remove_tags=["Overlay"]) self.library.edit_tags("label", item, remove_tags=["Overlay"], do_print=False)
if original: if original:
os.remove(original) os.remove(original)
else: else:
logger.error(f"No Poster found to restore for {item.title}") logger.error(f"No Poster found to restore for {item.title}")
logger.exorcise() logger.exorcise()
if item_overlays: if key_to_overlays:
logger.info("") logger.info("")
logger.separator(f"Applying Overlays for the {self.library.name} Library") logger.separator(f"Applying Overlays for the {self.library.name} Library")
logger.info("") logger.info("")
for i, (over_key, (item, over_names)) in enumerate(sorted(key_to_overlays.items(), key=lambda io: io[1][0].title), 1):
for i, (over_key, over_names) in enumerate(item_overlays.items(), 1): try:
try: logger.ghost(f"Overlaying: {i}/{len(key_to_overlays)} {item.title}")
item = item_keys[over_key] image_compare = None
logger.ghost(f"Overlaying: {i}/{len(item_overlays)} {item.title}") overlay_compare = None
image_compare = None if self.config.Cache:
overlay_compare = None image, image_compare, _ = self.config.Cache.query_image_map(item.ratingKey, f"{self.library.image_table_name}_overlays")
if self.config.Cache: overlay_compare = [] if overlay_compare is None else util.get_list(overlay_compare)
image, image_compare, _ = self.config.Cache.query_image_map(item.ratingKey, f"{self.library.image_table_name}_overlays") has_overlay = any([item_tag.tag.lower() == "overlay" for item_tag in item.labels])
overlay_compare = [] if overlay_compare is None else util.get_list(overlay_compare)
has_overlay = any([item_tag.tag.lower() == "overlay" for item_tag in item.labels]) overlay_change = False if has_overlay else True
if not overlay_change:
overlay_change = False if has_overlay else True for oc in overlay_compare:
if not overlay_change: if oc not in over_names:
for oc in overlay_compare: overlay_change = True
if oc not in over_names: if not overlay_change:
overlay_change = True
if not overlay_change:
for over_name in over_names:
if over_name not in overlay_compare or overlay_updated[over_name]:
overlay_change = True
clean_name, _ = util.validate_filename(item.title)
poster, _, item_dir = self.library.find_assets(
name="poster" if self.library.asset_folders else clean_name,
folder_name=clean_name if self.library.asset_folders else None,
prefix=f"{item.title}'s "
)
has_original = False
changed_image = False
new_backup = None
if poster:
if image_compare and str(poster.compare) != str(image_compare):
changed_image = True
elif has_overlay:
if os.path.exists(os.path.join(self.library.overlay_backup, f"{item.ratingKey}.png")):
has_original = os.path.join(self.library.overlay_backup, f"{item.ratingKey}.png")
elif os.path.exists(os.path.join(self.library.overlay_backup, f"{item.ratingKey}.jpg")):
has_original = os.path.join(self.library.overlay_backup, f"{item.ratingKey}.jpg")
else:
self.library.reload(item)
new_backup = find_poster_url(item)
if new_backup is None:
new_backup = item.posterUrl
else:
self.library.reload(item)
new_backup = item.posterUrl
if new_backup:
changed_image = True
image_response = self.config.get(new_backup)
if image_response.status_code >= 400:
raise Failed(f"Overlay Error: Poster Download Failed for {item.title}")
i_ext = "jpg" if image_response.headers["Content-Type"] == "image/jpeg" else "png"
backup_image_path = os.path.join(self.library.overlay_backup, f"{item.ratingKey}.{i_ext}")
with open(backup_image_path, "wb") as handler:
handler.write(image_response.content)
while util.is_locked(backup_image_path):
time.sleep(1)
has_original = backup_image_path
poster_uploaded = False
if changed_image or overlay_change:
new_poster = Image.open(poster.location if poster else has_original).convert("RGBA")
temp = os.path.join(self.library.overlay_folder, f"temp.png")
try:
for over_name in over_names: for over_name in over_names:
new_poster = new_poster.resize(overlay_images[over_name].size, Image.ANTIALIAS) if over_name not in overlay_compare or overlay_updated[over_name]:
new_poster.paste(overlay_images[over_name], (0, 0), overlay_images[over_name]) overlay_change = True
new_poster.save(temp, "PNG")
self.library.upload_poster(item, temp) clean_name, _ = util.validate_filename(item.title)
self.library.edit_tags("label", item, add_tags=["Overlay"]) poster, _, item_dir = self.library.find_assets(
name="poster" if self.library.asset_folders else clean_name,
folder_name=clean_name if self.library.asset_folders else None,
prefix=f"{item.title}'s "
)
has_original = None
changed_image = False
new_backup = None
if poster:
if image_compare and str(poster.compare) != str(image_compare):
changed_image = True
elif has_overlay:
if os.path.exists(os.path.join(self.library.overlay_backup, f"{item.ratingKey}.png")):
has_original = os.path.join(self.library.overlay_backup, f"{item.ratingKey}.png")
elif os.path.exists(os.path.join(self.library.overlay_backup, f"{item.ratingKey}.jpg")):
has_original = os.path.join(self.library.overlay_backup, f"{item.ratingKey}.jpg")
else:
self.library.reload(item)
new_backup = find_poster_url(item)
if new_backup is None:
new_backup = item.posterUrl
else:
self.library.reload(item) self.library.reload(item)
poster_uploaded = True new_backup = item.posterUrl
logger.info(f"Detail: Overlays: {', '.join(over_names)} applied to {item.title}") if new_backup:
except (OSError, BadRequest) as e: changed_image = True
logger.stacktrace() image_response = self.config.get(new_backup)
raise Failed(f"Overlay Error: {e}") if image_response.status_code >= 400:
raise Failed(f"Overlay Error: Poster Download Failed for {item.title}")
if self.config.Cache: i_ext = "jpg" if image_response.headers["Content-Type"] == "image/jpeg" else "png"
if poster_uploaded: backup_image_path = os.path.join(self.library.overlay_backup, f"{item.ratingKey}.{i_ext}")
self.config.Cache.update_image_map( with open(backup_image_path, "wb") as handler:
item.ratingKey, self.library.image_table_name, item.thumb, handler.write(image_response.content)
poster.compare if poster else item.thumb, overlay=','.join(over_names) while util.is_locked(backup_image_path):
) time.sleep(1)
except Failed as e: has_original = backup_image_path
logger.error(e)
poster_compare = None
if poster is None and has_original is None:
logger.error(f"Overlay Error: No poster found for {item.title}")
elif changed_image or overlay_change:
new_poster = Image.open(poster.location if poster else has_original).convert("RGBA")
temp = os.path.join(self.library.overlay_folder, f"temp.png")
try:
for over_name in over_names:
new_poster = new_poster.resize(overlay_images[over_name].size, Image.ANTIALIAS)
new_poster.paste(overlay_images[over_name], (0, 0), overlay_images[over_name])
new_poster.save(temp, "PNG")
self.library.upload_poster(item, temp)
self.library.edit_tags("label", item, add_tags=["Overlay"], do_print=False)
self.library.reload(item)
poster_compare = poster.compare if poster else item.thumb
logger.info(f"Detail: Overlays: {', '.join(over_names)} applied to {item.title}")
except (OSError, BadRequest) as e:
logger.stacktrace()
raise Failed(f"Overlay Error: {e}")
if self.config.Cache and poster_compare:
self.config.Cache.update_image_map(item.ratingKey, self.library.image_table_name, item.thumb,
poster_compare, overlay=','.join(over_names))
except Failed as e:
logger.error(e)
logger.exorcise() logger.exorcise()

@ -293,7 +293,7 @@ def update_libraries(config):
if not config.library_first and not config.test_mode and not collection_only: if not config.library_first and not config.test_mode and not collection_only:
if not overlays_only and library.library_operation: if not overlays_only and library.library_operation:
library.Operations.run_operations() library.Operations.run_operations()
if not operations_only and library.overlay_files or library.remove_overlays: if not operations_only and (library.overlay_files or library.remove_overlays):
library.Overlays.run_overlays() library.Overlays.run_overlays()
logger.remove_library_handler(library.mapping_name) logger.remove_library_handler(library.mapping_name)

Loading…
Cancel
Save