mirror of
https://github.com/SickGear/SickGear.git
synced 2024-11-21 12:25:04 +00:00
Merge branch 'feature/FixScaleImage' into dev
This commit is contained in:
commit
0384e218aa
9 changed files with 367 additions and 109 deletions
|
@ -45,6 +45,7 @@
|
|||
#person-content .thumb{display:block}
|
||||
#person-content > .main-image{margin-bottom:19px}
|
||||
#person-content > .cast .cast-bg{height:300px; margin:0 auto; background:url(/images/poster-person.jpg) center center no-repeat}
|
||||
#character-content{margin-left:235px}
|
||||
</style>
|
||||
<%
|
||||
def param(visible=True, rid=None, cache_person=None, cache_char=None, person=None, role=None, tvid_prodid=None, thumb=None, oid=None, pid=None):
|
||||
|
@ -64,10 +65,6 @@ def param(visible=True, rid=None, cache_person=None, cache_char=None, person=Non
|
|||
%>
|
||||
<div id="person">
|
||||
<div id="person-content">
|
||||
<div class="main-image cast">
|
||||
<a class="thumb" href="$sbRoot/$param(rid=$person.ref_id(), cache_person=True, thumb=0, oid=$person.id)" rel="dialog"><img src="$sbRoot/$param(False, rid=$person.id, cache_person=True)" class="cast-bg"></a>
|
||||
</div>
|
||||
|
||||
<div class="intro">#slurp
|
||||
#set $gender = ''
|
||||
#if $PersonGenders.female == $person.gender#
|
||||
|
@ -78,6 +75,10 @@ def param(visible=True, rid=None, cache_person=None, cache_char=None, person=Non
|
|||
<h2><span class="name">$person.name</span>#if $age #<span class="age">($age)</span>#end if##if $gender #<span class="gender" title="Biological gender">$gender</span>#end if##if $person.deathday # †#end if#</h2>
|
||||
</div>
|
||||
|
||||
<div class="main-image cast">
|
||||
<a class="thumb" href="$sbRoot/$param(rid=$person.ref_id(), cache_person=True, thumb=0, oid=$person.id)" rel="dialog"><img src="$sbRoot/$param(False, rid=$person.id, cache_person=True)" class="cast-bg"></a>
|
||||
</div>
|
||||
|
||||
<style>
|
||||
#character-content .cast-bg{display:block; background-color:#181818; border:1px solid #181818; -moz-border-radius:10px; -webkit-border-radius:10px; border-radius:10px}
|
||||
#character-content .cast .cast-bg{height:200px; background:url(/images/poster-person.jpg) center center no-repeat}
|
||||
|
@ -98,7 +99,7 @@ def param(visible=True, rid=None, cache_person=None, cache_char=None, person=Non
|
|||
#if not $section_header
|
||||
#set $section_header = True
|
||||
<div id="character-content">
|
||||
<div style="margin:40px 0 7px">is known in your show list as,</div>
|
||||
<div style="margin:0 0 7px">is known in your show list as,</div>
|
||||
#end if
|
||||
|
||||
<div class="role-panel">
|
||||
|
|
|
@ -24,7 +24,10 @@
|
|||
#set sg_root = $getVar('sbRoot', WEB_ROOT)
|
||||
##
|
||||
#import os.path
|
||||
#set global $inc_ofi = True
|
||||
#include $os.path.join($sg_str('PROG_DIR'), 'gui/slick/interfaces/default/inc_top.tmpl')
|
||||
<script type="text/javascript" src="$sbRoot/js/cast.js?v=$sbPID"></script>
|
||||
|
||||
<script>
|
||||
var config = {
|
||||
homeSearchFocus: #echo ['!1','!0'][$sg_var('HOME_SEARCH_FOCUS', True)]#,
|
||||
|
@ -39,6 +42,62 @@
|
|||
$(this).css('cursor', 'help');
|
||||
$(this).qtip({
|
||||
show: {solo:true},
|
||||
// Change qTip to manual hide when it contains many roles to scroll
|
||||
hide: {event:(5 < $(this).closest('div.show-card').attr('data-nroles')) ? 'unfocus' : 'mouseleave'},
|
||||
events: { // Callback events
|
||||
render: function(event, api) {
|
||||
// Grab the tooltip element from the API
|
||||
var tooltip = api.elements.tooltip
|
||||
tooltip.bind('tooltipshow', function(event, api) {
|
||||
var showcardEl = $(api.target).closest('div.show-card')
|
||||
if ('1' === showcardEl.attr('data-ajax')) { // do a one time fetch
|
||||
var qtipEl = $(this).find('.qtip-content'),
|
||||
premiereEl = qtipEl.find('.premiere'),
|
||||
genreEl = qtipEl.find('.genre'),
|
||||
overviewEl = qtipEl.find('.overview'),
|
||||
oldestEl = $('#oldest'),
|
||||
newestEl = $('#newest');
|
||||
|
||||
// Set initial text
|
||||
overviewEl.html('Fetching overview...');
|
||||
$.getJSON($.SickGear.Root + '/add-shows/tvm-get-showinfo', {
|
||||
tvid_prodid: showcardEl.attr('data-id'),
|
||||
oldest_dt: $('#oldest').attr('data-oldest-dt'),
|
||||
newest_dt: $('#newest').attr('data-newest-dt'),
|
||||
},
|
||||
function (data) {
|
||||
if (undefined !== data.overview) {
|
||||
showcardEl.attr('data-ajax', '0'); // mark one time fetch as completed
|
||||
if (undefined !== data.oldest) {
|
||||
oldestEl.attr('data-oldest-dt', data.oldest_dt)
|
||||
oldestEl.html(data.oldest);
|
||||
} else if (undefined !== data.newest) {
|
||||
newestEl.attr('data-newest-dt', data.newest_dt)
|
||||
newestEl.html(data.newest);
|
||||
}
|
||||
var premiere = '';
|
||||
if (data.str_premiered.length) {
|
||||
showcardEl.attr('data-premiered', data.ord_premiered);
|
||||
premiere = "<span style='font-weight:bold;font-size:0.9em;color:#888'><em>First air" + (data.started_past ? 'ed' : 's') + ": " + data.str_premiered + "</em></span>";
|
||||
}
|
||||
if (data.genres) {
|
||||
genreEl.css('display', 'block');
|
||||
genreEl.find('em').html(data.genres);
|
||||
}
|
||||
overviewEl.html(data.overview);
|
||||
if (data.network.length) {
|
||||
premiere += "<span style='display:block;clear:both;font-weight:bold;font-size:0.9em;color:#888'><em>On: " + data.network + "</em></span>";
|
||||
}
|
||||
premiereEl.html(premiere);
|
||||
} else {
|
||||
overviewEl.html('Failed to fetch TVmaze overview' );
|
||||
}
|
||||
}
|
||||
)
|
||||
}
|
||||
})
|
||||
}
|
||||
},
|
||||
position: {viewport:$(window), my:'left center', adjust:{y: -10,x: 2 }},
|
||||
style: {tip: {corner:true, method:'polygon'}, classes:'qtip-rounded qtip-bootstrap qtip-shadow ui-tooltip-sb'}
|
||||
});
|
||||
|
@ -47,6 +106,8 @@
|
|||
$.ll.handleScroll();
|
||||
});
|
||||
|
||||
$('.nav').on('mouseover', function() {$('.service, .browse-image').qtip('hide')})
|
||||
|
||||
savePrefs = (function(){
|
||||
var showsort = [], showfilter = [];
|
||||
|
||||
|
@ -63,7 +124,7 @@
|
|||
});
|
||||
});
|
||||
|
||||
$(document).ready(function(){
|
||||
$(function() {
|
||||
// initialise combos for dirty page refreshes
|
||||
$('#showsort').val('#end raw#$saved_showsort_view#raw#');
|
||||
|
||||
|
@ -259,7 +320,7 @@ $(document).ready(function(){
|
|||
}
|
||||
});
|
||||
|
||||
$('.service, .browse-image').each(addQTip);
|
||||
$('.service, a.browse-image').each(addQTip);
|
||||
|
||||
if (config.homeSearchFocus) {
|
||||
$('#search_show_name').focus();
|
||||
|
@ -288,6 +349,13 @@ $(document).ready(function(){
|
|||
input.focus();
|
||||
}
|
||||
});
|
||||
|
||||
objectFitImages();
|
||||
|
||||
$('#person .person-bg').each(function(i, oImage){
|
||||
removeImageBackground(oImage);
|
||||
scaleImage(oImage);
|
||||
});
|
||||
});
|
||||
|
||||
#end raw
|
||||
|
@ -297,6 +365,10 @@ $(document).ready(function(){
|
|||
<style>
|
||||
#set theme_suffix = ('', '-dark')['dark' == $getVar('sbThemeName', THEME_NAME)]
|
||||
.bfr{position:absolute;left:-999px;top:-999px}.bfr img{width:16px;height:16px}.spinner{display:inline-block;width:16px;height:16px;background:url(${sg_root}/images/loading16${theme_suffix}.gif) no-repeat 0 0}
|
||||
#person{min-height:130px; height:auto; width:215px; margin:auto; display:block}
|
||||
.main-image{margin:15px auto}
|
||||
.person-bg{height:300px; width:215px; display:block; background-color:#181818 !important; border:1px solid #181818; object-fit: contain; font-family: 'object-fit: contain;'; -moz-border-radius:10px; -webkit-border-radius:10px; border-radius:10px; background:url(/images/poster-person.jpg) center center no-repeat}
|
||||
.person-bg{margin:0 auto !important}
|
||||
</style>
|
||||
<div class="bfr"><img src="$sg_root/images/loading16${theme_suffix}.gif" /></div>
|
||||
|
||||
|
@ -341,7 +413,7 @@ $(document).ready(function(){
|
|||
<option value="by_rating"#if 'by_rating' in $saved_showsort_sortby#$selected>> #else#>#end if#% Rating</option>
|
||||
#end if
|
||||
#if $use_ratings and $use_votes
|
||||
<option value="by_rating_votes"#if 'by_rating_votes' in $saved_showsort_sortby#$selected>> #else#>#end if#% Rating > Votes</option>
|
||||
<option value="by_rating_votes"#if 'by_rating_votes' in $saved_showsort_sortby#$selected>> #else#>#end if#% Rating > $term_vote</option>
|
||||
#end if
|
||||
</optgroup>
|
||||
</select>
|
||||
|
@ -468,13 +540,15 @@ $(document).ready(function(){
|
|||
<h4 style="float:left;margin:0 0 0 2px">$browse_title</h4>
|
||||
#if $kwargs and $kwargs.get('oldest')
|
||||
<div class="grey-text" style="clear:left;margin-left:2px;font-size:0.85em">
|
||||
First aired from $kwargs['oldest'] until $kwargs['newest']
|
||||
First aired from <span id="oldest" data-oldest-dt="$kwargs.get('oldest_dt', '')">$kwargs['oldest']</span> until <span id="newest" data-newest-dt="$kwargs.get('newest_dt', '')">$kwargs['newest']</span>
|
||||
</div>
|
||||
#end if
|
||||
|
||||
#if $p_ref
|
||||
<div class="browse-image" style="margin: 10px 2px 30px; border-radius: 5px">
|
||||
<a class="browse-image" href="$sbRoot/imagecache/person?pid=$p_ref&thumb=1" rel="dialog"><img class="browse-image" src="$sbRoot/imagecache/person?pid=$p_ref&thumb=0"></a>
|
||||
<div id="person">
|
||||
<div id="person-content" class="main-image">
|
||||
<a class="thumb" href="$sbRoot/imagecache/person?pid=$p_ref&thumb=1" rel="dialog"><img class="person-bg" src="$sbRoot/imagecache/person?pid=$p_ref&thumb=0"></a>
|
||||
</div>
|
||||
</div>
|
||||
#end if
|
||||
#end if
|
||||
|
@ -489,7 +563,7 @@ $(document).ready(function(){
|
|||
#if 'returning' == $mode
|
||||
#set $overview = '%s: %s' % (
|
||||
'Season %s' % $this_show['episode_season'],
|
||||
$this_show['episode_overview'] or $this_show['overview'])
|
||||
$this_show[('episode_overview', 'overview')['No overview yet' == $this_show['episode_overview']]])
|
||||
#else
|
||||
#set $overview = $this_show['overview']
|
||||
#end if
|
||||
|
@ -500,14 +574,13 @@ $(document).ready(function(){
|
|||
#if $use_ratings:
|
||||
#set $data_rating = $try_float($this_show['rating'])
|
||||
#end if
|
||||
|
||||
<div class="show-card ${hide}${known}inlibrary" data-name="#echo re.sub(r'([\'\"])', r'', $this_show['title'])#" data_id="$show_id"#if $use_ratings# data-rating="$data_rating"#end if##if $use_votes# data-votes="$this_show['votes']"#end if# data-premiered="$this_show['ord_premiered']"#if $use_returning# data-returning="$this_show['ord_returning']"#end if# data-order="$this_show['order']"#if $use_network# data-network="$this_show['network']"#end if#>
|
||||
<div class="show-card ${hide}${known}inlibrary" data-name="#echo re.sub(r'([\'\"])', r'', $this_show['title'])#" data-id="$show_id" data-ajax="$this_show.get('overview_ajax', '0')" data-nroles="#echo len($this_show.get('p_chars', []))#" #if $use_ratings# data-rating="$data_rating"#end if##if $use_votes# data-votes="$this_show['votes']"#end if# data-premiered="$this_show['ord_premiered']"#if $use_returning# data-returning="$this_show['ord_returning']"#end if# data-order="$this_show['order']"#if $use_network# data-network="$this_show['network']"#end if#>
|
||||
<div class="show-card-inner">
|
||||
<div class="browse-image">
|
||||
<a class="browse-image" href="<%= anon_url(this_show['url_src_db']) %>" target="_blank"
|
||||
title="<span style='color: rgb(66, 139, 202)'>$re.sub(r'(?m)\s+\((?:19|20)\d\d\)\s*$', '', $title_html)</span>
|
||||
title="<span style='color: #226baa'>$re.sub(r'(?m)\s+\((?:19|20)\d\d\)\s*$', '', $title_html)</span>
|
||||
|
||||
#if $this_show['genres']#<br><div style='font-weight:bold'>(<em>$this_show['genres']</em>)</div>#end if#
|
||||
<div class='genre' style='display:#echo ('none', 'block')[bool($this_show['genres'])]#;font-weight:bold'>(<em>$this_show['genres']</em>)</div>
|
||||
#if $kwargs and $use_returning#<span style='display:block;clear:both;font-weight:bold;font-size:0.9em;color:#888'><em>Season $this_show['episode_season'] return#echo ('s', 'ed')[$this_show['return_past']]# $this_show['str_returning']</em></span>#end if#
|
||||
#if $this_show.get('country') or $this_show.get('language')
|
||||
<p style='line-height:15px;margin-bottom:2px'>
|
||||
|
@ -519,8 +592,15 @@ $(document).ready(function(){
|
|||
#end if
|
||||
</p>
|
||||
#end if
|
||||
<p style='margin:0 0 2px'>#echo re.sub(r'([,\.!][^,\.!]*?)$', '...', re.sub(r'([!\?\.])(?=\w)', r'\1 ', $overview)).replace('.....', '...')#</p>
|
||||
<p>#if $this_show['str_premiered']#<span style='font-weight:bold;font-size:0.9em;color:#888'><em>#if 'Trakt' == $browse_type and $kwargs and 'returning' == $mode#Air#else#First air#end if##echo ('s', 'ed')[$this_show['started_past']]#: $this_show['str_premiered']</em></span>#end if#
|
||||
#if $this_show.get('p_chars')
|
||||
<p style='overflow-y:auto;max-height:152px'>
|
||||
#for $char in $this_show['p_chars']
|
||||
<span style='display:block;clear:both;font-weight:bold;font-size:0.9em;color:#393'>as $char[0]#if $RoleTypes.ActorMain != $char[1]# ($char[2]/$char[3] eps)#end if#</span>
|
||||
#end for
|
||||
</p>
|
||||
#end if
|
||||
<p class='overview' style='margin:0 0 2px'>$overview</p>
|
||||
<p class='premiere'>#if $this_show['str_premiered']#<span style='font-weight:bold;font-size:0.9em;color:#888'><em>#if 'Trakt' == $browse_type and $kwargs and 'returning' == $mode#Air#else#First air#end if##echo ('s', 'ed')[$this_show['started_past']]#: $this_show['str_premiered']</em></span>#end if#
|
||||
#if $this_show.get('ended_str')# - <span style='font-weight:bold;font-size:0.9em;color:#888'><em>Ended: $this_show['ended_str']</em></span>#end if#
|
||||
#if $this_show.get('network')#<span style='display:block;clear:both;font-weight:bold;font-size:0.9em;color:#888'><em>On: $this_show['network']</em></span>#end if#
|
||||
</p>
|
||||
|
@ -538,19 +618,14 @@ $(document).ready(function(){
|
|||
<div class="show-title">
|
||||
#echo ((re.sub(r'^((?:A(?!\s+to)n?)|The)\s(\w)', r'<span class="article">\1</span> \2', $this_show['title']), $this_show['title'])[$sg_var('SORT_ARTICLE')], '<span> </span>')['' == $this_show['title']]#
|
||||
</div>
|
||||
#if $this_show.get('p_chars')
|
||||
<div class="show-title">
|
||||
#for $char in $this_show['p_chars']
|
||||
<div>as $char[0]#if $RoleTypes.ActorMain != $char[1]# ($char[2]/$char[3] eps)#end if#</div>
|
||||
#end for
|
||||
</div>
|
||||
#end if
|
||||
#if 'Ani' not in $browse_type
|
||||
<a class="show-toggle-hide" href="$sg_root/add-shows/show-toggle-hide?ids=$show_id" title="#echo ('H', 'Unh')[any($hide)]#ide"><i class="sgicon-delete"></i></a>
|
||||
#end if
|
||||
<div class="clearfix">
|
||||
#if $use_ratings or $use_votes
|
||||
<p>#if $use_ratings#<span class="rating">$this_show['rating']#if $re.search(r'^\d+(\.\d+)?$', (str($this_show['rating'])))#%</span>#end if##end if##if $use_votes#<i class="heart icon-glyph"></i><i>$this_show['votes'] $term_vote.lower()</i>#end if#</p>#slurp#
|
||||
#else
|
||||
<p> </p>
|
||||
#end if
|
||||
#if 'url_tvdb' in $this_show and $this_show['url_tvdb']
|
||||
<a class="service" href="<%= anon_url(this_show['url_tvdb']) %>" onclick="window.open(this.href, '_blank'); return false;"
|
||||
|
|
|
@ -310,8 +310,9 @@ class TmdbIndexer(TVInfoBase):
|
|||
self.img_base_url, self.size_map[TVInfoImageType.person_poster][TVInfoImageSize.medium],
|
||||
tmdb_person_obj['profile_path'])
|
||||
|
||||
clean_person_name = clean_data(tmdb_person_obj.get('name'))
|
||||
_it_person_obj = TVInfoPerson(
|
||||
p_id=tmdb_person_obj.get('id'), ids=TVInfoIDs(ids=person_ids), name=clean_data(tmdb_person_obj.get('name')),
|
||||
p_id=tmdb_person_obj.get('id'), ids=TVInfoIDs(ids=person_ids), name=clean_person_name,
|
||||
akas=clean_data(set(tmdb_person_obj.get('also_known_as') or [])),
|
||||
bio=clean_data(tmdb_person_obj.get('biography')), gender=gender,
|
||||
image=main_image, images=image_list, thumb_url=main_thumb,
|
||||
|
@ -331,6 +332,10 @@ class TmdbIndexer(TVInfoBase):
|
|||
ti_show.overview = self._enforce_text(character.get('overview'))
|
||||
ti_show.firstaired = clean_data(character.get('first_air_date'))
|
||||
ti_show.language = clean_data(character.get('original_language'))
|
||||
ti_show.popularity = character.get('popularity')
|
||||
ti_show.vote_count = character.get('vote_count')
|
||||
ti_show.vote_average = character.get('vote_average')
|
||||
ti_show.rating = ti_show.vote_average
|
||||
ti_show.genre_list = []
|
||||
for g in character.get('genre_ids') or []:
|
||||
if g in self.tv_genres:
|
||||
|
@ -350,9 +355,13 @@ class TmdbIndexer(TVInfoBase):
|
|||
(self.img_base_url,
|
||||
self.size_map[TVInfoImageType.person_poster][TVInfoImageSize.original],
|
||||
character['backdrop_path'])
|
||||
clean_char_name = clean_data(character.get('character'))
|
||||
clean_lower_person_name = (clean_person_name or '').lower() or None
|
||||
characters.append(
|
||||
TVInfoCharacter(name=clean_data(character.get('character')), ti_show=ti_show, person=[_it_person_obj],
|
||||
episode_count=character.get('episode_count'))
|
||||
TVInfoCharacter(name=clean_char_name, ti_show=ti_show, person=[_it_person_obj],
|
||||
episode_count=character.get('episode_count'),
|
||||
plays_self=clean_char_name and
|
||||
(clean_char_name or '').lower() in ('self', clean_lower_person_name))
|
||||
)
|
||||
|
||||
_it_person_obj.characters = characters
|
||||
|
@ -754,11 +763,16 @@ class TmdbIndexer(TVInfoBase):
|
|||
for character in sorted(list(filter(lambda b: b['credit_id'] in main_cast_credit_ids,
|
||||
person_obj.get('roles', []) or [])),
|
||||
key=lambda c: c['episode_count'], reverse=True):
|
||||
clean_char_name = clean_data(character['character'])
|
||||
clean_person_name = clean_data(person_obj['name'])
|
||||
clean_lower_person_name = (clean_person_name or '').lower() or None
|
||||
character_obj = TVInfoCharacter(
|
||||
name=clean_data(character['character']),
|
||||
name=clean_char_name,
|
||||
plays_self=clean_char_name and
|
||||
(clean_char_name or '').lower() in ('self', clean_lower_person_name),
|
||||
person=[
|
||||
TVInfoPerson(
|
||||
p_id=person_obj['id'], name=clean_data(person_obj['name']),
|
||||
p_id=person_obj['id'], name=clean_person_name,
|
||||
ids=TVInfoIDs(ids={TVINFO_TMDB: person_obj['id']}),
|
||||
image='%s%s%s' % (
|
||||
self.img_base_url,
|
||||
|
|
|
@ -6,7 +6,7 @@ from exceptions_helper import ConnectionSkipException, ex
|
|||
from six import iteritems
|
||||
from .trakt import TraktAPI
|
||||
from lib.tvinfo_base.exceptions import BaseTVinfoShownotfound
|
||||
from lib.tvinfo_base import TVInfoBase, TVINFO_TRAKT, TVINFO_TMDB, TVINFO_TVDB, TVINFO_TVRAGE, TVINFO_IMDB, \
|
||||
from lib.tvinfo_base import PersonGenders, TVInfoBase, TVINFO_TRAKT, TVINFO_TMDB, TVINFO_TVDB, TVINFO_TVRAGE, TVINFO_IMDB, \
|
||||
TVINFO_SLUG, TVInfoPerson, TVINFO_TWITTER, TVINFO_FACEBOOK, TVINFO_WIKIPEDIA, TVINFO_INSTAGRAM, TVInfoCharacter, \
|
||||
TVInfoShow, TVInfoIDs, TVInfoSocialIDs, TVINFO_TRAKT_SLUG, TVInfoEpisode, TVInfoSeason, RoleTypes
|
||||
from sg_helpers import clean_data, enforce_type, try_int
|
||||
|
@ -262,6 +262,7 @@ class TraktIndexer(TVInfoBase):
|
|||
deathdate=deathdate,
|
||||
homepage=person_obj['homepage'],
|
||||
birthplace=person_obj['birthplace'],
|
||||
gender=PersonGenders.trakt_map.get(person_obj['gender'], PersonGenders.unknown),
|
||||
social_ids=TVInfoSocialIDs(
|
||||
ids={TVINFO_TWITTER: person_obj['social_ids']['twitter'],
|
||||
TVINFO_FACEBOOK: person_obj['social_ids']['facebook'],
|
||||
|
@ -308,6 +309,7 @@ class TraktIndexer(TVInfoBase):
|
|||
if resp:
|
||||
if show_credits:
|
||||
pc = []
|
||||
clean_lower_person_name = (result.name or '').lower()
|
||||
for c in resp.get('cast') or []:
|
||||
ti_show = TVInfoShow()
|
||||
ti_show.id = c['show']['ids'].get('trakt')
|
||||
|
@ -327,9 +329,11 @@ class TraktIndexer(TVInfoBase):
|
|||
ti_show.rating = c['show'].get('rating')
|
||||
ti_show.vote_count = c['show'].get('votes')
|
||||
for ch in c.get('characters') or []:
|
||||
_ti_character = TVInfoCharacter(name=ch, regular=c.get('series_regular'),
|
||||
ti_show=ti_show, person=[result],
|
||||
episode_count=c.get('episode_count'))
|
||||
clean_ch = clean_data(ch)
|
||||
_ti_character = TVInfoCharacter(
|
||||
name=clean_ch, regular=c.get('series_regular'), ti_show=ti_show, person=[result],
|
||||
episode_count=c.get('episode_count'),
|
||||
plays_self=(clean_ch or '').lower() in ('self', clean_lower_person_name))
|
||||
pc.append(_ti_character)
|
||||
ti_show.cast[(RoleTypes.ActorGuest, RoleTypes.ActorMain)[
|
||||
c.get('series_regular', False)]].append(_ti_character)
|
||||
|
|
|
@ -57,6 +57,8 @@ empty_ep = TVInfoEpisode()
|
|||
empty_se = TVInfoSeason()
|
||||
tz_p = parser()
|
||||
|
||||
character_clean_regex = re.compile(r'^tb(a|d)$', flags=re.I)
|
||||
|
||||
img_type_map = {
|
||||
'poster': TVInfoImageType.poster,
|
||||
'banner': TVInfoImageType.banner,
|
||||
|
@ -397,6 +399,14 @@ class TvMaze(TVInfoBase):
|
|||
# type: (...) -> Dict[integer_types, integer_types]
|
||||
return {sid: v.seconds_since_epoch for sid, v in iteritems(tvmaze.show_updates().updates)}
|
||||
|
||||
@staticmethod
|
||||
def _clean_character_name(name):
|
||||
# type: (Optional[str]) -> str
|
||||
name = clean_data(name)
|
||||
if isinstance(name, str):
|
||||
return enforce_type(character_clean_regex.sub('', name), str, '')
|
||||
return enforce_type(name, str, '')
|
||||
|
||||
def _convert_person(self, tvmaze_person_obj, load_credits=True):
|
||||
# type: (tvmaze.Person, bool) -> TVInfoPerson
|
||||
ch = []
|
||||
|
@ -410,7 +420,15 @@ class TvMaze(TVInfoBase):
|
|||
ti_show.ids = TVInfoIDs(ids={TVINFO_TVMAZE: ti_show.id})
|
||||
ti_show.overview = clean_data(c.show.summary)
|
||||
ti_show.status = clean_data(c.show.status)
|
||||
ti_show.vote_average = clean_data((c.show.rating and c.show.rating.get('average'))) or None
|
||||
ti_show.rating = ti_show.vote_average
|
||||
net = c.show.network or c.show.web_channel
|
||||
ti_show.genre_list = clean_data(c.show.genres or [])
|
||||
ti_show.genre = '|'.join(ti_show.genre_list or [])
|
||||
ti_show.show_type = clean_data((
|
||||
isinstance(c.show.type, string_types) and [c.show.type.lower()] or
|
||||
isinstance(c.show.type, list) and [x.lower() for x in c.show.type] or []
|
||||
))
|
||||
if net:
|
||||
ti_show.network = clean_data(net.name)
|
||||
ti_show.network_id = net.maze_id
|
||||
|
@ -418,7 +436,18 @@ class TvMaze(TVInfoBase):
|
|||
ti_show.network_country_code = clean_data(net.code)
|
||||
ti_show.network_timezone = clean_data(net.timezone)
|
||||
ti_show.network_is_stream = None is not c.show.web_channel
|
||||
ch.append(TVInfoCharacter(name=clean_data(c.character.name), ti_show=ti_show, episode_count=1))
|
||||
_images = None
|
||||
if c.character.image and all(i_s in c.character.image and c.character.image[i_s]
|
||||
for i_s in ('original', 'medium')):
|
||||
_images = [TVInfoImage(TVInfoImageType.poster,
|
||||
sizes={TVInfoImageSize.original: c.character.image['original'],
|
||||
TVInfoImageSize.medium: c.character.image['medium']})]
|
||||
ch.append(TVInfoCharacter(name=self._clean_character_name(c.character.name),
|
||||
ti_show=ti_show, episode_count=1, plays_self=c.character.plays_self,
|
||||
voice=c.character.voice,
|
||||
image= c.character.image and c.character.image.get('original'),
|
||||
thumb_url= c.character.image and c.character.image.get('medium'),
|
||||
p_id=c.character.id, images=_images))
|
||||
try:
|
||||
birthdate = tvmaze_person_obj.birthday and tz_p.parse(tvmaze_person_obj.birthday).date()
|
||||
except (BaseException, Exception):
|
||||
|
@ -446,7 +475,7 @@ class TvMaze(TVInfoBase):
|
|||
(tvmaze_person_obj.guestcastcredits or [], False)]:
|
||||
for c in c_t: # type: tvmaze.CastCredit
|
||||
_show = c.show or c.episode.show
|
||||
_clean_char_name = clean_data(c.character.name)
|
||||
_clean_char_name = self._clean_character_name(c.character.name)
|
||||
ti_show = TVInfoShow()
|
||||
if None is not _show:
|
||||
_clean_show_name = clean_data(_show.name)
|
||||
|
@ -478,6 +507,8 @@ class TvMaze(TVInfoBase):
|
|||
ti_show.ids = TVInfoIDs(ids={TVINFO_TVMAZE: ti_show.id})
|
||||
ti_show.overview = enforce_type(clean_data(_show.summary), str, '')
|
||||
ti_show.status = clean_data(_show.status)
|
||||
ti_show.vote_average = clean_data(_show.rating and _show.rating.get('average')) or None
|
||||
ti_show.rating = ti_show.vote_average
|
||||
net = _show.network or _show.web_channel
|
||||
if net:
|
||||
ti_show.network = clean_data(net.name)
|
||||
|
@ -499,8 +530,18 @@ class TvMaze(TVInfoBase):
|
|||
_g_kw = {'guest_episodes_numbers': {c.episode.season_number: [c.episode.episode_number or 0]}}
|
||||
else:
|
||||
_g_kw = {}
|
||||
_images = None
|
||||
if c.character.image and all(i_s in c.character.image and c.character.image[i_s]
|
||||
for i_s in ('original', 'medium')):
|
||||
_images = [TVInfoImage(TVInfoImageType.poster,
|
||||
sizes={TVInfoImageSize.original: c.character.image['original'],
|
||||
TVInfoImageSize.medium: c.character.image['medium']})]
|
||||
ch.append(TVInfoCharacter(name=_clean_char_name, ti_show=ti_show, regular=regular, episode_count=1,
|
||||
person=[_ti_person_obj], **_g_kw))
|
||||
person=[_ti_person_obj], plays_self=c.character.plays_self,
|
||||
voice=c.character.voice,
|
||||
image=c.character.image and c.character.image.get('original'),
|
||||
thumb_url=c.character.image and c.character.image.get('medium'),
|
||||
p_id=c.character.id, images=_images, **_g_kw))
|
||||
_ti_person_obj.characters = ch
|
||||
return _ti_person_obj
|
||||
|
||||
|
@ -588,7 +629,7 @@ class TvMaze(TVInfoBase):
|
|||
else:
|
||||
_s_o.cast[RoleTypes.ActorMain].append(
|
||||
TVInfoCharacter(image=cur_ch.image and cur_ch.image.get('original'),
|
||||
name=clean_data(cur_ch.name),
|
||||
name=self._clean_character_name(cur_ch.name),
|
||||
ids=TVInfoIDs({TVINFO_TVMAZE: cur_ch.id}),
|
||||
p_id=cur_ch.id, person=[person], plays_self=cur_ch.plays_self,
|
||||
thumb_url=cur_ch.image and cur_ch.image.get('medium'),
|
||||
|
|
|
@ -12,6 +12,18 @@ if False:
|
|||
from typing import Any, AnyStr, Dict, List, Optional, Union
|
||||
|
||||
|
||||
url_maze_id_regex = re.compile(r'^https?://(?:(?:api|wwww)\.)?tvmaze\.com/shows/(\d+)', flags=re.I)
|
||||
|
||||
|
||||
def _parse_show_id_from_url(url):
|
||||
# type: (str) -> Optional[int]
|
||||
if isinstance(url, str):
|
||||
try:
|
||||
return int(url_maze_id_regex.search(url).group(1))
|
||||
except (BaseException, Exception):
|
||||
pass
|
||||
|
||||
|
||||
class Show(object):
|
||||
def __init__(self, data):
|
||||
self.status = data.get('status') # type: Optional[AnyStr]
|
||||
|
@ -36,7 +48,7 @@ class Show(object):
|
|||
self.runtime = data.get('runtime') # type: Optional[int]
|
||||
self.average_runtime = data.get('averageRuntime')
|
||||
self.type = data.get('type') # type: Optional[AnyStr]
|
||||
self.id = data.get('id') # type: int
|
||||
self.id = data.get('id') or ('href' in data and _parse_show_id_from_url(data['href'])) or None # type: int
|
||||
self.maze_id = self.id # type: int
|
||||
if data.get('network'):
|
||||
self.network = Network(data.get('network')) # type: Optional[Network]
|
||||
|
@ -428,9 +440,12 @@ class CastCredit(object):
|
|||
def populate(self, data):
|
||||
if data.get('_embedded'):
|
||||
if data['_embedded'].get('character'):
|
||||
self.character = Character(data['_embedded']['character'])
|
||||
self.character = Character(data['_embedded']['character'], base_data=data)
|
||||
if data['_embedded'].get('show'):
|
||||
self.show = Show(data['_embedded']['show'])
|
||||
elif ('episode' in data['_embedded'] and '_links' in data['_embedded']['episode'] and
|
||||
'show' in data['_embedded']['episode']['_links']):
|
||||
self.show = Show(data['_embedded']['episode']['_links']['show'])
|
||||
if data['_embedded'].get('episode'):
|
||||
self.episode = Episode(data['_embedded']['episode'])
|
||||
|
||||
|
|
|
@ -884,6 +884,7 @@ class PersonGenders(object):
|
|||
tmdb_map = {0: unknown, 1: female, 2: male}
|
||||
imdb_map = {'female': female, 'male': male}
|
||||
tvdb_map = {0: unknown, 1: male, 2: female, 3: unknown} # 3 is technically: other
|
||||
trakt_map = {'female': female, 'male': male}
|
||||
|
||||
|
||||
class Crew(PersonBase):
|
||||
|
|
|
@ -724,7 +724,7 @@ class Person(Referential):
|
|||
self._data_fetched = True
|
||||
tvsrc_result, found_persons, found_on_src, search_sources, \
|
||||
found_ids, ids_to_check, imdb_confirmed, source_confirmed = \
|
||||
None, {}, set(), [TVINFO_TRAKT, TVINFO_TMDB, TVINFO_IMDB, TVINFO_TVDB], \
|
||||
None, {}, set(), [TVINFO_TRAKT, TVINFO_TMDB, TVINFO_IMDB, TVINFO_TVDB, TVINFO_TVMAZE], \
|
||||
set([_k for _k, _v in iteritems(self.ids) if _v] + ['text']), {}, False, {}
|
||||
# confirmed_character = False
|
||||
max_search_src = len(search_sources)
|
||||
|
|
|
@ -4779,7 +4779,7 @@ class AddShows(Home):
|
|||
genres=', '.join(row.get('metadata', {}).get('genres', {})) or 'No genre yet',
|
||||
ids=ids,
|
||||
images='' if not img_uri else images,
|
||||
overview='No overview yet' if not overview else helpers.xhtml_escape(overview[:250:]),
|
||||
overview=self.clean_overview(overview),
|
||||
rating=int(helpers.try_float(rating) * 10),
|
||||
title=row.get('primary').get('title'),
|
||||
url_src_db='https://www.imdb.com/%s/' % row.get('primary').get('href').strip('/'),
|
||||
|
@ -4855,7 +4855,7 @@ class AddShows(Home):
|
|||
genres='',
|
||||
ids=ids,
|
||||
images='' if not img_uri else images,
|
||||
overview='No overview yet' if not overview else helpers.xhtml_escape(overview[:250:]),
|
||||
overview=self.clean_overview(overview),
|
||||
rating=0 if not len(rating) else int(helpers.try_float(rating) * 10),
|
||||
title=title,
|
||||
url_src_db='https://www.imdb.com/%s/' % url_path.strip('/'),
|
||||
|
@ -5040,6 +5040,19 @@ class AddShows(Home):
|
|||
f'?releaseYearMin={this_year}&releaseYearMax={this_year}{page}'
|
||||
html = helpers.get_url(url, headers={'User-Agent': browser_ua.get_ua()})
|
||||
if html:
|
||||
items_data = []
|
||||
try:
|
||||
items_html = html[6 + html.index('items:[{awards'):]
|
||||
items_bufr = re.split(r'\btype:"', items_html)
|
||||
for cur_item in items_bufr[1:]: # iterates from the first true type:"show" record
|
||||
if not cur_item.startswith('show'):
|
||||
break
|
||||
items_data.append(f'type:"{cur_item}')
|
||||
del items_html
|
||||
del items_bufr
|
||||
except (BaseException, Exception):
|
||||
pass
|
||||
|
||||
try:
|
||||
if re.findall('(c-navigationPagination_item--next)', html)[0]:
|
||||
kwargs.update(dict(more=1))
|
||||
|
@ -5053,7 +5066,7 @@ class AddShows(Home):
|
|||
rc_id = re.compile(r'(?i)[^A-Z0-9]')
|
||||
rc_img = re.compile(r'(.*?)(/resize/[^?]+)?(/catalog/provider.*?\.(?:jpg|png)).*')
|
||||
rc_season = re.compile(r'(\d+)(?:[.]\d*?)?$')
|
||||
for idx, cur_row in enumerate(items):
|
||||
for cur_idx, cur_row in enumerate(items):
|
||||
try:
|
||||
title = rc_title.sub(
|
||||
'', cur_row.find('div', class_='c-finderProductCard_title').get('data-title').strip())
|
||||
|
@ -5068,6 +5081,24 @@ class AddShows(Home):
|
|||
|
||||
images = None
|
||||
img_src = (cur_row.find('img') or {}).get('src', '').strip()
|
||||
if not img_src and items_data: # items_data is the sites' image method from 2024
|
||||
buffer_idx = None
|
||||
if title in items_data[cur_idx]:
|
||||
buffer_idx = cur_idx
|
||||
else:
|
||||
for cur_data_idx, cur_item in enumerate(items_data):
|
||||
if title in cur_item:
|
||||
buffer_idx = cur_data_idx
|
||||
break
|
||||
if None is not buffer_idx:
|
||||
try:
|
||||
img_rel = re.findall(
|
||||
r'bucketPath[^:]*?:[^"]*?"([^"]+?)"',
|
||||
items_data[buffer_idx], re.I)[0].encode().decode('unicode-escape')
|
||||
img_src = f'https://www.metacritic.com/a/img/catalog/{img_rel.strip("/")}'
|
||||
except (BaseException, Exception):
|
||||
pass
|
||||
|
||||
if img_src:
|
||||
img_uri = rc_img.sub(r'\1\3', img_src)
|
||||
images = dict(poster=dict(thumb=f'imagecache?path=browse/thumb/metac&source={img_uri}'))
|
||||
|
@ -5102,7 +5133,7 @@ class AddShows(Home):
|
|||
|
||||
overview = cur_row.find('div', class_='c-finderProductCard_description')
|
||||
if overview:
|
||||
overview = helpers.xhtml_escape(overview.get_text().strip()[:250:])
|
||||
overview = overview.get_text()
|
||||
|
||||
try:
|
||||
season = rc_season.findall(url_path)[0]
|
||||
|
@ -5117,7 +5148,7 @@ class AddShows(Home):
|
|||
genres='',
|
||||
ids=ids,
|
||||
images=images or '',
|
||||
overview=overview or 'No overview yet',
|
||||
overview=self.clean_overview(overview),
|
||||
rating=0 if not rating else rating or 'TBD',
|
||||
rating_user='tbd' if not rating_user else int(helpers.try_float(rating_user) * 10) or 'tbd',
|
||||
title=title,
|
||||
|
@ -5273,7 +5304,7 @@ class AddShows(Home):
|
|||
|
||||
genres = row.find(class_='genre')
|
||||
if genres:
|
||||
genres = re.sub(r',(\S)', r', \1', genres.get_text(strip=True))
|
||||
genres = re.sub(r',(\S)', r', \1', genres.get_text(strip=True)).lower()
|
||||
overview = row.find(class_='summary')
|
||||
if overview:
|
||||
overview = overview.get_text(strip=True)
|
||||
|
@ -5293,7 +5324,7 @@ class AddShows(Home):
|
|||
ids=ids,
|
||||
images='' if not img_uri else images,
|
||||
network=network or None,
|
||||
overview='No overview yet' if not overview else helpers.xhtml_escape(overview[:250:]),
|
||||
overview=self.clean_overview(overview),
|
||||
rating=(rating, 'TBD')[None is rating],
|
||||
title=title,
|
||||
url_src_db='https://next-episode.net/%s/' % url_path.strip('/'),
|
||||
|
@ -5319,9 +5350,21 @@ class AddShows(Home):
|
|||
|
||||
return self.new_show('|'.join(['', '', '', show_name]), use_show_name=True)
|
||||
|
||||
@staticmethod
|
||||
def _make_char_person_list(cur_show_info):
|
||||
# type: (TVInfoShow) -> List[Tuple[str, int, str, int]]
|
||||
return [(ch.name.replace('"', "'"), r_t, RoleTypes.reverse[r_t], ch.episode_count)
|
||||
for r_t in cur_show_info.cast or [] for ch in cur_show_info.cast[r_t] if ch.name]
|
||||
|
||||
@staticmethod
|
||||
def allow_browse_mru(mode_or_mru):
|
||||
# Fix an issue where a default view mixed with a deriviative view that requires a param will break the default
|
||||
# Disallows default views from using derivative mru's
|
||||
return 'person' not in mode_or_mru
|
||||
|
||||
def tmdb_default(self):
|
||||
method = getattr(self, sickgear.TMDB_MRU, None)
|
||||
if not callable(method):
|
||||
if not callable(method) or not self.allow_browse_mru(sickgear.TMDB_MRU):
|
||||
return self.tmdb_upcoming()
|
||||
return method()
|
||||
|
||||
|
@ -5347,7 +5390,7 @@ class AddShows(Home):
|
|||
|
||||
def tmdb_person(self, person_tmdb_id=None, **kwargs):
|
||||
return self.browse_tmdb(
|
||||
'Person at TMDB', mode='get_person', p_id=person_tmdb_id, **kwargs)
|
||||
'Person at TMDB', mode='person', p_id=person_tmdb_id, **kwargs)
|
||||
|
||||
def browse_tmdb(self, browse_title, **kwargs):
|
||||
|
||||
|
@ -5369,21 +5412,20 @@ class AddShows(Home):
|
|||
items = t.get_trending()
|
||||
elif 'trending_week' == mode:
|
||||
items = t.get_trending(time_window='week')
|
||||
elif 'get_person' == mode:
|
||||
elif 'person' == mode:
|
||||
items = []
|
||||
p_item = t.get_person(get_show_credits=True, **kwargs) # type: TVInfoPerson
|
||||
if p_item:
|
||||
p_ref = f'{TVINFO_TMDB}:{p_item.id}'
|
||||
dup = {} # type: Dict[int, TVInfoShow]
|
||||
for c in p_item.characters: # type: TVInfoCharacter
|
||||
c.ti_show.cast[RoleTypes.ActorMain].append(c)
|
||||
if c.ti_show.id not in dup:
|
||||
dup[c.ti_show.id] = c.ti_show
|
||||
items.append(c.ti_show)
|
||||
else:
|
||||
dup[c.ti_show.id].cast.update(c.ti_show.cast)
|
||||
dup[c.ti_show.id].cast[RoleTypes.ActorMain].extend(c.ti_show.cast[RoleTypes.ActorMain])
|
||||
del dup
|
||||
else:
|
||||
p_item = None
|
||||
else:
|
||||
items = t.discover()
|
||||
|
||||
|
@ -5400,7 +5442,10 @@ class AddShows(Home):
|
|||
airtime = cur_show_info.airs_time
|
||||
if not airtime or (0, 0) == (airtime.hour, airtime.minute):
|
||||
airtime = dateutil.parser.parse('23:59').time()
|
||||
dt = datetime.combine(dateutil.parser.parse(cur_show_info.firstaired, parseinfo).date(), airtime)
|
||||
try:
|
||||
dt = datetime.combine(dateutil.parser.parse(cur_show_info.firstaired, parseinfo).date(), airtime)
|
||||
except (BaseException, Exception):
|
||||
dt = None
|
||||
ord_premiered, str_premiered, started_past, oldest_dt, newest_dt, oldest, newest, _, _, _, _ \
|
||||
= self.sanitise_dates(dt, oldest_dt, newest_dt, oldest, newest)
|
||||
|
||||
|
@ -5416,20 +5461,17 @@ class AddShows(Home):
|
|||
language = ((cur_show_info.language and 'jap' in cur_show_info.language.lower())
|
||||
and 'jp' or 'en')
|
||||
filtered.append(dict(
|
||||
p_ref=p_ref,
|
||||
p_chars=[(ch.name, r_t, RoleTypes.reverse[r_t], ch.episode_count)
|
||||
for r_t in cur_show_info.cast or [] for ch in cur_show_info.cast[r_t]],
|
||||
ord_premiered=ord_premiered,
|
||||
str_premiered=str_premiered,
|
||||
started_past=started_past,
|
||||
episode_overview=helpers.xhtml_escape(cur_show_info.overview[:250:]).strip('*').strip(),
|
||||
episode_overview=self.clean_overview(cur_show_info),
|
||||
episode_season=cur_show_info.season,
|
||||
genres=', '.join(cur_show_info.genre_list)
|
||||
or (cur_show_info.genre and (cur_show_info.genre.strip('|').replace('|', ', ')) or ''),
|
||||
genres=(', '.join(cur_show_info.genre_list)
|
||||
or (cur_show_info.genre and (cur_show_info.genre.strip('|').replace('|', ', ')) or '')
|
||||
).lower(),
|
||||
ids=cur_show_info.ids.__dict__,
|
||||
images=images,
|
||||
overview=(helpers.xhtml_escape(cur_show_info.overview[:250:]).strip('*').strip()
|
||||
or 'No overview yet'),
|
||||
overview=self.clean_overview(cur_show_info),
|
||||
title=cur_show_info.seriesname,
|
||||
language=language,
|
||||
language_img=sickgear.MEMCACHE_FLAG_IMAGES.get(language, False),
|
||||
|
@ -5437,15 +5479,23 @@ class AddShows(Home):
|
|||
country_img=sickgear.MEMCACHE_FLAG_IMAGES.get(cc.lower(), False),
|
||||
network=network_name,
|
||||
url_src_db=base_url % cur_show_info.id,
|
||||
votes=cur_show_info.popularity or 0,
|
||||
rating=0 < (cur_show_info.rating or 0) and
|
||||
('%.2f' % (cur_show_info.rating * 10)).replace('.00', '') or 0,
|
||||
votes=('%.2f' % cur_show_info.popularity) or 0,
|
||||
))
|
||||
if p_ref:
|
||||
filtered[-1].update(dict(
|
||||
p_name=p_item.name,
|
||||
p_ref=p_ref,
|
||||
p_chars=self._make_char_person_list(cur_show_info)
|
||||
))
|
||||
except (BaseException, Exception):
|
||||
pass
|
||||
kwargs.update(dict(oldest=oldest, newest=newest, use_ratings=False, use_filter=True, term_vote='Score'))
|
||||
kwargs.update(dict(oldest=oldest, newest=newest, use_filter=True, term_vote='Score'))
|
||||
|
||||
kwargs.update(dict(footnote=footnote, use_networks=use_networks))
|
||||
|
||||
if mode:
|
||||
if mode and self.allow_browse_mru(mode):
|
||||
func = 'tmdb_%s' % mode
|
||||
if callable(getattr(self, func, None)):
|
||||
sickgear.TMDB_MRU = func
|
||||
|
@ -5460,7 +5510,7 @@ class AddShows(Home):
|
|||
|
||||
def trakt_default(self):
|
||||
method = getattr(self, sickgear.TRAKT_MRU, None)
|
||||
if not callable(method):
|
||||
if not callable(method) or not self.allow_browse_mru(sickgear.TMDB_MRU):
|
||||
return self.trakt_trending()
|
||||
return method()
|
||||
|
||||
|
@ -5592,7 +5642,7 @@ class AddShows(Home):
|
|||
if not items:
|
||||
error_msg = 'No items in watchlist. Use the "Add to watchlist" button at the Trakt website'
|
||||
raise ValueError(error_msg)
|
||||
elif 'get_person' == api_method:
|
||||
elif 'person' == mode:
|
||||
items = []
|
||||
p_item = t.get_person(get_show_credits=True, **kwargs) # type: TVInfoPerson
|
||||
if p_item:
|
||||
|
@ -5602,11 +5652,7 @@ class AddShows(Home):
|
|||
if c.ti_show.id not in dup:
|
||||
dup[c.ti_show.id] = c.ti_show
|
||||
items.append(c.ti_show)
|
||||
else:
|
||||
dup[c.ti_show.id].cast.update(c.ti_show.cast)
|
||||
del dup
|
||||
else:
|
||||
p_item = None
|
||||
else:
|
||||
items = t.get_trending()
|
||||
except TraktAuthException as e:
|
||||
|
@ -5662,10 +5708,6 @@ class AddShows(Home):
|
|||
images = {} if not image else dict(poster=dict(thumb=image))
|
||||
|
||||
filtered.append(dict(
|
||||
p_ref=p_ref,
|
||||
p_item=p_item,
|
||||
p_chars=[(ch.name, r_t, RoleTypes.reverse[r_t], ch.episode_count)
|
||||
for r_t in cur_show_info.cast or [] for ch in cur_show_info.cast[r_t]],
|
||||
ord_premiered=ord_premiered,
|
||||
str_premiered=str_premiered,
|
||||
ord_returning=ord_returning,
|
||||
|
@ -5673,14 +5715,13 @@ class AddShows(Home):
|
|||
started_past=started_past, # air time not yet available 16.11.2015
|
||||
return_past=return_past,
|
||||
episode_number=episode_info.episodenumber,
|
||||
episode_overview=helpers.xhtml_escape(episode_info.overview[:250:]).strip('*').strip(),
|
||||
episode_overview=self.clean_overview(episode_info),
|
||||
episode_season=getattr(episode_info.season, 'number', 1),
|
||||
genres=(', '.join(['%s' % v for v in cur_show_info.genre_list])),
|
||||
ids=cur_show_info.ids.__dict__,
|
||||
images=images,
|
||||
network=network_name,
|
||||
overview=(helpers.xhtml_escape(cur_show_info.overview[:250:]).strip('*').strip()
|
||||
or 'No overview yet'),
|
||||
overview=self.clean_overview(cur_show_info),
|
||||
rating=0 < (cur_show_info.rating or 0) and
|
||||
('%.2f' % (cur_show_info.rating * 10)).replace('.00', '') or 0,
|
||||
title=(cur_show_info.seriesname or '').strip(),
|
||||
|
@ -5692,7 +5733,14 @@ class AddShows(Home):
|
|||
url_tvdb=(
|
||||
'' if not (isinstance(cur_show_info.ids.tvdb, integer_types) and 0 < cur_show_info.ids.tvdb)
|
||||
else sickgear.TVInfoAPI(TVINFO_TVDB).config['show_url'] % cur_show_info.ids.tvdb),
|
||||
votes=cur_show_info.vote_count or '0'))
|
||||
votes=cur_show_info.vote_count or '0'
|
||||
))
|
||||
if p_ref:
|
||||
filtered[-1].update(dict(
|
||||
p_name=p_item.name,
|
||||
p_ref=p_ref,
|
||||
p_chars=self._make_char_person_list(cur_show_info)
|
||||
))
|
||||
except (BaseException, Exception):
|
||||
pass
|
||||
|
||||
|
@ -5705,7 +5753,7 @@ class AddShows(Home):
|
|||
|
||||
return self.browse_trakt(
|
||||
'get_person',
|
||||
'Person on Trakt',
|
||||
'Person at Trakt',
|
||||
mode='person',
|
||||
footnote='Note; Expect default placeholder images in this list',
|
||||
p_id=person_trakt_id
|
||||
|
@ -5728,14 +5776,11 @@ class AddShows(Home):
|
|||
error_msg = 'No items in watchlist. Use the "Add to watchlist" button at the Trakt website'
|
||||
return self.browse_shows(browse_type, browse_title, filtered, error_msg=error_msg, show_header=1, **kwargs)
|
||||
|
||||
if 'get_person' == api_method and filtered:
|
||||
browse_title = f'{getattr(filtered[0]["p_item"], "name", "")} (Person) on Trakt'
|
||||
|
||||
kwargs.update(dict(oldest=oldest, newest=newest, error_msg=error_msg, use_networks=use_networks))
|
||||
|
||||
if not any(m in mode for m in ('recommended', 'watchlist', 'person')):
|
||||
mode = mode.split('-')
|
||||
if mode:
|
||||
if mode and self.allow_browse_mru(mode):
|
||||
func = 'trakt_%s' % mode[0]
|
||||
if callable(getattr(self, func, None)):
|
||||
param = '' if 1 == len(mode) or mode[1] not in ['year', 'month', 'week', 'all'] else \
|
||||
|
@ -5944,7 +5989,7 @@ class AddShows(Home):
|
|||
network=network or None,
|
||||
ids=ids,
|
||||
images='' if not img_uri else images,
|
||||
overview='No overview yet' if not overview else helpers.xhtml_escape(overview[:250:]),
|
||||
overview=self.clean_overview(overview),
|
||||
rating=None,
|
||||
title=title,
|
||||
url_src_db='https://www.pogdesign.co.uk/%s' % url_path.strip('/'),
|
||||
|
@ -5972,7 +6017,7 @@ class AddShows(Home):
|
|||
|
||||
def tvm_default(self):
|
||||
method = getattr(self, sickgear.TVM_MRU, None)
|
||||
if not callable(method):
|
||||
if not callable(method) or not self.allow_browse_mru(sickgear.TMDB_MRU):
|
||||
return self.tvm_premieres()
|
||||
return method()
|
||||
|
||||
|
@ -5986,7 +6031,52 @@ class AddShows(Home):
|
|||
|
||||
def tvm_person(self, person_tvm_id=None, **kwargs):
|
||||
return self.browse_tvm(
|
||||
'Person at TVmaze', mode='get_person', p_id=person_tvm_id, **kwargs)
|
||||
'Person at TVmaze', mode='person', p_id=person_tvm_id, **kwargs)
|
||||
|
||||
@staticmethod
|
||||
def clean_overview(info=None):
|
||||
# type (AnyStr, TVInfoShow) -> AnyStr
|
||||
text = info if isinstance(info, str) else info.overview
|
||||
if text:
|
||||
result = helpers.xhtml_escape(re.sub(r'[\r\n]+', ' ', text[:250:])).strip('*').strip()
|
||||
result = re.sub(r'([!?.])(?=\w)', r'\1 ', result)
|
||||
result = re.sub(r'([,.!][^,.!]*?)$', '...', result)
|
||||
return result.replace('.....', '...')
|
||||
return 'No overview yet'
|
||||
|
||||
def tvm_get_showinfo(self, tvid_prodid=None, oldest_dt=9999999, newest_dt=0):
|
||||
result = {}
|
||||
if 'tvmaze' in tvid_prodid:
|
||||
tvid = TVINFO_TVMAZE
|
||||
tvinfo_config = sickgear.TVInfoAPI(tvid).api_params.copy()
|
||||
t = sickgear.TVInfoAPI(tvid).setup(**tvinfo_config) # type: Union[TvmazeIndexer, TVInfoBase]
|
||||
show_info = t.get_show(int(tvid_prodid.replace('tvmaze:','')), load_episodes=False)
|
||||
|
||||
oldest_dt, newest_dt = int(oldest_dt), int(newest_dt)
|
||||
ord_premiered, str_premiered, started_past, old_dt, new_dt, oldest, newest, \
|
||||
ok_returning, ord_returning, str_returning, return_past \
|
||||
= self.sanitise_dates(show_info.firstaired, oldest_dt, newest_dt, None, None)
|
||||
result = dict(
|
||||
ord_premiered=ord_premiered,
|
||||
str_premiered=str_premiered,
|
||||
#ord_returning=ord_returning,
|
||||
#str_returning=str_returning,
|
||||
started_past=started_past,
|
||||
#return_past=return_past,
|
||||
genres=((show_info.genre or '')
|
||||
or ', '.join(show_info.genre_list)
|
||||
or ', '.join(show_info.show_type) or '').strip('|').replace('|', ', ').lower(),
|
||||
overview=self.clean_overview(show_info),
|
||||
network=show_info.network or ', '.join(show_info.networks) or '',
|
||||
)
|
||||
if old_dt < oldest_dt:
|
||||
result['oldest_dt'] = old_dt
|
||||
result['oldest'] = oldest
|
||||
elif new_dt > newest_dt:
|
||||
result['newest_dt'] = old_dt
|
||||
result['newest'] = newest,
|
||||
|
||||
return json_dumps(result)
|
||||
|
||||
def browse_tvm(self, browse_title, **kwargs):
|
||||
|
||||
|
@ -6002,30 +6092,31 @@ class AddShows(Home):
|
|||
t = sickgear.TVInfoAPI(tvid).setup(**tvinfo_config) # type: Union[TvmazeIndexer, TVInfoBase]
|
||||
if 'premieres' == mode:
|
||||
items = t.get_premieres()
|
||||
elif 'get_person' == mode:
|
||||
elif 'person' == mode:
|
||||
items = []
|
||||
p_item = t.get_person(get_show_credits=True, **kwargs) # type: TVInfoPerson
|
||||
if p_item:
|
||||
p_ref = f'{TVINFO_TVMAZE}:{p_item.id}'
|
||||
dup = {} # type: Dict[int, TVInfoShow]
|
||||
for c in p_item.characters: # type: TVInfoCharacter
|
||||
c.ti_show.cast[(RoleTypes.ActorGuest, RoleTypes.ActorMain)[True is c.regular]].append(c)
|
||||
if c.ti_show.id not in dup:
|
||||
dup[c.ti_show.id] = c.ti_show
|
||||
items.append(c.ti_show)
|
||||
else:
|
||||
dup[c.ti_show.id].cast.update(c.ti_show.cast)
|
||||
dup[c.ti_show.id].cast[RoleTypes.ActorMain].extend(c.ti_show.cast[RoleTypes.ActorMain])
|
||||
dup[c.ti_show.id].cast[RoleTypes.ActorGuest].extend(c.ti_show.cast[RoleTypes.ActorGuest])
|
||||
del dup
|
||||
else:
|
||||
p_item = None
|
||||
else:
|
||||
items = t.get_returning()
|
||||
|
||||
# handle switching between returning and premieres
|
||||
sickgear.BROWSELIST_MRU.setdefault(browse_type, dict())
|
||||
showfilter = ('by_returning', 'by_premiered')['premieres' == mode]
|
||||
saved_showsort = sickgear.BROWSELIST_MRU[browse_type].get('tvm_%s' % mode) or '*,asc'
|
||||
showsort = saved_showsort + (',%s' % showfilter, '')[3 == len(saved_showsort.split(','))]
|
||||
sickgear.BROWSELIST_MRU[browse_type].update(dict(showfilter=showfilter, showsort=showsort))
|
||||
if mode in ('premieres', 'returning'):
|
||||
showfilter = ('by_returning', 'by_premiered')['premieres' == mode]
|
||||
saved_showsort = sickgear.BROWSELIST_MRU[browse_type].get('tvm_%s' % mode) or '*,asc'
|
||||
showsort = saved_showsort + (f',{showfilter}', '')[3 == len(saved_showsort.split(','))]
|
||||
sickgear.BROWSELIST_MRU[browse_type].update(dict(showfilter=showfilter, showsort=showsort))
|
||||
|
||||
oldest, newest, oldest_dt, newest_dt, dedupe = None, None, 9999999, 0, []
|
||||
use_networks = False
|
||||
|
@ -6048,7 +6139,7 @@ class AddShows(Home):
|
|||
if 'returning' == mode and not ok_returning:
|
||||
continue
|
||||
|
||||
image = self._make_cache_image_url(tvid, cur_show_info, use_source_id='get_person' == mode)
|
||||
image = self._make_cache_image_url(tvid, cur_show_info, use_source_id='person' == mode)
|
||||
images = {} if not image else dict(poster=dict(thumb=image))
|
||||
|
||||
network_name = cur_show_info.network
|
||||
|
@ -6061,10 +6152,11 @@ class AddShows(Home):
|
|||
|
||||
language = (('jap' in (cur_show_info.language or '').lower()) and 'jp' or 'en')
|
||||
|
||||
overview = self.clean_overview(cur_show_info)
|
||||
overview_ajax = ("No overview yet" == overview
|
||||
and p_ref and not bool(cur_show_info.cast[RoleTypes.ActorMain]))
|
||||
|
||||
filtered.append(dict(
|
||||
p_ref=p_ref,
|
||||
p_chars=[(ch.name, r_t, RoleTypes.reverse[r_t], ch.episode_count)
|
||||
for r_t in cur_show_info.cast or [] for ch in cur_show_info.cast[r_t]],
|
||||
ord_premiered=ord_premiered,
|
||||
str_premiered=str_premiered,
|
||||
ord_returning=ord_returning,
|
||||
|
@ -6072,14 +6164,15 @@ class AddShows(Home):
|
|||
started_past=started_past,
|
||||
return_past=return_past,
|
||||
episode_number=episode_info.episodenumber or '',
|
||||
episode_overview=helpers.xhtml_escape(episode_info.overview[:250:]).strip(),
|
||||
episode_overview=self.clean_overview(episode_info),
|
||||
episode_season=getattr(episode_info.season, 'number', episode_info.seasonnumber),
|
||||
genres=((cur_show_info.genre or '').strip('|').replace('|', ', ')
|
||||
or ', '.join(cur_show_info.show_type) or ''),
|
||||
genres=((cur_show_info.genre or '')
|
||||
or ', '.join(cur_show_info.genre_list)
|
||||
or ', '.join(cur_show_info.show_type) or '').strip('|').replace('|', ', ').lower(),
|
||||
ids=cur_show_info.ids.__dict__,
|
||||
images=images,
|
||||
overview=(helpers.xhtml_escape(cur_show_info.overview[:250:]).strip('*').strip()
|
||||
or 'No overview yet'),
|
||||
overview_ajax=(0, 1)[overview_ajax],
|
||||
overview=overview,
|
||||
rating=cur_show_info.rating or cur_show_info.popularity or 0,
|
||||
title=cur_show_info.seriesname,
|
||||
language=language,
|
||||
|
@ -6089,13 +6182,23 @@ class AddShows(Home):
|
|||
network=network_name,
|
||||
url_src_db=base_url % cur_show_info.id,
|
||||
))
|
||||
if p_ref:
|
||||
filtered[-1].update(dict(
|
||||
p_name=p_item.name or None,
|
||||
p_ref=p_ref,
|
||||
p_chars=self._make_char_person_list(cur_show_info)
|
||||
))
|
||||
except (BaseException, Exception):
|
||||
pass
|
||||
kwargs.update(dict(oldest=oldest, newest=newest))
|
||||
|
||||
kwargs.update(dict(footnote=footnote, use_votes=False, use_networks=use_networks))
|
||||
kwargs.update(dict(oldest=oldest, newest=newest, oldest_dt=oldest_dt, newest_dt=newest_dt))
|
||||
|
||||
if mode:
|
||||
params = dict(footnote=footnote, use_votes=False, use_networks=use_networks)
|
||||
if p_ref:
|
||||
params.update(dict(use_ratings=False))
|
||||
kwargs.update(params)
|
||||
|
||||
if mode and self.allow_browse_mru(mode):
|
||||
func = 'tvm_%s' % mode
|
||||
if callable(getattr(self, func, None)):
|
||||
sickgear.TVM_MRU = func
|
||||
|
@ -6110,6 +6213,9 @@ class AddShows(Home):
|
|||
|
||||
@staticmethod
|
||||
def sanitise_dates(date, oldest_dt, newest_dt, oldest, newest, episode_info=None, combine_ep_airtime=False):
|
||||
# in case of person search (tvmaze) guest starring entires have only show name/id, no dates
|
||||
if None is date:
|
||||
return 9, '', True, oldest_dt, newest_dt, oldest, newest, True, 9, 'TBC', False
|
||||
parseinfo = dateutil.parser.parserinfo(dayfirst=False, yearfirst=True)
|
||||
dt = date if isinstance(date, datetime) else dateutil.parser.parse(date)
|
||||
if episode_info:
|
||||
|
@ -6189,7 +6295,8 @@ class AddShows(Home):
|
|||
t = PageTemplate(web_handler=self, file='home_browseShows.tmpl')
|
||||
t.submenu = self.home_menu()
|
||||
t.browse_type = browse_type
|
||||
t.browse_title = browse_title
|
||||
t.browse_title = browse_title if ('person' != kwargs.get('mode') or not shows) \
|
||||
else f'{shows[0].get("p_name", "")} (Person) on {browse_type}'
|
||||
t.p_ref = (0 < len(shows) and shows[0].get('p_ref')) or None
|
||||
t.saved_showfilter = sickgear.BROWSELIST_MRU.get(browse_type, {}).get('showfilter', '')
|
||||
t.saved_showsort = sickgear.BROWSELIST_MRU.get(browse_type, {}).get('showsort', '*,asc,by_order')
|
||||
|
|
Loading…
Reference in a new issue