Browse Source

Change move TVMaze get_premieres and get_returning functions to TVInfoBase.

Change switch to TVInfoBase.
Fix IMDb search.
tags/release_0.25.1
Prinz23 4 years ago
committed by JackDandy
parent
commit
509e686292
  1. 26
      lib/tvinfo_base/base.py
  2. 121
      lib/tvmaze_api/tvmaze_api.py
  3. 62
      sickbeard/webserve.py

26
lib/tvinfo_base/base.py

@ -126,6 +126,9 @@ class TVInfoIDs(object):
return {TVINFO_TVDB: self.tvdb, TVINFO_TMDB: self.tmdb, TVINFO_TVMAZE: self.tvmaze, return {TVINFO_TVDB: self.tvdb, TVINFO_TMDB: self.tmdb, TVINFO_TVMAZE: self.tvmaze,
TVINFO_IMDB: self.imdb, TVINFO_TRAKT: self.trakt, TVINFO_TVRAGE: self.rage}.get(key) TVINFO_IMDB: self.imdb, TVINFO_TRAKT: self.trakt, TVINFO_TVRAGE: self.rage}.get(key)
def get(self, key):
return self.__getitem__(key)
def __iter__(self): def __iter__(self):
for s, v in [(TVINFO_TVDB, self.tvdb), (TVINFO_TMDB, self.tmdb), (TVINFO_TVMAZE, self.tvmaze), for s, v in [(TVINFO_TVDB, self.tvdb), (TVINFO_TMDB, self.tmdb), (TVINFO_TVMAZE, self.tvmaze),
(TVINFO_IMDB, self.imdb), (TVINFO_TRAKT, self.trakt), (TVINFO_TVRAGE, self.rage)]: (TVINFO_IMDB, self.imdb), (TVINFO_TRAKT, self.trakt), (TVINFO_TVRAGE, self.rage)]:
@ -502,14 +505,16 @@ class TVInfoEpisode(dict):
self.thumbadded = None # type: Optional[AnyStr] self.thumbadded = None # type: Optional[AnyStr]
self.rating = None # type: Union[integer_types, float] self.rating = None # type: Union[integer_types, float]
self.siteratingcount = None # type: integer_types self.siteratingcount = None # type: integer_types
self.show = None # type: Optional[TVInfoShow]
def __str__(self): def __str__(self):
show_name = self.show and self.show.seriesname and '<Show %s> - ' % self.show.seriesname
seasno, epno = int(getattr(self, 'seasonnumber', 0)), int(getattr(self, 'episodenumber', 0)) seasno, epno = int(getattr(self, 'seasonnumber', 0)), int(getattr(self, 'episodenumber', 0))
epname = getattr(self, 'episodename', '') epname = getattr(self, 'episodename', '')
if None is not epname: if None is not epname:
return '<Episode %02dx%02d - %r>' % (seasno, epno, epname) return '%s<Episode %02dx%02d - %r>' % (show_name, seasno, epno, epname)
else: else:
return '<Episode %02dx%02d>' % (seasno, epno) return '%s<Episode %02dx%02d>' % (show_name, seasno, epno)
def __getattr__(self, key): def __getattr__(self, key):
if key in self: if key in self:
@ -554,6 +559,7 @@ class TVInfoEpisode(dict):
if cur_value.find(text_type(term).lower()) > -1: if cur_value.find(text_type(term).lower()) > -1:
return self return self
__unicode__ = __str__
__repr__ = __str__ __repr__ = __str__
__nonzero__ = __bool__ __nonzero__ = __bool__
@ -1146,8 +1152,22 @@ class TVInfoBase(object):
""" """
return [] return []
def discover(self, result_count=100, **kwargs): def discover(self, result_count=100, get_extra_images=False, **kwargs):
# type: (...) -> List[TVInfoEpisode]
return []
def get_premieres(self, result_count=100, **kwargs):
# type: (...) -> List[TVInfoEpisode]
"""
get all premiering shows
"""
return []
def get_returning(self, result_count=100, get_extra_images=False, **kwargs):
# type: (...) -> List[TVInfoShow] # type: (...) -> List[TVInfoShow]
"""
get all returning shows
"""
return [] return []
def __getitem__(self, item): def __getitem__(self, item):

