Commit 4afc2cc3 authored by echel0n's avatar echel0n
Browse files

Added app caching of episode images retrieved from series providers

Limited `SEARCH_QUEUE_STATUS_UPDATED` websocket updates to manual searches
Added de-composited status and quality props to episode object json data
Added V2 API endpoint for episode statuses
Added V2 API endpoint for series search formats
Refactored pausing a show to only pause searches and downloads, shows will now continue to get updates from series providers
parent 45553730
...@@ -56,23 +56,49 @@ class ImageCache(object): ...@@ -56,23 +56,49 @@ class ImageCache(object):
""" """
return os.path.abspath(os.path.join(sickrage.app.cache_dir, 'images')) return os.path.abspath(os.path.join(sickrage.app.cache_dir, 'images'))
def _cache_series_dir(self, series_id):
"""
Builds up the full path to the image cache directory
"""
return os.path.abspath(os.path.join(self._cache_dir(), 'series', str(series_id)))
def _cache_seasons_dir(self, series_id):
"""
Builds up the full path to the image cache directory
"""
return os.path.abspath(os.path.join(self._cache_series_dir(series_id), 'seasons'))
def _cache_episodes_dir(self, series_id):
"""
Builds up the full path to the image cache directory
"""
return os.path.abspath(os.path.join(self._cache_series_dir(series_id), 'episodes'))
def _thumbnails_dir(self): def _thumbnails_dir(self):
""" """
Builds up the full path to the thumbnails image cache directory Builds up the full path to the thumbnails image cache directory
""" """
return os.path.abspath(os.path.join(self._cache_dir(), 'thumbnails')) return os.path.abspath(os.path.join(self._cache_dir(), 'thumbnails'))
def poster_path(self, series_id): def poster_path(self, series_id, season_id=None, episode_id=None):
""" """
Builds up the path to a poster cache for a given series id Builds up the path to a poster cache for a given series id
:param series_id: ID of the show to use in the file name :param series_id: ID of the show to use in the file name
:return: a full path to the cached poster file for the given series id :return: a full path to the cached poster file for the given series id
""" """
poster_file_name = str(series_id) + '.poster.jpg' if episode_id:
return os.path.join(self._cache_dir(), poster_file_name) poster_file_name = str(episode_id) + '.poster.jpg'
return os.path.join(self._cache_episodes_dir(series_id), poster_file_name)
elif season_id:
poster_file_name = str(season_id) + '.poster.jpg'
return os.path.join(self._cache_seasons_dir(series_id), poster_file_name)
else:
poster_file_name = str(series_id) + '.poster.jpg'
return os.path.join(self._cache_dir(), poster_file_name)
def banner_path(self, series_id): def banner_path(self, series_id, season_id=None, episode_id=None):
""" """
Builds up the path to a banner cache for a given series id Builds up the path to a banner cache for a given series id
...@@ -82,7 +108,7 @@ class ImageCache(object): ...@@ -82,7 +108,7 @@ class ImageCache(object):
banner_file_name = str(series_id) + '.banner.jpg' banner_file_name = str(series_id) + '.banner.jpg'
return os.path.join(self._cache_dir(), banner_file_name) return os.path.join(self._cache_dir(), banner_file_name)
def fanart_path(self, series_id): def fanart_path(self, series_id, season_id=None, episode_id=None):
""" """
Builds up the path to a fanart cache for a given series id Builds up the path to a fanart cache for a given series id
...@@ -92,7 +118,7 @@ class ImageCache(object): ...@@ -92,7 +118,7 @@ class ImageCache(object):
fanart_file_name = str(series_id) + '.fanart.jpg' fanart_file_name = str(series_id) + '.fanart.jpg'
return os.path.join(self._cache_dir(), fanart_file_name) return os.path.join(self._cache_dir(), fanart_file_name)
def fanart_thumb_path(self, series_id): def fanart_thumb_path(self, series_id, season_id=None, episode_id=None):
""" """
Builds up the path to a poster thumb cache for a given series id Builds up the path to a poster thumb cache for a given series id
...@@ -102,7 +128,7 @@ class ImageCache(object): ...@@ -102,7 +128,7 @@ class ImageCache(object):
fanartthumb_file_name = str(series_id) + '.fanart.jpg' fanartthumb_file_name = str(series_id) + '.fanart.jpg'
return os.path.join(self._thumbnails_dir(), fanartthumb_file_name) return os.path.join(self._thumbnails_dir(), fanartthumb_file_name)
def poster_thumb_path(self, series_id): def poster_thumb_path(self, series_id, season_id=None, episode_id=None):
""" """
Builds up the path to a poster thumb cache for a given series id Builds up the path to a poster thumb cache for a given series id
...@@ -112,7 +138,7 @@ class ImageCache(object): ...@@ -112,7 +138,7 @@ class ImageCache(object):
posterthumb_file_name = str(series_id) + '.poster.jpg' posterthumb_file_name = str(series_id) + '.poster.jpg'
return os.path.join(self._thumbnails_dir(), posterthumb_file_name) return os.path.join(self._thumbnails_dir(), posterthumb_file_name)
def banner_thumb_path(self, series_id): def banner_thumb_path(self, series_id, season_id=None, episode_id=None):
""" """
Builds up the path to a banner thumb cache for a given series id Builds up the path to a banner thumb cache for a given series id
...@@ -122,15 +148,15 @@ class ImageCache(object): ...@@ -122,15 +148,15 @@ class ImageCache(object):
bannerthumb_file_name = str(series_id) + '.banner.jpg' bannerthumb_file_name = str(series_id) + '.banner.jpg'
return os.path.join(self._thumbnails_dir(), bannerthumb_file_name) return os.path.join(self._thumbnails_dir(), bannerthumb_file_name)
def has_poster(self, series_id): def has_poster(self, series_id, season_id=None, episode_id=None):
""" """
Returns true if a cached poster exists for the given series id Returns true if a cached poster exists for the given series/season/episode id
""" """
poster_path = self.poster_path(series_id) poster_path = self.poster_path(series_id, season_id, episode_id)
sickrage.app.log.debug("Checking if file " + str(poster_path) + " exists") sickrage.app.log.debug("Checking if file " + str(poster_path) + " exists")
return os.path.isfile(poster_path) return os.path.isfile(poster_path)
def has_banner(self, series_id): def has_banner(self, series_id, season_id=None, episode_id=None):
""" """
Returns true if a cached banner exists for the given series id Returns true if a cached banner exists for the given series id
""" """
...@@ -138,7 +164,7 @@ class ImageCache(object): ...@@ -138,7 +164,7 @@ class ImageCache(object):
sickrage.app.log.debug("Checking if file " + str(banner_path) + " exists") sickrage.app.log.debug("Checking if file " + str(banner_path) + " exists")
return os.path.isfile(banner_path) return os.path.isfile(banner_path)
def has_fanart(self, series_id): def has_fanart(self, series_id, season_id=None, episode_id=None):
""" """
Returns true if a cached fanart exists for the given series id Returns true if a cached fanart exists for the given series id
""" """
...@@ -146,7 +172,7 @@ class ImageCache(object): ...@@ -146,7 +172,7 @@ class ImageCache(object):
sickrage.app.log.debug("Checking if file " + str(fanart_path) + " exists") sickrage.app.log.debug("Checking if file " + str(fanart_path) + " exists")
return os.path.isfile(fanart_path) return os.path.isfile(fanart_path)
def has_poster_thumbnail(self, series_id): def has_poster_thumbnail(self, series_id, season_id=None, episode_id=None):
""" """
Returns true if a cached poster thumbnail exists for the given series id Returns true if a cached poster thumbnail exists for the given series id
""" """
...@@ -154,7 +180,7 @@ class ImageCache(object): ...@@ -154,7 +180,7 @@ class ImageCache(object):
sickrage.app.log.debug("Checking if file " + str(poster_thumb_path) + " exists") sickrage.app.log.debug("Checking if file " + str(poster_thumb_path) + " exists")
return os.path.isfile(poster_thumb_path) return os.path.isfile(poster_thumb_path)
def has_banner_thumbnail(self, series_id): def has_banner_thumbnail(self, series_id, season_id=None, episode_id=None):
""" """
Returns true if a cached banner exists for the given series id Returns true if a cached banner exists for the given series id
""" """
...@@ -263,7 +289,7 @@ class ImageCache(object): ...@@ -263,7 +289,7 @@ class ImageCache(object):
sickrage.app.log.error("Invalid cache image type: {}".format(img_type)) sickrage.app.log.error("Invalid cache image type: {}".format(img_type))
return False return False
# retrieve the image from a series provider using the generic metadata class # retrieve series and season images from a series provider
metadata_generator = MetadataProvider() metadata_generator = MetadataProvider()
img_data = metadata_generator._retrieve_show_image(self.IMAGE_TYPES[img_type], show_obj) img_data = metadata_generator._retrieve_show_image(self.IMAGE_TYPES[img_type], show_obj)
if not img_data: if not img_data:
...@@ -273,6 +299,29 @@ class ImageCache(object): ...@@ -273,6 +299,29 @@ class ImageCache(object):
return result return result
def _cache_episode_images_from_series_provider(self, show_obj, force=False):
"""
Retrieves episode images from a series provider and saves it to the cache folder
:param show_obj: TVShow object that we want to cache an image for
:return: bool representing success
"""
metadata_generator = MetadataProvider()
# retrieve episode images from a series provider
series_provider_language = show_obj.lang or sickrage.app.config.general.series_provider_default_language
series_info = show_obj.series_provider.get_series_info(show_obj.series_id, language=series_provider_language)
if not series_info:
return False
for episode in show_obj.episodes:
series_episode = series_info[episode.season][episode.episode]
img_data = metadata_generator.get_image(series_episode.imageUrl)
if img_data:
dest_path = self.poster_path(show_obj.series_id, episode_id=series_episode.id)
metadata_generator._write_image(img_data, dest_path, force)
def fill_cache(self, show_obj, force=False): def fill_cache(self, show_obj, force=False):
""" """
Caches all images for the given show. Copies them from the show dir if possible, or Caches all images for the given show. Copies them from the show dir if possible, or
...@@ -318,18 +367,20 @@ class ImageCache(object): ...@@ -318,18 +367,20 @@ class ImageCache(object):
cur_file_type) + " needs metadata: " + str(need_images[cur_file_type])) cur_file_type) + " needs metadata: " + str(need_images[cur_file_type]))
if cur_file_type in need_images and need_images[cur_file_type]: if cur_file_type in need_images and need_images[cur_file_type]:
sickrage.app.log.debug( sickrage.app.log.debug(f"Found an image in the show dir that doesn't exist in the cache, caching it: {cur_file_name}, type {cur_file_type}")
"Found an image in the show dir that doesn't exist in the cache, caching it: " + cur_file_name + ", type " + str(
cur_file_type))
self._cache_image_from_file(cur_file_name, cur_file_type, show_obj.series_id) self._cache_image_from_file(cur_file_name, cur_file_type, show_obj.series_id)
need_images[cur_file_type] = False need_images[cur_file_type] = False
# download from a series provider for missing ones # download missing series and season images from a series provider
for cur_image_type in [self.POSTER, self.BANNER, self.POSTER_THUMB, self.BANNER_THUMB, self.FANART]: for cur_image_type in [self.POSTER, self.BANNER, self.POSTER_THUMB, self.BANNER_THUMB, self.FANART]:
sickrage.app.log.debug( sickrage.app.log.debug(f"Seeing if we still need an image of type {cur_image_type}: {need_images[cur_image_type]}")
"Seeing if we still need an image of type " + str(cur_image_type) + ": " + str(
need_images[cur_image_type]))
if cur_image_type in need_images and need_images[cur_image_type]: if cur_image_type in need_images and need_images[cur_image_type]:
self._cache_image_from_series_provider(show_obj, cur_image_type, force) self._cache_image_from_series_provider(show_obj, cur_image_type, force)
# download missing episode images from a series provider
sickrage.app.log.debug(f"Seeing if we still need episode poster images")
for episode in show_obj.episodes:
if not self.has_poster(show_obj.series_id, episode_id=episode.episode_id):
self._cache_episode_images_from_series_provider(show_obj, force)
sickrage.app.log.info("Done cache check") sickrage.app.log.info("Done cache check")
...@@ -9,7 +9,7 @@ from sickrage.core.tv.show.helpers import find_show ...@@ -9,7 +9,7 @@ from sickrage.core.tv.show.helpers import find_show
class Media(object): class Media(object):
def __init__(self, series_id, series_provider_id, media_format=None): def __init__(self, series_id, episode_id=None, series_provider_id=None, media_format=None):
""" """
:param series_id: The series id of the show :param series_id: The series id of the show
:param media_format: The media format of the show image :param media_format: The media format of the show image
...@@ -24,6 +24,8 @@ class Media(object): ...@@ -24,6 +24,8 @@ class Media(object):
except ValueError: except ValueError:
self.series_id = 0 self.series_id = 0
self.episode_id = episode_id
self.series_provider_id = series_provider_id self.series_provider_id = series_provider_id
def get_default_media_name(self): def get_default_media_name(self):
......
...@@ -30,7 +30,7 @@ class Banner(Media): ...@@ -30,7 +30,7 @@ class Banner(Media):
""" """
def __init__(self, series_id, series_provider_id, media_format=None): def __init__(self, series_id, series_provider_id, media_format=None):
super(Banner, self).__init__(series_id, series_provider_id, media_format) super(Banner, self).__init__(series_id, series_provider_id=series_provider_id, media_format=media_format)
def get_default_media_name(self): def get_default_media_name(self):
return 'banner-thumb.png' if self.media_format == 'thumb' else 'banner.png' return 'banner-thumb.png' if self.media_format == 'thumb' else 'banner.png'
......
...@@ -30,7 +30,7 @@ class FanArt(Media): ...@@ -30,7 +30,7 @@ class FanArt(Media):
""" """
def __init__(self, series_id, series_provider_id, media_format=None): def __init__(self, series_id, series_provider_id, media_format=None):
super(FanArt, self).__init__(series_id, series_provider_id, media_format) super(FanArt, self).__init__(series_id, series_provider_id=series_provider_id, media_format=media_format)
def get_default_media_name(self): def get_default_media_name(self):
return 'fanart.png' return 'fanart.png'
......
...@@ -29,7 +29,7 @@ class Network(Media): ...@@ -29,7 +29,7 @@ class Network(Media):
""" """
def __init__(self, series_id, series_provider_id, media_format=None): def __init__(self, series_id, series_provider_id, media_format=None):
super(Network, self).__init__(series_id, series_provider_id, media_format) super(Network, self).__init__(series_id, series_provider_id=series_provider_id, media_format=media_format)
def get_default_media_name(self): def get_default_media_name(self):
return os.path.join('network', 'nonetwork.png') return os.path.join('network', 'nonetwork.png')
......
...@@ -29,8 +29,8 @@ class Poster(Media): ...@@ -29,8 +29,8 @@ class Poster(Media):
Get the poster of a show Get the poster of a show
""" """
def __init__(self, series_id, series_provider_id, media_format='normal'): def __init__(self, series_id, episode_id=None, series_provider_id=None, media_format='normal'):
super(Poster, self).__init__(series_id, series_provider_id, media_format) super(Poster, self).__init__(series_id, episode_id, series_provider_id, media_format)
def get_default_media_name(self): def get_default_media_name(self):
return 'poster-thumb.png' if self.media_format == 'thumb' else 'poster.png' return 'poster-thumb.png' if self.media_format == 'thumb' else 'poster.png'
...@@ -39,10 +39,10 @@ class Poster(Media): ...@@ -39,10 +39,10 @@ class Poster(Media):
media_file = '' media_file = ''
if self.media_format == 'normal': if self.media_format == 'normal':
media_file = ImageCache().poster_path(self.series_id) media_file = ImageCache().poster_path(self.series_id, episode_id=self.episode_id)
if self.media_format == 'thumb': if self.media_format == 'thumb':
media_file = ImageCache().poster_thumb_path(self.series_id) media_file = ImageCache().poster_thumb_path(self.series_id, episode_id=self.episode_id)
if not all([media_file, os.path.exists(media_file)]): if not all([media_file, os.path.exists(media_file)]):
media_file = os.path.join(self.get_media_root(), 'images', self.get_default_media_name()) media_file = os.path.join(self.get_media_root(), 'images', self.get_default_media_name())
......
...@@ -49,12 +49,16 @@ def series_image(series_id=None, series_provider_id=None, which=None): ...@@ -49,12 +49,16 @@ def series_image(series_id=None, series_provider_id=None, which=None):
elif which == SeriesImageType.FANART: elif which == SeriesImageType.FANART:
return FanArt(series_id, series_provider_id, media_format) return FanArt(series_id, series_provider_id, media_format)
elif which in (SeriesImageType.POSTER, SeriesImageType.POSTER_THUMB): elif which in (SeriesImageType.POSTER, SeriesImageType.POSTER_THUMB):
return Poster(series_id, series_provider_id, media_format) return Poster(series_id, episode_id=None, series_provider_id=series_provider_id, media_format=media_format)
elif which == SeriesImageType.NETWORK: elif which == SeriesImageType.NETWORK:
return Network(series_id, series_provider_id, media_format) return Network(series_id, series_provider_id, media_format)
def series_provider_image(series_id=None, series_provider_id=None, which=None): def episode_image(series_id, episode_id, series_provider_id=None):
return Poster(series_id, episode_id=episode_id, series_provider_id=series_provider_id)
def series_provider_image(series_id=None, episode_id=None, series_provider_id=None, which=None):
media_format = ('normal', 'thumb')[which in (SeriesImageType.BANNER_THUMB, SeriesImageType.POSTER_THUMB, SeriesImageType.SMALL)] media_format = ('normal', 'thumb')[which in (SeriesImageType.BANNER_THUMB, SeriesImageType.POSTER_THUMB, SeriesImageType.SMALL)]
if which not in (SeriesImageType.FANART, SeriesImageType.POSTER, SeriesImageType.BANNER, SeriesImageType.BANNER_THUMB, SeriesImageType.POSTER_THUMB): if which not in (SeriesImageType.FANART, SeriesImageType.POSTER, SeriesImageType.BANNER, SeriesImageType.BANNER_THUMB, SeriesImageType.POSTER_THUMB):
...@@ -86,4 +90,4 @@ def series_provider_image(series_id=None, series_provider_id=None, which=None): ...@@ -86,4 +90,4 @@ def series_provider_image(series_id=None, series_provider_id=None, which=None):
elif which == SeriesImageType.FANART: elif which == SeriesImageType.FANART:
return FanArt(int(series_id), series_provider_id, media_format) return FanArt(int(series_id), series_provider_id, media_format)
elif which in [SeriesImageType.POSTER, SeriesImageType.POSTER_THUMB]: elif which in [SeriesImageType.POSTER, SeriesImageType.POSTER_THUMB]:
return Poster(int(series_id), series_provider_id, media_format) return Poster(int(series_id), episode_id, series_provider_id, media_format)
...@@ -150,10 +150,10 @@ class DailySearchTask(Task): ...@@ -150,10 +150,10 @@ class DailySearchTask(Task):
try: try:
sickrage.app.log.info("Starting daily search for: [" + show_object.name + "]") sickrage.app.log.info("Starting daily search for: [" + show_object.name + "]")
WebSocketMessage('SEARCH_QUEUE_STATUS_UPDATED', # WebSocketMessage('SEARCH_QUEUE_STATUS_UPDATED',
{'seriesSlug': show_object.slug, # {'seriesSlug': show_object.slug,
'episodeId': episode_object.episode_id, # 'episodeId': episode_object.episode_id,
'searchQueueStatus': episode_object.search_queue_status}).push() # 'searchQueueStatus': episode_object.search_queue_status}).push()
search_result = search_providers(self.series_id, search_result = search_providers(self.series_id,
self.series_provider_id, self.series_provider_id,
...@@ -176,10 +176,10 @@ class DailySearchTask(Task): ...@@ -176,10 +176,10 @@ class DailySearchTask(Task):
except Exception: except Exception:
sickrage.app.log.debug(traceback.format_exc()) sickrage.app.log.debug(traceback.format_exc())
finally: finally:
WebSocketMessage('SEARCH_QUEUE_STATUS_UPDATED', # WebSocketMessage('SEARCH_QUEUE_STATUS_UPDATED',
{'seriesSlug': show_object.slug, # {'seriesSlug': show_object.slug,
'episodeId': episode_object.episode_id, # 'episodeId': episode_object.episode_id,
'searchQueueStatus': episode_object.search_queue_status}).push() # 'searchQueueStatus': episode_object.search_queue_status}).push()
sickrage.app.log.info("Finished daily search for: [" + show_object.name + "]") sickrage.app.log.info("Finished daily search for: [" + show_object.name + "]")
...@@ -282,10 +282,10 @@ class BacklogSearchTask(Task): ...@@ -282,10 +282,10 @@ class BacklogSearchTask(Task):
try: try:
sickrage.app.log.info("Starting backlog search for: [{}] S{:02d}E{:02d}".format(show_object.name, self.season, self.episode)) sickrage.app.log.info("Starting backlog search for: [{}] S{:02d}E{:02d}".format(show_object.name, self.season, self.episode))
WebSocketMessage('SEARCH_QUEUE_STATUS_UPDATED', # WebSocketMessage('SEARCH_QUEUE_STATUS_UPDATED',
{'seriesSlug': show_object.slug, # {'seriesSlug': show_object.slug,
'episodeId': episode_object.episode_id, # 'episodeId': episode_object.episode_id,
'searchQueueStatus': episode_object.search_queue_status}).push() # 'searchQueueStatus': episode_object.search_queue_status}).push()
search_result = search_providers(self.series_id, search_result = search_providers(self.series_id,
self.series_provider_id, self.series_provider_id,
...@@ -308,10 +308,10 @@ class BacklogSearchTask(Task): ...@@ -308,10 +308,10 @@ class BacklogSearchTask(Task):
except Exception: except Exception:
sickrage.app.log.debug(traceback.format_exc()) sickrage.app.log.debug(traceback.format_exc())
finally: finally:
WebSocketMessage('SEARCH_QUEUE_STATUS_UPDATED', # WebSocketMessage('SEARCH_QUEUE_STATUS_UPDATED',
{'seriesSlug': show_object.slug, # {'seriesSlug': show_object.slug,
'episodeId': episode_object.episode_id, # 'episodeId': episode_object.episode_id,
'searchQueueStatus': episode_object.search_queue_status}).push() # 'searchQueueStatus': episode_object.search_queue_status}).push()
sickrage.app.log.info("Finished backlog search for: [{}] S{:02d}E{:02d}".format(show_object.name, self.season, self.episode)) sickrage.app.log.info("Finished backlog search for: [{}] S{:02d}E{:02d}".format(show_object.name, self.season, self.episode))
...@@ -346,10 +346,10 @@ class FailedSearchTask(Task): ...@@ -346,10 +346,10 @@ class FailedSearchTask(Task):
try: try:
sickrage.app.log.info("Starting failed download search for: [" + episode_object.name + "]") sickrage.app.log.info("Starting failed download search for: [" + episode_object.name + "]")
WebSocketMessage('SEARCH_QUEUE_STATUS_UPDATED', # WebSocketMessage('SEARCH_QUEUE_STATUS_UPDATED',
{'seriesSlug': show_object.slug, # {'seriesSlug': show_object.slug,
'episodeId': episode_object.episode_id, # 'episodeId': episode_object.episode_id,
'searchQueueStatus': episode_object.search_queue_status}).push() # 'searchQueueStatus': episode_object.search_queue_status}).push()
sickrage.app.log.info("Marking episode as bad: [" + episode_object.pretty_name() + "]") sickrage.app.log.info("Marking episode as bad: [" + episode_object.pretty_name() + "]")
...@@ -382,9 +382,9 @@ class FailedSearchTask(Task): ...@@ -382,9 +382,9 @@ class FailedSearchTask(Task):
except Exception: except Exception:
sickrage.app.log.debug(traceback.format_exc()) sickrage.app.log.debug(traceback.format_exc())
finally: finally:
WebSocketMessage('SEARCH_QUEUE_STATUS_UPDATED', # WebSocketMessage('SEARCH_QUEUE_STATUS_UPDATED',
{'seriesSlug': show_object.slug, # {'seriesSlug': show_object.slug,
'episodeId': episode_object.episode_id, # 'episodeId': episode_object.episode_id,
'searchQueueStatus': episode_object.search_queue_status}).push() # 'searchQueueStatus': episode_object.search_queue_status}).push()
sickrage.app.log.info("Finished failed download search for: [" + show_object.name + "]") sickrage.app.log.info("Finished failed download search for: [" + show_object.name + "]")
...@@ -116,9 +116,9 @@ class ShowQueue(Queue): ...@@ -116,9 +116,9 @@ class ShowQueue(Queue):
if (self.is_being_refreshed(series_id) or self.is_being_refreshed(series_id)) and not force: if (self.is_being_refreshed(series_id) or self.is_being_refreshed(series_id)) and not force:
raise CantRefreshShowException("This show is already being refreshed or queued to be refreshed, skipping this request.") raise CantRefreshShowException("This show is already being refreshed or queued to be refreshed, skipping this request.")
if show_obj.paused and not force: # if show_obj.paused and not force:
sickrage.app.log.debug('Skipping show [{}] because it is paused.'.format(show_obj.name)) # sickrage.app.log.debug('Skipping show [{}] because it is paused.'.format(show_obj.name))
return # return
sickrage.app.log.debug("Queueing show refresh for {}".format(show_obj.name)) sickrage.app.log.debug("Queueing show refresh for {}".format(show_obj.name))
......
...@@ -40,6 +40,7 @@ from sickrage.core.enums import SearchFormat, FileTimestampTimezone ...@@ -40,6 +40,7 @@ from sickrage.core.enums import SearchFormat, FileTimestampTimezone
from sickrage.core.exceptions import EpisodeNotFoundException, EpisodeDeletedException, NoNFOException from sickrage.core.exceptions import EpisodeNotFoundException, EpisodeDeletedException, NoNFOException
from sickrage.core.helpers import replace_extension, modify_file_timestamp, sanitize_scene_name, remove_non_release_groups, \ from sickrage.core.helpers import replace_extension, modify_file_timestamp, sanitize_scene_name, remove_non_release_groups, \
remove_extension, sanitize_file_name, make_dirs, move_file, delete_empty_folders, file_size, is_media_file, try_int, safe_getattr, flatten remove_extension, sanitize_file_name, make_dirs, move_file, delete_empty_folders, file_size, is_media_file, try_int, safe_getattr, flatten
from sickrage.core.media.util import episode_image
from sickrage.core.tv.show.helpers import find_show from sickrage.core.tv.show.helpers import find_show
from sickrage.notification_providers import NotificationProvider from sickrage.notification_providers import NotificationProvider
from sickrage.series_providers.exceptions import SeriesProviderSeasonNotFound, SeriesProviderEpisodeNotFound from sickrage.series_providers.exceptions import SeriesProviderSeasonNotFound, SeriesProviderEpisodeNotFound
...@@ -308,6 +309,10 @@ class TVEpisode(object): ...@@ -308,6 +309,10 @@ class TVEpisode(object):
with sickrage.app.main_db.session() as session: with sickrage.app.main_db.session() as session:
session.flush() session.flush()
@property
def poster(self):
return episode_image(self.series_id, self.episode_id, self.series_provider_id).url
@property @property
def show(self): def show(self):
return find_show(self.series_id, self.series_provider_id) return find_show(self.series_id, self.series_provider_id)
...@@ -529,7 +534,8 @@ class TVEpisode(object): ...@@ -529,7 +534,8 @@ class TVEpisode(object):
self.episode_id = try_int(safe_getattr(series_episode_info, 'id'), self.episode_id) self.episode_id = try_int(safe_getattr(series_episode_info, 'id'), self.episode_id)
if not self.episode_id: if not self.episode_id:
sickrage.app.log.warning(f"Failed to retrieve {self.show.name} - S{int(season or 0):02d}E{int(episode or 0):02d} episode ID from {self.show.series_provider.name}") sickrage.app.log.warning(
f"Failed to retrieve {self.show.name} - S{int(season or 0):02d}E{int(episode or 0):02d} episode ID from {self.show.series_provider.name}")
self.show.delete_episode(season, episode) self.show.delete_episode(season, episode)
return False return False
...@@ -1391,4 +1397,22 @@ class TVEpisode(object): ...@@ -1391,4 +1397,22 @@ class TVEpisode(object):
json_data['overview'] = self.overview.name