fixed detect image changes

This commit is contained in:
meisnate12 2021-06-12 11:29:17 -04:00
parent c6c0429fb3
commit 7e55107d36
5 changed files with 118 additions and 74 deletions

View file

@ -1,7 +1,7 @@
import logging, os, re
from datetime import datetime, timedelta
from modules import anidb, anilist, imdb, letterboxd, mal, plex, radarr, sonarr, tautulli, tmdb, trakttv, tvdb, util
from modules.util import Failed
from modules.util import Failed, Image
from plexapi.exceptions import BadRequest, NotFound
from plexapi.video import Movie, Show
from urllib.parse import quote
@ -1742,42 +1742,47 @@ class CollectionBuilder:
for p in self.posters:
logger.info(f"Method: {p} Poster: {self.posters[p]}")
if "url_poster" in self.posters: self.library.upload_image("url_poster", self.obj, self.posters["url_poster"])
elif "file_poster" in self.posters: self.library.upload_image("file_poster", self.obj, self.posters["file_poster"], url=False)
elif "tmdb_poster" in self.posters: self.library.upload_image("tmdb_poster", self.obj, self.posters["tmdb_poster"])
elif "tmdb_profile" in self.posters: self.library.upload_image("tmdb_poster", self.obj, self.posters["tmdb_profile"])
elif "tvdb_poster" in self.posters: self.library.upload_image("tvdb_poster", self.obj, self.posters["tvdb_poster"])
elif "asset_directory" in self.posters: self.library.upload_image("asset_directory", self.obj, self.posters["asset_directory"], url=False)
elif "tmdb_person" in self.posters: self.library.upload_image("tmdb_person", self.obj, self.posters["tmdb_person"])
elif "tmdb_collection_details" in self.posters: self.library.upload_image("tmdb_collection_details", self.obj, self.posters["tmdb_collection_details"])
elif "tmdb_actor_details" in self.posters: self.library.upload_image("tmdb_actor_details", self.obj, self.posters["tmdb_actor_details"])
elif "tmdb_crew_details" in self.posters: self.library.upload_image("tmdb_crew_details", self.obj, self.posters["tmdb_crew_details"])
elif "tmdb_director_details" in self.posters: self.library.upload_image("tmdb_director_details", self.obj, self.posters["tmdb_director_details"])
elif "tmdb_producer_details" in self.posters: self.library.upload_image("tmdb_producer_details", self.obj, self.posters["tmdb_producer_details"])
elif "tmdb_writer_details" in self.posters: self.library.upload_image("tmdb_writer_details", self.obj, self.posters["tmdb_writer_details"])
elif "tmdb_movie_details" in self.posters: self.library.upload_image("tmdb_movie_details", self.obj, self.posters["tmdb_movie_details"])
elif "tvdb_movie_details" in self.posters: self.library.upload_image("tvdb_movie_details", self.obj, self.posters["tvdb_movie_details"])
elif "tvdb_show_details" in self.posters: self.library.upload_image("tvdb_show_details", self.obj, self.posters["tvdb_show_details"])
elif "tmdb_show_details" in self.posters: self.library.upload_image("tmdb_show_details", self.obj, self.posters["tmdb_show_details"])
else: logger.info("No poster to update")
if len(self.backgrounds) > 1:
logger.info(f"{len(self.backgrounds)} backgrounds found:")
for b in self.backgrounds:
logger.info(f"Method: {b} Background: {self.backgrounds[b]}")
if "url_background" in self.backgrounds: self.library.upload_image("url_background", self.obj, self.backgrounds["url_background"], poster=False)
elif "file_background" in self.backgrounds: self.library.upload_image("file_background", self.obj, self.backgrounds["file_background"], poster=False, url=False)
elif "tmdb_background" in self.backgrounds: self.library.upload_image("tmdb_background", self.obj, self.backgrounds["tmdb_background"], poster=False)
elif "tvdb_background" in self.backgrounds: self.library.upload_image("tvdb_background", self.obj, self.backgrounds["tvdb_background"], poster=False)
elif "asset_directory" in self.backgrounds: self.library.upload_image("asset_directory", self.obj, self.backgrounds["asset_directory"], poster=False, url=False)
elif "tmdb_collection_details" in self.backgrounds: self.library.upload_image("tmdb_collection_details", self.obj, self.backgrounds["tmdb_collection_details"], poster=False)
elif "tmdb_movie_details" in self.backgrounds: self.library.upload_image("tmdb_movie_details", self.obj, self.backgrounds["tmdb_movie_details"], poster=False)
elif "tvdb_movie_details" in self.backgrounds: self.library.upload_image("tvdb_movie_details", self.obj, self.backgrounds["tvdb_movie_details"], poster=False)
elif "tvdb_show_details" in self.backgrounds: self.library.upload_image("tvdb_show_details", self.obj, self.backgrounds["tvdb_show_details"], poster=False)
elif "tmdb_show_details" in self.backgrounds: self.library.upload_image("tmdb_show_details", self.obj, self.backgrounds["tmdb_show_details"], poster=False)
poster = None
if "url_poster" in self.posters: poster = Image("url_poster", self.posters["url_poster"])
elif "file_poster" in self.posters: poster = Image("file_poster", self.posters["file_poster"], is_url=False)
elif "tmdb_poster" in self.posters: poster = Image("tmdb_poster", self.posters["tmdb_poster"])
elif "tmdb_profile" in self.posters: poster = Image("tmdb_poster", self.posters["tmdb_profile"])
elif "tvdb_poster" in self.posters: poster = Image("tvdb_poster", self.posters["tvdb_poster"])
elif "asset_directory" in self.posters: poster = Image("asset_directory", self.posters["asset_directory"], is_url=False)
elif "tmdb_person" in self.posters: poster = Image("tmdb_person", self.posters["tmdb_person"])
elif "tmdb_collection_details" in self.posters: poster = Image("tmdb_collection_details", self.posters["tmdb_collection_details"])
elif "tmdb_actor_details" in self.posters: poster = Image("tmdb_actor_details", self.posters["tmdb_actor_details"])
elif "tmdb_crew_details" in self.posters: poster = Image("tmdb_crew_details", self.posters["tmdb_crew_details"])
elif "tmdb_director_details" in self.posters: poster = Image("tmdb_director_details", self.posters["tmdb_director_details"])
elif "tmdb_producer_details" in self.posters: poster = Image("tmdb_producer_details", self.posters["tmdb_producer_details"])
elif "tmdb_writer_details" in self.posters: poster = Image("tmdb_writer_details", self.posters["tmdb_writer_details"])
elif "tmdb_movie_details" in self.posters: poster = Image("tmdb_movie_details", self.posters["tmdb_movie_details"])
elif "tvdb_movie_details" in self.posters: poster = Image("tvdb_movie_details", self.posters["tvdb_movie_details"])
elif "tvdb_show_details" in self.posters: poster = Image("tvdb_show_details", self.posters["tvdb_show_details"])
elif "tmdb_show_details" in self.posters: poster = Image("tmdb_show_details", self.posters["tmdb_show_details"])
else: logger.info("No poster to update")
background = None
if "url_background" in self.backgrounds: background = Image("url_background", self.backgrounds["url_background"], is_poster=False)
elif "file_background" in self.backgrounds: background = Image("file_background", self.backgrounds["file_background"], is_poster=False, is_url=False)
elif "tmdb_background" in self.backgrounds: background = Image("tmdb_background", self.backgrounds["tmdb_background"], is_poster=False)
elif "tvdb_background" in self.backgrounds: background = Image("tvdb_background", self.backgrounds["tvdb_background"], is_poster=False)
elif "asset_directory" in self.backgrounds: background = Image("asset_directory", self.backgrounds["asset_directory"], is_poster=False, is_url=False)
elif "tmdb_collection_details" in self.backgrounds: background = Image("tmdb_collection_details", self.backgrounds["tmdb_collection_details"], is_poster=False)
elif "tmdb_movie_details" in self.backgrounds: background = Image("tmdb_movie_details", self.backgrounds["tmdb_movie_details"], is_poster=False)
elif "tvdb_movie_details" in self.backgrounds: background = Image("tvdb_movie_details", self.backgrounds["tvdb_movie_details"], is_poster=False)
elif "tvdb_show_details" in self.backgrounds: background = Image("tvdb_show_details", self.backgrounds["tvdb_show_details"], is_poster=False)
elif "tmdb_show_details" in self.backgrounds: background = Image("tmdb_show_details", self.backgrounds["tmdb_show_details"], is_poster=False)
else: logger.info("No background to update")
if poster or background:
self.library.upload_images(self.obj, poster=poster, background=background)
def run_collections_again(self):
self.obj = self.library.get_collection(self.name)
name, collection_items = self.library.get_collection_name_and_items(self.obj, self.smart_label_collection)

