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):
"""
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):
"""
Builds up the full path to the thumbnails image cache directory
"""
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
: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
"""
poster_file_name = str(series_id) + '.poster.jpg'
return os.path.join(self._cache_dir(), poster_file_name)
if episode_id:
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
......@@ -82,7 +108,7 @@ class ImageCache(object):
banner_file_name = str(series_id) + '.banner.jpg'
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
......@@ -92,7 +118,7 @@ class ImageCache(object):
fanart_file_name = str(series_id) + '.fanart.jpg'
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
......@@ -102,7 +128,7 @@ class ImageCache(object):
fanartthumb_file_name = str(series_id) + '.fanart.jpg'
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
......@@ -112,7 +138,7 @@ class ImageCache(object):
posterthumb_file_name = str(series_id) + '.poster.jpg'
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
......@@ -122,15 +148,15 @@ class ImageCache(object):
bannerthumb_file_name = str(series_id) + '.banner.jpg'
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")
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
"""
......@@ -138,7 +164,7 @@ class ImageCache(object):
sickrage.app.log.debug("Checking if file " + str(banner_path) + " exists")
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
"""
......@@ -146,7 +172,7 @@ class ImageCache(object):
sickrage.app.log.debug("Checking if file " + str(fanart_path) + " exists")
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
"""
......@@ -154,7 +180,7 @@ class ImageCache(object):
sickrage.app.log.debug("Checking if file " + str(poster_thumb_path) + " exists")
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
"""
......@@ -263,7 +289,7 @@ class ImageCache(object):
sickrage.app.log.error("Invalid cache image type: {}".format(img_type))
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()
img_data = metadata_generator._retrieve_show_image(self.IMAGE_TYPES[img_type], show_obj)
if not img_data:
......@@ -273,6 +299,29 @@ class ImageCache(object):
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):
"""
Caches all images for the given show. Copies them from the show dir if possible, or
......@@ -318,18 +367,20 @@ class ImageCache(object):
cur_file_type) + " needs metadata: " + str(need_images[cur_file_type]))
if cur_file_type in need_images and need_images[cur_file_type]:
sickrage.app.log.debug(
"Found an image in the show dir that doesn't exist in the cache, caching it: " + cur_file_name + ", type " + str(
cur_file_type))
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}")
self._cache_image_from_file(cur_file_name, cur_file_type, show_obj.series_id)
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]:
sickrage.app.log.debug(
"Seeing if we still need an image of type " + str(cur_image_type) + ": " + str(
need_images[cur_image_type]))
sickrage.app.log.debug(f"Seeing if we still need an image of type {cur_image_type}: {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)
# 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")
......@@ -9,7 +9,7 @@ from sickrage.core.tv.show.helpers import find_show
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 media_format: The media format of the show image
......@@ -24,6 +24,8 @@ class Media(object):
except ValueError:
self.series_id = 0
self.episode_id = episode_id
self.series_provider_id = series_provider_id
def get_default_media_name(self):
......
......@@ -30,7 +30,7 @@ class Banner(Media):
"""
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):
return 'banner-thumb.png' if self.media_format == 'thumb' else 'banner.png'
......
......@@ -30,7 +30,7 @@ class FanArt(Media):
"""
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):
return 'fanart.png'
......
......@@ -29,7 +29,7 @@ class Network(Media):
"""
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):
return os.path.join('network', 'nonetwork.png')
......
......@@ -29,8 +29,8 @@ class Poster(Media):
Get the poster of a show
"""
def __init__(self, series_id, series_provider_id, media_format='normal'):
super(Poster, self).__init__(series_id, series_provider_id, media_format)
def __init__(self, series_id, episode_id=None, series_provider_id=None, media_format='normal'):
super(Poster, self).__init__(series_id, episode_id, series_provider_id, media_format)
def get_default_media_name(self):
return 'poster-thumb.png' if self.media_format == 'thumb' else 'poster.png'
......@@ -39,10 +39,10 @@ class Poster(Media):
media_file = ''
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':
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)]):
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):
elif which == SeriesImageType.FANART:
return FanArt(series_id, series_provider_id, media_format)
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:
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)]
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):
elif which == SeriesImageType.FANART:
return FanArt(int(series_id), series_provider_id, media_format)
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):
try:
sickrage.app.log.info("Starting daily search for: [" + show_object.name + "]")
WebSocketMessage('SEARCH_QUEUE_STATUS_UPDATED',
{'seriesSlug': show_object.slug,
'episodeId': episode_object.episode_id,
'searchQueueStatus': episode_object.search_queue_status}).push()
# WebSocketMessage('SEARCH_QUEUE_STATUS_UPDATED',
# {'seriesSlug': show_object.slug,
# 'episodeId': episode_object.episode_id,
# 'searchQueueStatus': episode_object.search_queue_status}).push()
search_result = search_providers(self.series_id,
self.series_provider_id,
......@@ -176,10 +176,10 @@ class DailySearchTask(Task):
except Exception:
sickrage.app.log.debug(traceback.format_exc())
finally:
WebSocketMessage('SEARCH_QUEUE_STATUS_UPDATED',
{'seriesSlug': show_object.slug,
'episodeId': episode_object.episode_id,
'searchQueueStatus': episode_object.search_queue_status}).push()
# WebSocketMessage('SEARCH_QUEUE_STATUS_UPDATED',
# {'seriesSlug': show_object.slug,
# 'episodeId': episode_object.episode_id,
# 'searchQueueStatus': episode_object.search_queue_status}).push()
sickrage.app.log.info("Finished daily search for: [" + show_object.name + "]")
......@@ -282,10 +282,10 @@ class BacklogSearchTask(Task):
try:
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',
{'seriesSlug': show_object.slug,
'episodeId': episode_object.episode_id,
'searchQueueStatus': episode_object.search_queue_status}).push()
# WebSocketMessage('SEARCH_QUEUE_STATUS_UPDATED',
# {'seriesSlug': show_object.slug,
# 'episodeId': episode_object.episode_id,
# 'searchQueueStatus': episode_object.search_queue_status}).push()
search_result = search_providers(self.series_id,
self.series_provider_id,
......@@ -308,10 +308,10 @@ class BacklogSearchTask(Task):
except Exception:
sickrage.app.log.debug(traceback.format_exc())
finally:
WebSocketMessage('SEARCH_QUEUE_STATUS_UPDATED',
{'seriesSlug': show_object.slug,
'episodeId': episode_object.episode_id,
'searchQueueStatus': episode_object.search_queue_status}).push()
# WebSocketMessage('SEARCH_QUEUE_STATUS_UPDATED',
# {'seriesSlug': show_object.slug,
# 'episodeId': episode_object.episode_id,
# '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))
......@@ -346,10 +346,10 @@ class FailedSearchTask(Task):
try:
sickrage.app.log.info("Starting failed download search for: [" + episode_object.name + "]")
WebSocketMessage('SEARCH_QUEUE_STATUS_UPDATED',
{'seriesSlug': show_object.slug,
'episodeId': episode_object.episode_id,
'searchQueueStatus': episode_object.search_queue_status}).push()
# WebSocketMessage('SEARCH_QUEUE_STATUS_UPDATED',
# {'seriesSlug': show_object.slug,
# 'episodeId': episode_object.episode_id,
# 'searchQueueStatus': episode_object.search_queue_status}).push()
sickrage.app.log.info("Marking episode as bad: [" + episode_object.pretty_name() + "]")
......@@ -382,9 +382,9 @@ class FailedSearchTask(Task):
except Exception:
sickrage.app.log.debug(traceback.format_exc())
finally:
WebSocketMessage('SEARCH_QUEUE_STATUS_UPDATED',
{'seriesSlug': show_object.slug,
'episodeId': episode_object.episode_id,
'searchQueueStatus': episode_object.search_queue_status}).push()
# WebSocketMessage('SEARCH_QUEUE_STATUS_UPDATED',
# {'seriesSlug': show_object.slug,
# 'episodeId': episode_object.episode_id,
# 'searchQueueStatus': episode_object.search_queue_status}).push()
sickrage.app.log.info("Finished failed download search for: [" + show_object.name + "]")
......@@ -116,9 +116,9 @@ class ShowQueue(Queue):
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.")
if show_obj.paused and not force:
sickrage.app.log.debug('Skipping show [{}] because it is paused.'.format(show_obj.name))
return
# if show_obj.paused and not force:
# sickrage.app.log.debug('Skipping show [{}] because it is paused.'.format(show_obj.name))
# return
sickrage.app.log.debug("Queueing show refresh for {}".format(show_obj.name))
......
......@@ -40,6 +40,7 @@ from sickrage.core.enums import SearchFormat, FileTimestampTimezone
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, \
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.notification_providers import NotificationProvider
from sickrage.series_providers.exceptions import SeriesProviderSeasonNotFound, SeriesProviderEpisodeNotFound
......@@ -308,6 +309,10 @@ class TVEpisode(object):
with sickrage.app.main_db.session() as session:
session.flush()
@property
def poster(self):
return episode_image(self.series_id, self.episode_id, self.series_provider_id).url
@property
def show(self):
return find_show(self.series_id, self.series_provider_id)
......@@ -529,7 +534,8 @@ class TVEpisode(object):
self.episode_id = try_int(safe_getattr(series_episode_info, 'id'), 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)
return False
......@@ -1391,4 +1397,22 @@ class TVEpisode(object):
json_data['overview'] = self.overview.name
json_data['searchQueueStatus'] = self.search_queue_status
# status and quality section
status, quality = Quality.split_composite_status(self.status)
json_data['status'] = {
'name': status.display_name,
'slug': status.name
}
json_data['quality'] = {
'name': quality.display_name,
'slug': quality.name
}
# images section
json_data['images'] = {
'poster': self.poster
}
return json_data
......@@ -74,9 +74,9 @@ class ShowUpdater(object):
# start update process
pi_list = []
for show_obj in get_show_list():
if show_obj.paused:
sickrage.app.log.info('Show update skipped, show: {} is paused.'.format(show_obj.name))
continue
# if show_obj.paused:
# sickrage.app.log.info('Show update skipped, show: {} is paused.'.format(show_obj.name))
# continue
if show_obj.status == 'Ended':
if not sickrage.app.config.general.show_update_stale:
......
......@@ -32,6 +32,7 @@ from tornado.ioloop import IOLoop
from tornado.web import Application, RedirectHandler, StaticFileHandler
import sickrage
from sickrage.core.webserver.handlers.api.v2.episode import ApiV2EpisodeStatusesHandler
from sickrage.core.webserver.helpers import create_https_certificates, is_certificate_valid, certificate_needs_renewal
from sickrage.core.webserver.handlers.account import AccountLinkHandler, AccountUnlinkHandler, AccountIsLinkedHandler
from sickrage.core.webserver.handlers.announcements import AnnouncementsHandler, MarkAnnouncementSeenHandler, AnnouncementCountHandler
......@@ -45,7 +46,7 @@ from sickrage.core.webserver.handlers.api.v2.postprocess import Apiv2PostProcess
from sickrage.core.webserver.handlers.api.v2.schedule import ApiV2ScheduleHandler
from sickrage.core.webserver.handlers.api.v2.series import ApiV2SeriesHandler, ApiV2SeriesEpisodesHandler, ApiV2SeriesImagesHandler, ApiV2SeriesImdbInfoHandler, \
ApiV2SeriesBlacklistHandler, ApiV2SeriesWhitelistHandler, ApiV2SeriesRefreshHandler, ApiV2SeriesUpdateHandler, ApiV2SeriesEpisodesRenameHandler, \
ApiV2SeriesEpisodesManualSearchHandler
ApiV2SeriesEpisodesManualSearchHandler, ApiV2SeriesSearchFormatsHandler
from sickrage.core.webserver.handlers.api.v2.series_provider import ApiV2SeriesProvidersHandler, ApiV2SeriesProvidersSearchHandler, \
ApiV2SeriesProvidersLanguagesHandler
from sickrage.core.webserver.handlers.calendar import CalendarHandler
......@@ -241,7 +242,9 @@ class WebServer(object):
(fr'{self.api_v2_root}/series/(\d+[-][a-z]+)/blacklist', ApiV2SeriesBlacklistHandler),
(fr'{self.api_v2_root}/series/(\d+[-][a-z]+)/whitelist', ApiV2SeriesWhitelistHandler),
(fr'{self.api_v2_root}/series/(\d+[-][a-z]+)/refresh', ApiV2SeriesRefreshHandler),
(fr'{self.api_v2_root}/series/(\d+[-][a-z]+)/update', ApiV2SeriesUpdateHandler)
(fr'{self.api_v2_root}/series/(\d+[-][a-z]+)/update', ApiV2SeriesUpdateHandler),
(fr'{self.api_v2_root}/series/search-formats', ApiV2SeriesSearchFormatsHandler),
(fr'{self.api_v2_root}/episodes/statuses', ApiV2EpisodeStatusesHandler),
]
# New UI Static File Handlers
......
......@@ -32,31 +32,17 @@ class ApiV2ConfigHandler(ApiV2BaseHandler):
config_data = sickrage.app.config.to_json()
config_data['constants'] = {
'episodeStatuses': [{
'name': x.name,
'displayName': x.display_name,
'value': x.value
} for x in EpisodeStatus],
'overviewStrings': [{
'name': x.name,
'cssName': x.css_name
} for x in Overview],
'showSearchFormats': [{
'name': x.name,
'displayName': x.display_name,
'value': x.value
} for x in SearchFormat],
'qualities': [{
'name': x.name,
'displayName': x.display_name,
'cssName': x.css_name,
'isPreset': x.is_preset,
'value': x.value
} for x in Qualities],
'compositeStatuses': {
'snatched': [x.name for x in EpisodeStatus.composites(EpisodeStatus.SNATCHED)],
'downloaded': [x.name for x in EpisodeStatus.composites(EpisodeStatus.DOWNLOADED)]
}
} for x in Qualities]
}
return self.json_response(config_data)
......@@ -18,5 +18,15 @@
# You should have received a copy of the GNU General Public License
# along with SiCKRAGE. If not, see <http://www.gnu.org/licenses/>.
# ##############################################################################
from sickrage.core import EpisodeStatus
from sickrage.core.webserver.handlers.api.v2 import ApiV2BaseHandler
class ApiV2EpisodeStatusesHandler(ApiV2BaseHandler):
def get(self):
statuses = [{
'name': x.display_name,
'slug': x.name,
} for x in EpisodeStatus]
return self.json_response(statuses)
......@@ -600,3 +600,13 @@ class ApiV2SeriesEpisodesManualSearchHandler(ApiV2BaseHandler):
return self.json_response({'success': True})
return self._not_found(error=_(f"Unable to find season {season_num} episode {episode_num} for show {series.name} on search providers"))
class ApiV2SeriesSearchFormatsHandler(ApiV2BaseHandler):
def get(self):
search_formats = [{
'name': x.display_name,
'slug': x.name,
} for x in SearchFormat]
return self.json_response(search_formats)
......@@ -199,7 +199,7 @@
<input type="checkbox" class="toggle color-primary is-material"
id="paused"
name="paused" ${('', 'checked')[show.paused == 1]} />
${_('pause this show (SiCKRAGE will not download episodes)')}
${_('pause this show (SiCKRAGE will download episodes but will continue to get updates)')}
</label>
</div>
</div>
......
......@@ -428,7 +428,7 @@ class MetadataProvider(object):
sickrage.app.log.debug("No thumb is available for this episode, not creating a thumb")
return False
thumb_data = self.get_show_image(thumb_url)
thumb_data = self.get_image(thumb_url)
result = self._write_image(thumb_data, file_path)
......@@ -506,7 +506,7 @@ class MetadataProvider(object):
sickrage.app.log.debug("Path for season " + str(season) + " came back blank, skipping this season")
return False
seasonData = self.get_show_image(season_url)
seasonData = self.get_image(season_url)
if not seasonData:
sickrage.app.log.debug("No season poster data available, skipping this season")
return False
......@@ -521,7 +521,7 @@ class MetadataProvider(object):
sickrage.app.log.debug("Path for season " + str(season) + " came back blank, skipping this season")
return False
seasonData = self.get_show_image(season_url)
seasonData = self.get_image(season_url)
if not seasonData:
sickrage.app.log.debug("No season banner data available, skipping this season")
return False
......@@ -611,7 +611,7 @@ class MetadataProvider(object):