121
lib/tvmaze_api/tvmaze_api.py

@ -30,6 +30,7 @@ from lib.pytvmaze import tvmaze
if False: if False:
from typing import Any, AnyStr, Dict, List, Optional from typing import Any, AnyStr, Dict, List, Optional
from six import integer_types from six import integer_types
from lib.pytvmaze.tvmaze import Episode as TVMazeEpisode, Show as TVMazeShow
log = logging.getLogger('tvmaze.api') log = logging.getLogger('tvmaze.api')
log.addHandler(logging.NullHandler()) log.addHandler(logging.NullHandler())
@ -548,20 +549,116 @@ class TvMaze(TVInfoBase):
if p: if p:
return self._convert_person(p) return self._convert_person(p)
def get_premieres(self): def get_premieres(self, result_count=100, get_extra_images=False, **kwargs):
# type: (...) -> List[tvmaze.Episode] # type: (...) -> List[TVInfoEpisode]
return self.filtered_schedule(lambda e: all([1 == e.season_number, 1 == e.episode_number])) return self._filtered_schedule(lambda e: all([1 == e.season_number, 1 == e.episode_number]),
get_images=get_extra_images)
def get_returning(self):
# type: (...) -> List[tvmaze.Episode] def get_returning(self, result_count=100, get_extra_images=False, **kwargs):
return self.filtered_schedule(lambda e: all([1 != e.season_number, 1 == e.episode_number])) # type: (...) -> List[TVInfoEpisode]
return self._filtered_schedule(lambda e: all([1 != e.season_number, 1 == e.episode_number]),
@staticmethod get_images=get_extra_images)
def filtered_schedule(condition):
def _make_episode(self, episode_data, show_data=None, get_images=False):
# type: (TVMazeEpisode, TVMazeShow, bool) -> TVInfoEpisode
"""
make out of TVMazeEpisode object and optionally TVMazeShow a TVInfoEpisode
"""
tv_s = TVInfoShow()
tv_s.seriesname = show_data.name
tv_s.id = show_data.maze_id
tv_s.seriesid = tv_s.id
tv_s.language = show_data.language
tv_s.overview = show_data.summary
tv_s.firstaired = show_data.premiered
tv_s.runtime = show_data.average_runtime or show_data.runtime
tv_s.vote_average = show_data.rating and show_data.rating.get('average')
tv_s.popularity = show_data.weight
tv_s.genre_list = show_data.genres or []
tv_s.genre = ', '.join(tv_s.genre_list)
tv_s.official_site = show_data.official_site
tv_s.status = show_data.status
tv_s.show_type = show_data.type
tv_s.lastupdated = show_data.updated
tv_s.poster = show_data.image and show_data.image.get('original')
tv_s.aliases = [a.name for a in show_data.akas]
if 'days' in show_data.schedule:
tv_s.airs_dayofweek = ', '.join(show_data.schedule['days'])
network = show_data.network or show_data.web_channel
if network:
tv_s.network_is_stream = None is not show_data.web_channel
tv_s.network = network.name
tv_s.network_id = network.maze_id
tv_s.network_country = network.country
tv_s.network_country_code = network.code
tv_s.network_timezone = network.timezone
if get_images and show_data.images:
b_set, f_set, p_set = False, False, False
for img in show_data.images:
img_type = img_type_map.get(img.type, TVInfoImageType.other)
img_width, img_height = img.resolutions['original'].get('width'), \
img.resolutions['original'].get('height')
img_ar = img_width and img_height and float(img_width) / float(img_height)
img_ar_type = self._which_type(img_width, img_ar)
if TVInfoImageType.poster == img_type and img_ar and img_ar_type != img_type and \
tv_s.poster == img.resolutions.get('original')['url']:
p_set = False
tv_s.poster = None
tv_s.poster_thumb = None
img_type = (TVInfoImageType.other, img_type)[
not img_ar or img_ar_type == img_type or
img_type not in (TVInfoImageType.banner, TVInfoImageType.poster, TVInfoImageType.fanart)]
img_src = {}
for res, img_url in iteritems(img.resolutions):
img_size = img_size_map.get(res)
if img_size:
img_src[img_size] = img_url.get('url')
tv_s.images.setdefault(img_type, []).append(
TVInfoImage(
image_type=img_type, sizes=img_src, img_id=img.id, main_image=img.main,
type_str=img.type, width=img_width, height=img_height, aspect_ratio=img_ar))
if not p_set and TVInfoImageType.poster == img_type:
p_set = True
tv_s.poster = img.resolutions.get('original')['url']
tv_s.poster_thumb = img.resolutions.get('original')['url']
elif not b_set and 'banner' == img.type and TVInfoImageType.banner == img_type:
b_set = True
tv_s.banner = img.resolutions.get('original')['url']
tv_s.banner_thumb = img.resolutions.get('medium')['url']
elif not f_set and 'background' == img.type and TVInfoImageType.fanart == img_type:
f_set = True
tv_s.fanart = img.resolutions.get('original')['url']
tv_s.ids = TVInfoIDs(
tvdb=show_data.externals.get('thetvdb'), rage=show_data.externals.get('tvrage'), tvmaze=show_data.id,
imdb=show_data.externals.get('imdb') and try_int(show_data.externals.get('imdb').replace('tt', ''), None))
tv_s.imdb_id = show_data.externals.get('imdb') and try_int(show_data.externals.get('imdb').replace('tt', ''))
ep_obj = TVInfoEpisode()
ep_obj.id = episode_data.maze_id
ep_obj.seasonnumber = episode_data.season_number
ep_obj.episodenumber = episode_data.episode_number
ep_obj.episodename = episode_data.title
ep_obj.airtime = episode_data.airtime
ep_obj.firstaired = episode_data.airdate
if episode_data.airstamp:
try:
at = _datetime_to_timestamp(tz_p.parse(episode_data.airstamp))
ep_obj.timestamp = at
except (BaseException, Exception):
pass
ep_obj.filename = episode_data.image and (episode_data.image.get('original') or
episode_data.image.get('medium'))
ep_obj.is_special = episode_data.is_special()
ep_obj.overview = episode_data.summary
ep_obj.runtime = episode_data.runtime
ep_obj.show = tv_s
return ep_obj
def _filtered_schedule(self, condition, get_images=False):
try: try:
return sorted([ result = sorted([
e for e in tvmaze.get_full_schedule() e for e in tvmaze.get_full_schedule()
if condition(e) and (None is e.show.language or re.search('(?i)eng|jap', e.show.language))], if condition(e) and (None is e.show.language or re.search('(?i)eng|jap', e.show.language))],
key=lambda x: x.show.premiered or x.airstamp) key=lambda x: x.show.premiered or x.airstamp)
except(BaseException, Exception): return [self._make_episode(r, r.show, get_images) for r in result]
except(BaseException, Exception) as e:
return [] return []

