fixed detect image changes

pull/309/head
meisnate12 4 years ago
parent c6c0429fb3
commit 7e55107d36

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

@ -246,5 +246,5 @@ class Cache:
with sqlite3.connect(self.cache_path) as connection: with sqlite3.connect(self.cache_path) as connection:
connection.row_factory = sqlite3.Row connection.row_factory = sqlite3.Row
with closing(connection.cursor()) as cursor: 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)) cursor.execute("UPDATE image_map SET location = ?, compare = ? WHERE rating_key = ? AND library = ? AND type = ?", (location, compare, rating_key, library, image_type))

@ -1,7 +1,7 @@
import logging, os, re, requests import logging, os, re, requests
from datetime import datetime from datetime import datetime
from modules import plex, util from modules import plex, util
from modules.util import Failed from modules.util import Failed, Image
from plexapi.exceptions import NotFound from plexapi.exceptions import NotFound
from ruamel import yaml 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 self.library.edit_tags(attr, obj, add_tags=add_tags, remove_tags=remove_tags, sync_tags=sync_tags)
return False 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]]: 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: else:
logger.error(f"Metadata Error: {attr} attribute is blank") logger.error(f"Metadata Error: {attr} attribute is blank")
def set_images(obj, group, alias): def set_images(obj, group, alias):
poster = None
background = None
if "url_poster" in alias: if "url_poster" in alias:
set_image("url_poster", obj, group, alias) poster = set_image("url_poster", group, alias)
elif "file_poster" in 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: 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: 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("") logger.info("")
util.separator() util.separator()

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

@ -1,4 +1,4 @@
import logging, re, signal, sys, time, traceback import logging, os, re, signal, sys, time, traceback
from datetime import datetime from datetime import datetime
from pathvalidate import is_valid_filename, sanitize_filename from pathvalidate import is_valid_filename, sanitize_filename
from plexapi.exceptions import BadRequest, NotFound, Unauthorized from plexapi.exceptions import BadRequest, NotFound, Unauthorized
@ -18,6 +18,16 @@ class TimeoutExpired(Exception):
class Failed(Exception): class Failed(Exception):
pass 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): def retry_if_not_failed(exception):
return not isinstance(exception, Failed) return not isinstance(exception, Failed)

Loading…
Cancel
Save