From f33a2df5f0ce958c129f0d8a3d8281f1ab0a154e Mon Sep 17 00:00:00 2001 From: meisnate12 Date: Sat, 18 Dec 2021 19:48:11 -0500 Subject: [PATCH] #513 added dimensional_asset_rename to autoname asset files --- modules/builder.py | 4 +-- modules/config.py | 2 ++ modules/library.py | 44 ++----------------------------- modules/plex.py | 63 +++++++++++++++++++++++++++++++++----------- plex_meta_manager.py | 5 ++-- 5 files changed, 56 insertions(+), 62 deletions(-) diff --git a/modules/builder.py b/modules/builder.py index d51eaa2c..42d11c77 100644 --- a/modules/builder.py +++ b/modules/builder.py @@ -1990,7 +1990,7 @@ class CollectionBuilder: rating_keys.remove(int(item.ratingKey)) if "item_assets" in self.item_details or overlay is not None: try: - self.library.update_item_from_assets(item, overlay=overlay) + self.library.find_assets(item, name=overlay) except Failed as e: logger.error(e) self.library.edit_tags("label", item, add_tags=add_tags, remove_tags=remove_tags, sync_tags=sync_tags) @@ -2176,7 +2176,7 @@ class CollectionBuilder: if "name_mapping" in self.details: if self.details["name_mapping"]: name_mapping = self.details["name_mapping"] else: logger.error(f"{self.Type} Error: name_mapping attribute is blank") - poster_image, background_image = self.library.find_collection_assets(self.obj, name=name_mapping) + poster_image, background_image = self.library.find_assets(self.obj, name=name_mapping, upload=False) if poster_image: self.posters["asset_directory"] = poster_image if background_image: diff --git a/modules/config.py b/modules/config.py index 58d569d6..3d156765 100644 --- a/modules/config.py +++ b/modules/config.py @@ -223,6 +223,7 @@ class ConfigFile: "asset_folders": check_for_attribute(self.data, "asset_folders", parent="settings", var_type="bool", default=True), "asset_depth": check_for_attribute(self.data, "asset_depth", parent="settings", var_type="int", default=0), "create_asset_folders": check_for_attribute(self.data, "create_asset_folders", parent="settings", var_type="bool", default=False), + "dimensional_asset_rename": check_for_attribute(self.data, "dimensional_asset_rename", parent="settings", var_type="bool", default=False), "show_missing_season_assets": check_for_attribute(self.data, "show_missing_season_assets", parent="settings", var_type="bool", default=False), "sync_mode": check_for_attribute(self.data, "sync_mode", parent="settings", default="append", test_list=sync_modes), "collection_minimum": check_for_attribute(self.data, "collection_minimum", parent="settings", var_type="int", default=1), @@ -505,6 +506,7 @@ class ConfigFile: params["missing_only_released"] = check_for_attribute(lib, "missing_only_released", parent="settings", var_type="bool", default=self.general["missing_only_released"], do_print=False, save=False) params["only_filter_missing"] = check_for_attribute(lib, "only_filter_missing", parent="settings", var_type="bool", default=self.general["only_filter_missing"], do_print=False, save=False) params["create_asset_folders"] = check_for_attribute(lib, "create_asset_folders", parent="settings", var_type="bool", default=self.general["create_asset_folders"], do_print=False, save=False) + params["dimensional_asset_rename"] = check_for_attribute(lib, "dimensional_asset_rename", parent="settings", var_type="bool", default=self.general["dimensional_asset_rename"], do_print=False, save=False) params["show_missing_season_assets"] = check_for_attribute(lib, "show_missing_season_assets", parent="settings", var_type="bool", default=self.general["show_missing_season_assets"], do_print=False, save=False) params["collection_minimum"] = check_for_attribute(lib, "collection_minimum", parent="settings", var_type="int", default=self.general["collection_minimum"], do_print=False, save=False) params["delete_below_minimum"] = check_for_attribute(lib, "delete_below_minimum", parent="settings", var_type="bool", default=self.general["delete_below_minimum"], do_print=False, save=False) diff --git a/modules/library.py b/modules/library.py index 87d8afc0..8ae65f2e 100644 --- a/modules/library.py +++ b/modules/library.py @@ -2,7 +2,7 @@ import logging, os, requests, shutil, time from abc import ABC, abstractmethod from modules import util from modules.meta import MetadataFile -from modules.util import Failed, ImageData +from modules.util import Failed from PIL import Image from ruamel import yaml @@ -43,6 +43,7 @@ class Library(ABC): self.missing_path = os.path.join(self.default_dir, f"{self.mapping_name}_missing.yml") self.asset_folders = params["asset_folders"] self.create_asset_folders = params["create_asset_folders"] + self.dimensional_asset_rename = params["dimensional_asset_rename"] self.show_missing_season_assets = params["show_missing_season_assets"] self.sync_mode = params["sync_mode"] self.collection_minimum = params["collection_minimum"] @@ -253,44 +254,3 @@ class Library(ABC): logger.info("") logger.info(util.adjust_space(f"Processed {len(items)} {self.type}s")) return items - - def find_collection_assets(self, item, name=None, create=False): - if name is None: - name = item.title - found_folder = False - poster = None - background = None - for ad in self.asset_directory: - item_dir = None - if self.asset_folders: - if os.path.isdir(os.path.join(ad, name)): - item_dir = os.path.join(ad, name) - else: - for n in range(1, self.asset_depth + 1): - new_path = ad - for i in range(1, n + 1): - new_path = os.path.join(new_path, "*") - matches = util.glob_filter(os.path.join(new_path, name)) - if len(matches) > 0: - item_dir = os.path.abspath(matches[0]) - break - if item_dir is None: - continue - found_folder = True - poster_filter = os.path.join(item_dir, "poster.*") - background_filter = os.path.join(item_dir, "background.*") - else: - poster_filter = os.path.join(ad, f"{name}.*") - background_filter = os.path.join(ad, f"{name}_background.*") - matches = util.glob_filter(poster_filter) - if len(matches) > 0: - poster = ImageData("asset_directory", os.path.abspath(matches[0]), prefix=f"{item.title}'s ", is_url=False) - matches = util.glob_filter(background_filter) - if len(matches) > 0: - background = ImageData("asset_directory", os.path.abspath(matches[0]), prefix=f"{item.title}'s ", is_poster=False, is_url=False) - if poster or background: - return poster, background - if create and self.asset_folders and not found_folder: - os.makedirs(os.path.join(self.asset_directory[0], name), exist_ok=True) - logger.info(f"Asset Directory Created: {os.path.join(self.asset_directory[0], name)}") - return None, None diff --git a/modules/plex.py b/modules/plex.py index bc38fa3a..29240d79 100644 --- a/modules/plex.py +++ b/modules/plex.py @@ -2,11 +2,13 @@ import logging, os, plexapi, requests from modules import builder, util from modules.library import Library from modules.util import Failed, ImageData +from PIL import Image from plexapi import utils from plexapi.exceptions import BadRequest, NotFound, Unauthorized from plexapi.collection import Collection from plexapi.playlist import Playlist from plexapi.server import PlexServer +from plexapi.video import Movie, Show from retrying import retry from urllib import parse from xml.etree.ElementTree import ParseError @@ -643,8 +645,15 @@ class Plex(Library): logger.info(f"{obj.title[:25]:<25} | {attr.capitalize()} | {display}") return len(display) > 0 - def update_item_from_assets(self, item, overlay=None, create=False): - name = os.path.basename(os.path.dirname(str(item.locations[0])) if self.is_movie else str(item.locations[0])) + def find_assets(self, item, name=None, upload=True): + if isinstance(item, Movie): + name = os.path.basename(os.path.dirname(str(item.locations[0]))) + elif isinstance(item, Show): + name = os.path.basename(str(item.locations[0])) + elif isinstance(item, Collection): + name = name if name else item.title + else: + return None, None found_folder = False poster = None background = None @@ -670,15 +679,38 @@ class Plex(Library): else: poster_filter = os.path.join(ad, f"{name}.*") background_filter = os.path.join(ad, f"{name}_background.*") - matches = util.glob_filter(poster_filter) - if len(matches) > 0: - poster = ImageData("asset_directory", os.path.abspath(matches[0]), prefix=f"{item.title}'s ", is_url=False) - matches = util.glob_filter(background_filter) - if len(matches) > 0: - background = ImageData("asset_directory", os.path.abspath(matches[0]), prefix=f"{item.title}'s ", is_poster=False, is_url=False) + + poster_matches = util.glob_filter(poster_filter) + if len(poster_matches) > 0: + poster = ImageData("asset_directory", os.path.abspath(poster_matches[0]), prefix=f"{item.title}'s ", is_url=False) + + background_matches = util.glob_filter(background_filter) + if len(background_matches) > 0: + background = ImageData("asset_directory", os.path.abspath(background_matches[0]), prefix=f"{item.title}'s ", is_poster=False, is_url=False) + + if item_dir and self.dimensional_asset_rename and (not poster or not background): + for file in util.glob_filter(os.path.join(item_dir, "*.*")): + if file.lower().endswith((".jpg", ".png", ".jpeg")): + image = Image.open(poster) + _w, _h = image.size + image.close() + if not poster and _h > _w: + new_path = os.path.join(os.path.dirname(file), f"poster{os.path.splitext(file)[1].lower()}") + os.rename(file, new_path) + poster = ImageData("asset_directory", os.path.abspath(new_path), prefix=f"{item.title}'s ", is_url=False) + elif not background and _w > _h: + new_path = os.path.join(os.path.dirname(file), f"background{os.path.splitext(file)[1].lower()}") + os.rename(file, new_path) + background = ImageData("asset_directory", os.path.abspath(new_path), prefix=f"{item.title}'s ", is_poster=False, is_url=False) + if poster and background: + break + if poster or background: - self.upload_images(item, poster=poster, background=background, overlay=overlay) - if self.is_show: + if upload: + self.upload_images(item, poster=poster, background=background, overlay=name) + else: + return poster, background + if isinstance(item, Show): missing_assets = "" found_season = False for season in self.query(item.seasons): @@ -713,12 +745,13 @@ class Plex(Library): self.upload_images(episode, poster=episode_poster) if self.show_missing_season_assets and found_season and missing_assets: util.print_multiline(f"Missing Season Posters for {item.title}{missing_assets}", info=True) - if not poster and overlay: - self.upload_images(item, overlay=overlay) - if create and self.asset_folders and not found_folder: + if isinstance(item, (Movie, Show)) and not poster and name: + self.upload_images(item, overlay=name) + if self.create_asset_folders and self.asset_folders and not found_folder: os.makedirs(os.path.join(self.asset_directory[0], name), exist_ok=True) logger.info(f"Asset Directory Created: {os.path.join(self.asset_directory[0], name)}") - elif not overlay and self.asset_folders and not found_folder: + elif isinstance(item, (Movie, Show)) and not name and self.asset_folders and not found_folder: logger.error(f"Asset Warning: No asset folder found called '{name}'") - elif not poster and not background and self.show_missing_assets: + elif isinstance(item, (Movie, Show)) and not poster and not background and self.show_missing_assets: logger.error(f"Asset Warning: No poster or background found in an assets folder for '{name}'") + return None, None diff --git a/plex_meta_manager.py b/plex_meta_manager.py index bc264af1..ca18a372 100644 --- a/plex_meta_manager.py +++ b/plex_meta_manager.py @@ -686,7 +686,7 @@ def library_operations(config, library): continue util.print_return(f"Processing: {i}/{len(items)} {item.title}") if library.assets_for_all: - library.update_item_from_assets(item, create=library.create_asset_folders) + library.find_assets(item) tmdb_id = None tvdb_id = None imdb_id = None @@ -910,8 +910,7 @@ def library_operations(config, library): util.separator(f"Unmanaged Collection Assets Check for {library.name} Library", space=False, border=False) logger.info("") for col in unmanaged_collections: - poster, background = library.find_collection_assets(col, create=library.create_asset_folders) - library.upload_images(col, poster=poster, background=background) + library.find_assets(col) def run_collection(config, library, metadata, requested_collections): global stats