62
sickbeard/webserve.py

@ -93,7 +93,6 @@ from lib.dateutil.relativedelta import relativedelta
from lib.fuzzywuzzy import fuzz from lib.fuzzywuzzy import fuzz
from lib.libtrakt import TraktAPI from lib.libtrakt import TraktAPI
from lib.libtrakt.exceptions import TraktException, TraktAuthException from lib.libtrakt.exceptions import TraktException, TraktAuthException
from lib.tvmaze_api.tvmaze_api import TvMaze
import lib.rarfile.rarfile as rarfile import lib.rarfile.rarfile as rarfile
@ -5195,10 +5194,13 @@ class AddShows(Home):
if (int(_datetime_to_timestamp(datetime.datetime.now())) if (int(_datetime_to_timestamp(datetime.datetime.now()))
< sickbeard.MEMCACHE.get(mem_key, {}).get('last_update', 0)): < sickbeard.MEMCACHE.get(mem_key, {}).get('last_update', 0)):
return sickbeard.MEMCACHE.get(mem_key).get('data') return sickbeard.MEMCACHE.get(mem_key).get('data')
tvinfo_config = sickbeard.TVInfoAPI(TVINFO_TVMAZE).api_params.copy()
t = sickbeard.TVInfoAPI(TVINFO_TVMAZE).setup(**tvinfo_config)
if 'prem' in mem_key: if 'prem' in mem_key:
data = TvMaze().get_premieres() data = t.get_premieres()
else: else:
data = TvMaze().get_returning() data = t.get_returning()
sickbeard.MEMCACHE[mem_key] = dict( sickbeard.MEMCACHE[mem_key] = dict(
last_update=(30*60) + int(_datetime_to_timestamp(datetime.datetime.now())), data=data) last_update=(30*60) + int(_datetime_to_timestamp(datetime.datetime.now())), data=data)
return data return data
@ -5211,21 +5213,23 @@ class AddShows(Home):
oldest, newest, oldest_dt, newest_dt, use_networks = None, None, 9999999, 0, False oldest, newest, oldest_dt, newest_dt, use_networks = None, None, 9999999, 0, False
dedupe = [] dedupe = []
parseinfo = dateutil.parser.parserinfo(dayfirst=False, yearfirst=True) parseinfo = dateutil.parser.parserinfo(dayfirst=False, yearfirst=True)
base_url = sickbeard.TVInfoAPI(TVINFO_TVMAZE).config['show_url']
for cur_episode_info in episodes: for cur_episode_info in episodes:
if cur_episode_info.show.maze_id in dedupe: if cur_episode_info.show.id in dedupe:
continue continue
dedupe += [cur_episode_info.show.maze_id] dedupe += [cur_episode_info.show.id]
try: try:
if cur_episode_info.airtime: if cur_episode_info.airtime:
airtime = dateutil.parser.parse(cur_episode_info.airtime).time() airtime = dateutil.parser.parse(cur_episode_info.airtime).time()
else: else:
airtime = cur_episode_info.airstamp and dateutil.parser.parse(cur_episode_info.airstamp).time() airtime = cur_episode_info.timestamp \
and SGDatetime.from_timestamp(cur_episode_info.timestamp).time()
if (0, 0) == (airtime.hour, airtime.minute): if (0, 0) == (airtime.hour, airtime.minute):
airtime = dateutil.parser.parse('23:59').time() airtime = dateutil.parser.parse('23:59').time()
dt = datetime.datetime.combine( dt = datetime.datetime.combine(
dateutil.parser.parse( dateutil.parser.parse(
(cur_episode_info.show.premiered or cur_episode_info.airdate), parseinfo).date(), airtime) (cur_episode_info.show.firstaired or cur_episode_info.firstaired), parseinfo).date(), airtime)
dt_ordinal = dt.toordinal() dt_ordinal = dt.toordinal()
now_ordinal = datetime.datetime.now().toordinal() now_ordinal = datetime.datetime.now().toordinal()
when_past = dt_ordinal < now_ordinal when_past = dt_ordinal < now_ordinal
@ -5242,36 +5246,36 @@ class AddShows(Home):
if 'Return' in browse_title: if 'Return' in browse_title:
returning = '9' returning = '9'
returning_str = 'TBC' returning_str = 'TBC'
if cur_episode_info.airdate: if cur_episode_info.firstaired:
returning = cur_episode_info.airdate returning = cur_episode_info.firstaired
dt_returning = datetime.datetime.combine( dt_returning = datetime.datetime.combine(
dateutil.parser.parse(returning, parseinfo).date(), airtime) dateutil.parser.parse(returning, parseinfo).date(), airtime)
when_past = dt_returning.toordinal() < now_ordinal when_past = dt_returning.toordinal() < now_ordinal
returning_str = SGDatetime.sbfdate(dt_returning) returning_str = SGDatetime.sbfdate(dt_returning)
try: try:
img_uri = next(i for i in cur_episode_info.show.images img_uri = cur_episode_info.show.poster
if i.main and 'poster' == i.type).resolutions['original']['url']
images = dict(poster=dict(thumb='imagecache?path=browse/thumb/tvmaze&source=%s' % img_uri)) images = dict(poster=dict(thumb='imagecache?path=browse/thumb/tvmaze&source=%s' % img_uri))
sickbeard.CACHE_IMAGE_URL_LIST.add_url(img_uri) sickbeard.CACHE_IMAGE_URL_LIST.add_url(img_uri)
except(BaseException, Exception): except(BaseException, Exception):
images = {} images = {}
ids = dict(tvmaze=cur_episode_info.maze_id) ids = dict(tvmaze=cur_episode_info.id)
imdb_id = cur_episode_info.show.externals.get('imdb') imdb_id = cur_episode_info.show.imdb_id
if imdb_id: if imdb_id:
ids.update(dict(imdb=imdb_id)) if isinstance(imdb_id, string_types) and 'tt' in imdb_id:
tvdb_id = cur_episode_info.show.externals.get('thetvdb') ids.update(dict(imdb=imdb_id))
elif isinstance(imdb_id, integer_types):
ids.update(dict(imdb='tt%08d' % imdb_id))
tvdb_id = cur_episode_info.show.ids.get(TVINFO_TVDB)
if tvdb_id: if tvdb_id:
ids.update(dict(tvdb=tvdb_id)) ids.update(dict(tvdb=tvdb_id))
network_name = (getattr(cur_episode_info.show.network, 'name', None) network_name = cur_episode_info.show.network
or getattr(cur_episode_info.show.web_channel, 'name', None) or '')
cc = 'US' cc = 'US'
if network_name: if network_name:
use_networks = True use_networks = True
cc = (getattr(cur_episode_info.show.network, 'code', None) cc = cur_episode_info.show.network_country_code or cc
or getattr(cur_episode_info.show.web_channel, 'code', None) or 'US')
language = ((cur_episode_info.show.language and 'jap' in cur_episode_info.show.language.lower()) language = ((cur_episode_info.show.language and 'jap' in cur_episode_info.show.language.lower())
and 'jp' or 'en') and 'jp' or 'en')
@ -5282,23 +5286,23 @@ class AddShows(Home):
returning=returning, returning=returning,
returning_str=returning_str, returning_str=returning_str,
when_past=when_past, when_past=when_past,
episode_number=cur_episode_info.episode_number, episode_number=cur_episode_info.episodenumber,
episode_season=cur_episode_info.season_number, episode_season=cur_episode_info.seasonnumber,
episode_overview='' if not cur_episode_info.summary else cur_episode_info.summary.strip(), episode_overview='' if not cur_episode_info.overview else cur_episode_info.overview.strip(),
genres=(', '.join(['%s' % v for v in cur_episode_info.show.genres]) genres=(', '.join(['%s' % v for v in cur_episode_info.show.genre_list])
or cur_episode_info.show.type or ''), or cur_episode_info.show.show_type or ''),
images=images, images=images,
overview=('No overview yet' if not cur_episode_info.show.summary overview=('No overview yet' if not cur_episode_info.show.overview
else helpers.xhtml_escape(cur_episode_info.show.summary.strip()[:250:]) else helpers.xhtml_escape(cur_episode_info.show.overview.strip()[:250:])
.strip('*').strip()), .strip('*').strip()),
title=cur_episode_info.show.name, title=cur_episode_info.show.seriesname,
language=language, language=language,
language_img=sickbeard.MEMCACHE_FLAG_IMAGES.get(language, False), language_img=sickbeard.MEMCACHE_FLAG_IMAGES.get(language, False),
country=cc, country=cc,
country_img=sickbeard.MEMCACHE_FLAG_IMAGES.get(cc.lower(), False), country_img=sickbeard.MEMCACHE_FLAG_IMAGES.get(cc.lower(), False),
network=network_name, network=network_name,
rating=cur_episode_info.show.weight or 0, rating=cur_episode_info.show.rating or cur_episode_info.show.popularity or 0,
url_src_db=cur_episode_info.show.url, url_src_db=base_url % cur_episode_info.show.id,
)) ))
except (BaseException, Exception): except (BaseException, Exception):
pass pass

Loading…
Cancel
Save