View file

@ -246,5 +246,5 @@ class Cache:
with sqlite3.connect(self.cache_path) as connection:
connection.row_factory = sqlite3.Row
with closing(connection.cursor()) as cursor:
cursor.execute("INSERT OR IGNORE INTO image_map(rating_key, library) VALUES(?, ?)", (rating_key, library))
cursor.execute("INSERT OR IGNORE INTO image_map(rating_key, library, type) VALUES(?, ?, ?)", (rating_key, library, image_type))
cursor.execute("UPDATE image_map SET location = ?, compare = ? WHERE rating_key = ? AND library = ? AND type = ?", (location, compare, rating_key, library, image_type))

View file

@ -1,7 +1,7 @@
import logging, os, re, requests
from datetime import datetime
from modules import plex, util
from modules.util import Failed
from modules.util import Failed, Image
from plexapi.exceptions import NotFound
from ruamel import yaml
@ -141,21 +141,26 @@ class Metadata:
return self.library.edit_tags(attr, obj, add_tags=add_tags, remove_tags=remove_tags, sync_tags=sync_tags)
return False
def set_image(attr, obj, group, alias, poster=True, url=True):
def set_image(attr, group, alias, is_poster=True, is_url=True):
if group[alias[attr]]:
self.library.upload_image(attr, obj, group[alias[attr]], poster=poster, url=url)
return Image(attr, group[alias[attr]], is_poster=is_poster, is_url=is_url)
else:
logger.error(f"Metadata Error: {attr} attribute is blank")
def set_images(obj, group, alias):
poster = None
background = None
if "url_poster" in alias:
set_image("url_poster", obj, group, alias)
poster = set_image("url_poster", group, alias)
elif "file_poster" in alias:
set_image("file_poster", obj, group, alias, url=False)
poster = set_image("file_poster", group, alias, is_url=False)
if "url_background" in alias:
set_image("url_background", obj, group, alias, poster=False)
background = set_image("url_background", group, alias, is_poster=False)
elif "file_background" in alias:
set_image("file_background", obj, group, alias, poster=False, url=False)
background = set_image("file_background", group, alias, is_poster=False, is_url=False)
if poster or background:
self.library.upload_images(obj, poster=poster, background=background)
logger.info("")
util.separator()

