mirror of
https://github.com/meisnate12/Plex-Meta-Manager
synced 2024-11-26 06:20:23 +00:00
[9] more overlay updates
This commit is contained in:
parent
ff0ee3dce2
commit
33709b28ee
11 changed files with 155 additions and 299 deletions
2
VERSION
2
VERSION
|
@ -1 +1 @@
|
|||
1.16.5-develop8
|
||||
1.16.5-develop9
|
||||
|
|
|
@ -141,6 +141,22 @@ libraries:
|
|||
- 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
|
||||
|
||||
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> |
|
||||
| `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_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` |
|
||||
| `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 |
|
||||
|
|
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).
|
||||
|
||||
**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**
|
||||
|
||||
|
@ -73,9 +73,11 @@ overlays:
|
|||
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
|
||||
overlays:
|
||||
|
@ -88,7 +90,7 @@ overlays:
|
|||
all:
|
||||
hdr: true
|
||||
4K-HDR:
|
||||
remove_overlay:
|
||||
supress_overlays:
|
||||
- 4K
|
||||
- HDR
|
||||
plex_search:
|
||||
|
@ -129,7 +131,9 @@ These filter media items added to the collection by any of the Builders.
|
|||
|
||||
* [Filters](filters)
|
||||
|
||||
## Examples
|
||||
## Example
|
||||
|
||||
### Example Overlay File
|
||||
|
||||
```yaml
|
||||
overlays:
|
||||
|
@ -153,4 +157,18 @@ overlays:
|
|||
plex_all: true
|
||||
filters:
|
||||
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"]
|
||||
string_details = ["sort_title", "content_rating", "name_mapping"]
|
||||
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",
|
||||
"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"
|
||||
]
|
||||
episode_parts_only = ["plex_pilots"]
|
||||
overlay_only = ["overlay", "remove_overlay"]
|
||||
overlay_only = ["overlay", "supress_overlays"]
|
||||
overlay_attributes = [
|
||||
"filters", "limit", "show_missing", "save_missing", "missing_only_released", "minimum_items", "cache_builders", "tmdb_region"
|
||||
] + all_builders + overlay_only
|
||||
|
@ -264,7 +264,7 @@ class CollectionBuilder:
|
|||
self.data[attr] = new_attributes[attr]
|
||||
methods[attr.lower()] = attr
|
||||
|
||||
self.remove_overlays = []
|
||||
self.supress_overlays = []
|
||||
if self.overlay:
|
||||
if "overlay" in methods:
|
||||
logger.debug("")
|
||||
|
@ -308,14 +308,14 @@ class CollectionBuilder:
|
|||
if not os.path.exists(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("Validating Method: remove_overlay")
|
||||
logger.debug(f"Value: {data[methods['remove_overlay']]}")
|
||||
if data[methods["remove_overlay"]]:
|
||||
self.remove_overlays = util.get_list(data[methods["remove_overlay"]])
|
||||
logger.debug("Validating Method: supress_overlays")
|
||||
logger.debug(f"Value: {data[methods['supress_overlays']]}")
|
||||
if data[methods["supress_overlays"]]:
|
||||
self.supress_overlays = util.get_list(data[methods["supress_overlays"]])
|
||||
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 "libraries" in methods:
|
||||
|
|
|
@ -577,7 +577,6 @@ class ConfigFile:
|
|||
"mass_originally_available_update": None,
|
||||
"mass_imdb_parental_labels": 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"]
|
||||
|
||||
|
@ -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)
|
||||
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)
|
||||
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"]:
|
||||
try:
|
||||
params["mass_collection_mode"] = util.check_collection_mode(lib["operations"]["mass_collection_mode"])
|
||||
|
@ -753,12 +750,16 @@ class ConfigFile:
|
|||
params["skip_library"] = True
|
||||
|
||||
params["overlay_path"] = []
|
||||
params["remove_overlays"] = False
|
||||
if lib and "overlay_path" in lib:
|
||||
if not lib["overlay_path"]:
|
||||
raise Failed("Config Error: overlay_path attribute is blank")
|
||||
files = util.load_files(lib["overlay_path"], "overlay_path")
|
||||
if not files:
|
||||
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
|
||||
|
||||
logger.info("")
|
||||
|
|
|
@ -3,7 +3,7 @@ from modules import util
|
|||
from modules.builder import CollectionBuilder
|
||||
from modules.util import Failed
|
||||
from plexapi.exceptions import BadRequest
|
||||
from plexapi.video import Show, Season, Episode
|
||||
from plexapi.video import Movie, Show, Season, Episode
|
||||
from PIL import Image
|
||||
|
||||
logger = util.logger
|
||||
|
@ -18,12 +18,12 @@ class Overlays:
|
|||
logger.info("")
|
||||
logger.separator(f"{self.library.name} Library Overlays")
|
||||
logger.info("")
|
||||
overlay_rating_keys = {}
|
||||
item_keys = {}
|
||||
overlay_to_keys = {}
|
||||
key_to_item = {}
|
||||
os.makedirs(self.library.overlay_backup, exist_ok=True)
|
||||
overlay_updated = {}
|
||||
overlay_images = {}
|
||||
item_overlays = {}
|
||||
key_to_overlays = {}
|
||||
if self.library.remove_overlays:
|
||||
logger.info("")
|
||||
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)
|
||||
|
||||
if builder.overlay not in overlay_rating_keys:
|
||||
overlay_rating_keys[builder.overlay] = []
|
||||
if builder.overlay not in overlay_to_keys:
|
||||
overlay_to_keys[builder.overlay] = []
|
||||
|
||||
if builder.filters or builder.tmdb_filters:
|
||||
logger.info("")
|
||||
|
@ -54,19 +54,19 @@ class Overlays:
|
|||
builder.filter_and_save_items(builder.gather_ids(method, value))
|
||||
if builder.added_items:
|
||||
for item in builder.added_items:
|
||||
item_keys[item.ratingKey] = item
|
||||
if item.ratingKey not in overlay_rating_keys[builder.overlay]:
|
||||
overlay_rating_keys[builder.overlay].append(item.ratingKey)
|
||||
key_to_item[item.ratingKey] = item
|
||||
if item.ratingKey not in overlay_to_keys[builder.overlay]:
|
||||
overlay_to_keys[builder.overlay].append(item.ratingKey)
|
||||
|
||||
if builder.remove_overlays:
|
||||
for rk in overlay_rating_keys[builder.overlay]:
|
||||
for remove_overlay in builder.remove_overlays:
|
||||
if remove_overlay in overlay_rating_keys and rk in overlay_rating_keys[remove_overlay]:
|
||||
overlay_rating_keys[remove_overlay].remove(rk)
|
||||
if builder.supress_overlays:
|
||||
for rk in overlay_to_keys[builder.overlay]:
|
||||
for supress_overlay in builder.supress_overlays:
|
||||
if supress_overlay in overlay_to_keys and rk in overlay_to_keys[supress_overlay]:
|
||||
overlay_to_keys[supress_overlay].remove(rk)
|
||||
except Failed as 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)
|
||||
image_compare = None
|
||||
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_images[overlay_name] = Image.open(overlay_file).convert("RGBA")
|
||||
for over_key in over_keys:
|
||||
if over_key not in item_overlays:
|
||||
item_overlays[over_key] = []
|
||||
item_overlays[over_key].append(overlay_name)
|
||||
if over_key not in key_to_overlays:
|
||||
key_to_overlays[over_key] = (key_to_item[over_key], [])
|
||||
key_to_overlays[over_key][1].append(overlay_name)
|
||||
if self.config.Cache:
|
||||
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):
|
||||
if self.library.is_movie:
|
||||
if isinstance(plex_item, Movie):
|
||||
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
|
||||
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
|
||||
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:
|
||||
|
@ -97,7 +97,7 @@ class Overlays:
|
|||
return self.config.TMDb.get_episode(tmdb_id, plex_item.seasonNumber, plex_item.episodeNumber).still_url
|
||||
|
||||
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()
|
||||
if self.library.is_show:
|
||||
|
@ -129,102 +129,99 @@ class Overlays:
|
|||
poster_location = find_poster_url(item)
|
||||
if poster_location:
|
||||
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:
|
||||
os.remove(original)
|
||||
else:
|
||||
logger.error(f"No Poster found to restore for {item.title}")
|
||||
logger.exorcise()
|
||||
|
||||
if item_overlays:
|
||||
if key_to_overlays:
|
||||
logger.info("")
|
||||
logger.separator(f"Applying Overlays for the {self.library.name} Library")
|
||||
logger.info("")
|
||||
for i, (over_key, (item, over_names)) in enumerate(sorted(key_to_overlays.items(), key=lambda io: io[1][0].title), 1):
|
||||
try:
|
||||
logger.ghost(f"Overlaying: {i}/{len(key_to_overlays)} {item.title}")
|
||||
image_compare = None
|
||||
overlay_compare = None
|
||||
if self.config.Cache:
|
||||
image, image_compare, _ = self.config.Cache.query_image_map(item.ratingKey, f"{self.library.image_table_name}_overlays")
|
||||
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])
|
||||
|
||||
for i, (over_key, over_names) in enumerate(item_overlays.items(), 1):
|
||||
try:
|
||||
item = item_keys[over_key]
|
||||
logger.ghost(f"Overlaying: {i}/{len(item_overlays)} {item.title}")
|
||||
image_compare = None
|
||||
overlay_compare = None
|
||||
if self.config.Cache:
|
||||
image, image_compare, _ = self.config.Cache.query_image_map(item.ratingKey, f"{self.library.image_table_name}_overlays")
|
||||
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:
|
||||
for oc in overlay_compare:
|
||||
if oc not in over_names:
|
||||
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
|
||||
|
||||
overlay_change = False if has_overlay else True
|
||||
if not overlay_change:
|
||||
for oc in overlay_compare:
|
||||
if oc not in over_names:
|
||||
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 "
|
||||
)
|
||||
|
||||
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")
|
||||
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)
|
||||
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
|
||||
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:
|
||||
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"])
|
||||
self.library.reload(item)
|
||||
poster_uploaded = True
|
||||
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}")
|
||||
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:
|
||||
if poster_uploaded:
|
||||
self.config.Cache.update_image_map(
|
||||
item.ratingKey, self.library.image_table_name, item.thumb,
|
||||
poster.compare if poster else item.thumb, overlay=','.join(over_names)
|
||||
)
|
||||
except Failed as e:
|
||||
logger.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()
|
||||
|
|
|
@ -293,7 +293,7 @@ def update_libraries(config):
|
|||
if not config.library_first and not config.test_mode and not collection_only:
|
||||
if not overlays_only and library.library_operation:
|
||||
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()
|
||||
|
||||
logger.remove_library_handler(library.mapping_name)
|
||||
|
|
Loading…
Reference in a new issue