View file

@ -1,7 +1,7 @@
import glob, logging, os, requests
from modules import builder, util
from modules.meta import Metadata
from modules.util import Failed
from modules.util import Failed, Image
import plexapi
from plexapi import utils
from plexapi.exceptions import BadRequest, NotFound, Unauthorized
@ -426,39 +426,59 @@ class PlexAPI:
self.reload(item)
@retry(stop_max_attempt_number=6, wait_fixed=10000, retry_on_exception=util.retry_if_not_plex)
def _upload_image(self, item, location, poster=True, url=True):
if poster and url:
item.uploadPoster(url=location)
elif poster:
item.uploadPoster(filepath=location)
elif url:
item.uploadArt(url=location)
def _upload_image(self, item, image):
if image.is_poster and image.is_url:
item.uploadPoster(url=image.location)
elif image.is_poster:
item.uploadPoster(filepath=image.location)
elif image.is_url:
item.uploadArt(url=image.location)
else:
item.uploadArt(filepath=location)
item.uploadArt(filepath=image.location)
self.reload(item)
def upload_image(self, attr, item, location, name="", poster=True, url=True):
image_type = "poster" if poster else "background"
message = f"{name}{image_type} to [{'URL' if url else 'File'}] {location}"
def upload_images(self, item, poster=None, background=None):
poster_uploaded = False
if poster is not None:
try:
image = None
if self.config.Cache:
image, image_compare = self.config.Cache.query_image_map(item.ratingKey, self.original_mapping_name, image_type)
compare = location if url else os.stat(location).st_size
if compare != image_compare:
image, image_compare = self.config.Cache.query_image_map(item.ratingKey, self.original_mapping_name, "poster")
if str(poster.compare) != str(image_compare):
image = None
if image is None \
or (image_type == "poster" and image != item.thumb) \
or (image_type == "background" and image != item.art):
self._upload_image(item, location, poster=poster, url=url)
if self.config.Cache:
self.reload(item)
self.config.Cache.update_image_map(item.ratingKey, self.original_mapping_name, image_type, item.thumb if image_type == "poster" else item.art, compare)
logger.info(f"Detail: {attr} updated {message}")
if image is None or image != item.thumb:
self._upload_image(item, poster)
poster_uploaded = True
logger.info(f"Detail: {poster.attribute} updated {poster.message}")
else:
logger.info(f"Detail: {name}{image_type} update not needed")
logger.info(f"Detail: {poster.prefix}poster update not needed")
except BadRequest:
util.print_stacktrace()
logger.error(f"Detail: {attr} failed to update {message}")
logger.error(f"Detail: {poster.attribute} failed to update {poster.message}")
background_uploaded = False
if background is not None:
try:
image = None
if self.config.Cache:
image, image_compare = self.config.Cache.query_image_map(item.ratingKey, self.original_mapping_name, "background")
if str(background.compare) != str(image_compare):
image = None
if image is None or image != item.art:
self._upload_image(item, background)
background_uploaded = True
logger.info(f"Detail: {background.attribute} updated {background.message}")
else:
logger.info(f"Detail: {background.prefix}background update not needed")
except BadRequest:
util.print_stacktrace()
logger.error(f"Detail: {background.attribute} failed to update {background.message}")
if self.config.Cache:
if poster_uploaded:
self.config.Cache.update_image_map(item.ratingKey, self.original_mapping_name, "poster", item.thumb, poster.compare)
if background_uploaded:
self.config.Cache.update_image_map(item.ratingKey, self.original_mapping_name, "background", item.art, background.compare)
@retry(stop_max_attempt_number=6, wait_fixed=10000, retry_on_exception=util.retry_if_not_failed)
def get_search_choices(self, search_name, title=True):
@ -736,6 +756,8 @@ class PlexAPI:
elif not name:
name = os.path.basename(os.path.dirname(item.locations[0]) if self.is_movie else item.locations[0])
for ad in dirs:
poster = None
background = None
poster_image = None
background_image = None
if self.asset_folders:
@ -750,12 +772,14 @@ class PlexAPI:
if len(matches) > 0:
poster_image = os.path.abspath(matches[0])
if upload:
self.upload_image("asset_directory", item, poster_image, name=f"{item.title}'s ", url=False)
poster = Image("asset_directory", poster_image, prefix=f"{item.title}'s ", is_url=False)
matches = glob.glob(background_filter)
if len(matches) > 0:
background_image = os.path.abspath(matches[0])
if upload:
self.upload_image("asset_directory", item, background_image, name=f"{item.title}'s ", poster=False, url=False)
background = Image("asset_directory", background_image, prefix=f"{item.title}'s ", is_poster=False, is_url=False)
if poster or background:
self.upload_images(item, poster=poster, background=background)
if collection_mode:
for ite in self.query(item.items):
self.update_item_from_assets(ite, dirs=[os.path.join(ad, name)])
@ -770,7 +794,7 @@ class PlexAPI:
matches = glob.glob(season_filter)
if len(matches) > 0:
season_path = os.path.abspath(matches[0])
self.upload_image("asset_directory", season, season_path, name=f"{item.title} Season {season.seasonNumber}'s ", url=False)
self.upload_images(season, poster=Image("asset_directory", season_path, prefix=f"{item.title} Season {season.seasonNumber}'s ", is_url=False))
for episode in self.query(season.episodes):
if self.asset_folders:
episode_filter = os.path.join(ad, name, f"{episode.seasonEpisode.upper()}.*")
@ -779,5 +803,5 @@ class PlexAPI:
matches = glob.glob(episode_filter)
if len(matches) > 0:
episode_path = os.path.abspath(matches[0])
self.upload_image("asset_directory", episode, episode_path, name=f"{item.title} {episode.seasonEpisode.upper()}'s ", url=False)
self.upload_images(episode, poster=Image("asset_directory", episode_path, prefix=f"{item.title} {episode.seasonEpisode.upper()}'s ", is_url=False))
return None, None

View file

@ -1,4 +1,4 @@
import logging, re, signal, sys, time, traceback
import logging, os, re, signal, sys, time, traceback
from datetime import datetime
from pathvalidate import is_valid_filename, sanitize_filename
from plexapi.exceptions import BadRequest, NotFound, Unauthorized
@ -18,6 +18,16 @@ class TimeoutExpired(Exception):
class Failed(Exception):
pass
class Image:
def __init__(self, attribute, location, prefix="", is_poster=True, is_url=True):
self.attribute = attribute
self.location = location
self.prefix = prefix
self.is_poster = is_poster
self.is_url = is_url
self.compare = location if is_url else os.stat(location).st_size
self.message = f"{prefix}{'poster' if is_poster else 'background'} to [{'URL' if is_url else 'File'}] {location}"
def retry_if_not_failed(exception):
return not isinstance(exception, Failed)