Browse Source

Change use diskcache instead of memcache for TVmaze cards.

Change disable AKAs for TVmaze cards since each calls the API and are not needed here.
Fix handling of card filters and sort states.
tags/release_0.25.1
JackDandy 4 years ago
parent
commit
4a1a9eea60
  1. 2
      CHANGES.md
  2. 22
      gui/slick/interfaces/default/home_browseShows.tmpl
  3. 50
      lib/api_tvmaze/tvmaze_api.py
  4. 5
      lib/tvinfo_base/base.py
  5. 34
      sickbeard/webserve.py

2
CHANGES.md

@ -83,6 +83,7 @@
* Add show name/networks card user input filter * Add show name/networks card user input filter
* Change only auto refresh card view if a recoverable error occurs * Change only auto refresh card view if a recoverable error occurs
* Update Requests library 2.25.1 (bdc00eb) to 2.26.0 (b0e025a) * Update Requests library 2.25.1 (bdc00eb) to 2.26.0 (b0e025a)
* Fix handling of card filters and sort states
[develop changelog] [develop changelog]
@ -93,6 +94,7 @@
* Fix genre field in tvmaze_api * Fix genre field in tvmaze_api
* Change api interface folders to api_* to fix legacy tmdb_api folder cleanup on new installs * Change api interface folders to api_* to fix legacy tmdb_api folder cleanup on new installs
* Fix TVmaze genres property to be lowercase string * Fix TVmaze genres property to be lowercase string
* Change use diskcache instead of memcache for TVmaze cards
### 0.24.15 (2021-08-05 11:45:00 UTC) ### 0.24.15 (2021-08-05 11:45:00 UTC)

22
gui/slick/interfaces/default/home_browseShows.tmpl

@ -102,7 +102,7 @@ $(document).ready(function(){
}); });
#raw #raw
$('#showsort').on('change', function(){ $('#showsort').on('change', function(){
var sortCriteria = this.value.replace('by_', ''), el$ = $('#container'), shuffle = !1; var elValue = this.value, sortCriteria = elValue.replace('by_', ''), el$ = $('#container'), shuffle = !1;
switch (sortCriteria) { switch (sortCriteria) {
case 'asc': case 'asc':
case 'desc': case 'desc':
@ -119,16 +119,14 @@ $(document).ready(function(){
#end if #end if
break; break;
#if $use_ratings #if $use_ratings
case 'rating':
shuffle = !0;
break;
#if $use_votes #if $use_votes
case 'rating_votes': case 'rating_votes':
sortCriteria = ['rating', 'votes']; sortCriteria = ['rating', 'votes'];
#end if
case 'rating':
shuffle = !0; shuffle = !0;
break; break;
#end if #end if
#end if
default: default:
sortCriteria = 'name' sortCriteria = 'name'
break; break;
@ -140,21 +138,21 @@ $(document).ready(function(){
option$ = showSort.filter('option[value="asc"].selected, option[value="desc"].selected'); option$ = showSort.filter('option[value="asc"].selected, option[value="desc"].selected');
option$.removeClass('selected').removeAttr('selected').html(option$.text().replace(/^>\s/i, '')); option$.removeClass('selected').removeAttr('selected').html(option$.text().replace(/^>\s/i, ''));
option$ = showSort.filter($('option[value="' + this.value + '"]')); option$ = showSort.filter($('option[value="' + elValue + '"]'));
option$.addClass('selected').attr('selected', !0).html('> ' + option$.text()); option$.addClass('selected').attr('selected', !0).html('> ' + option$.text());
savePrefs(); savePrefs();
el$.one('layoutComplete', llUpdate); el$.one('layoutComplete', llUpdate);
el$.isotope({ el$.isotope({
sortAscending: 'asc' === this.value, sortAscending: 'asc' === elValue,
sortBy: showSort.filter($('option[value^="by_"][class*="selected"]')).val().replace('by_', '') sortBy: showSort.filter($('option[value^="by_"][class*="selected"]')).val().replace('by_', '')
}); });
} else if(0 == this.value.indexOf('by_')){ } else if(0 == elValue.indexOf('by_')){
option$ = showSort.filter($('option[value^="by_"][class*="selected"]')); option$ = showSort.filter($('option[value^="by_"][class*="selected"]'));
option$.removeClass('selected').removeAttr('selected').html(option$.text().replace(/^>\s/i, '')); option$.removeClass('selected').removeAttr('selected').html(option$.text().replace(/^>\s/i, ''));
option$ = showSort.filter($('option[value="' + this.value + '"]')); option$ = showSort.filter($('option[value="' + elValue + '"]'));
option$.addClass('selected').attr('selected', !0).html('> ' + option$.text()); option$.addClass('selected').attr('selected', !0).html('> ' + option$.text());
savePrefs(); savePrefs();
@ -184,12 +182,12 @@ $(document).ready(function(){
option$ = showSort.filter($('option[value^="*"].selected, #showsort option[value^="."].selected')); option$ = showSort.filter($('option[value^="*"].selected, #showsort option[value^="."].selected'));
option$.removeClass('selected').removeAttr('selected').html(option$.text().replace(/^>\s/i, '')); option$.removeClass('selected').removeAttr('selected').html(option$.text().replace(/^>\s/i, ''));
option$ = showSort.filter($('option[value="' + this.value + '"]')); option$ = showSort.filter($('option[value="' + elValue + '"]'));
option$.addClass('selected').attr('selected', !0).html('> ' + option$.text()); option$.addClass('selected').attr('selected', !0).html('> ' + option$.text());
savePrefs(); savePrefs();
var showCards = $('.show-card'), filter = this.value; var showCards = $('.show-card'), filter = elValue;
if('.hide' === filter){ if('.hide' === filter){
showCards.filter($('.hide')).removeClass('hide').addClass('to-hide'); showCards.filter($('.hide')).removeClass('hide').addClass('to-hide');
filter = '.to-hide'; filter = '.to-hide';
@ -324,7 +322,7 @@ $(document).ready(function(){
</optgroup> </optgroup>
<optgroup label="Sort by"> <optgroup label="Sort by">
<option value="by_name"#if 'by_name' in $saved_showsort_sortby and not $reset_showsort_sortby#$selected>>&nbsp;#else#>#end if#Name</option> <option value="by_name"#if 'by_name' in $saved_showsort_sortby and not $reset_showsort_sortby#$selected>>&nbsp;#else#>#end if#Name</option>
# omit for TVMaze as Original == First Aired ## omit for TVMaze as original order == First Aired
#if 'TVmaze' not in $browse_type #if 'TVmaze' not in $browse_type
<option value="by_order"#if 'by_order' in $saved_showsort_sortby or $reset_showsort_sortby#$selected>>&nbsp;#else#>#end if#Original</option> <option value="by_order"#if 'by_order' in $saved_showsort_sortby or $reset_showsort_sortby#$selected>>&nbsp;#else#>#end if#Original</option>
#end if #end if

50
lib/api_tvmaze/tvmaze_api.py

@ -14,6 +14,7 @@ import requests
from urllib3.util.retry import Retry from urllib3.util.retry import Retry
from requests.adapters import HTTPAdapter from requests.adapters import HTTPAdapter
from _23 import filter_iter
from six import integer_types, iteritems, string_types from six import integer_types, iteritems, string_types
from sg_helpers import get_url, try_int from sg_helpers import get_url, try_int
from lib.dateutil.parser import parser from lib.dateutil.parser import parser
@ -549,18 +550,16 @@ class TvMaze(TVInfoBase):
if p: if p:
return self._convert_person(p) return self._convert_person(p)
def get_premieres(self, result_count=100, get_extra_images=False, **kwargs): def get_premieres(self, **kwargs):
# type: (...) -> List[TVInfoEpisode] # type: (...) -> List[TVInfoEpisode]
return self._filtered_schedule(lambda e: all([1 == e.season_number, 1 == e.episode_number]), return self._filtered_schedule(**kwargs).get('premieres')
get_images=get_extra_images)
def get_returning(self, result_count=100, get_extra_images=False, **kwargs): def get_returning(self, **kwargs):
# type: (...) -> List[TVInfoEpisode] # type: (...) -> List[TVInfoEpisode]
return self._filtered_schedule(lambda e: all([1 != e.season_number, 1 == e.episode_number]), return self._filtered_schedule(**kwargs).get('returning')
get_images=get_extra_images)
def _make_episode(self, episode_data, show_data=None, get_images=False): def _make_episode(self, episode_data, show_data=None, get_images=False, get_akas=False):
# type: (TVMazeEpisode, TVMazeShow, bool) -> TVInfoEpisode # type: (TVMazeEpisode, TVMazeShow, bool, bool) -> TVInfoEpisode
""" """
make out of TVMazeEpisode object and optionally TVMazeShow a TVInfoEpisode make out of TVMazeEpisode object and optionally TVMazeShow a TVInfoEpisode
""" """
@ -581,6 +580,7 @@ class TvMaze(TVInfoBase):
ti_show.show_type = show_data.type ti_show.show_type = show_data.type
ti_show.lastupdated = show_data.updated ti_show.lastupdated = show_data.updated
ti_show.poster = show_data.image and show_data.image.get('original') ti_show.poster = show_data.image and show_data.image.get('original')
if get_akas:
ti_show.aliases = [a.name for a in show_data.akas] ti_show.aliases = [a.name for a in show_data.akas]
if 'days' in show_data.schedule: if 'days' in show_data.schedule:
ti_show.airs_dayofweek = ', '.join(show_data.schedule['days']) ti_show.airs_dayofweek = ', '.join(show_data.schedule['days'])
@ -656,12 +656,32 @@ class TvMaze(TVInfoBase):
ti_episode.show = ti_show ti_episode.show = ti_show
return ti_episode return ti_episode
def _filtered_schedule(self, condition, get_images=False): def _filtered_schedule(self, **kwargs):
cache_name_key = 'tvmaze_schedule'
is_none, schedule = self._get_cache_entry(cache_name_key)
if None is schedule and not is_none:
schedule = []
try: try:
result = sorted([ schedule = 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))],
key=lambda x: x.show.premiered or x.airstamp)
return [self._make_episode(r, r.show, get_images) for r in result]
except(BaseException, Exception): except(BaseException, Exception):
return [] pass
premieres = []
returning = []
rc_lang = re.compile('(?i)eng|jap')
for cur_show in filter_iter(lambda s: 1 == s.episode_number and (
None is s.show.language or rc_lang.search(s.show.language)), schedule):
if 1 == cur_show.season_number:
premieres += [cur_show]
else:
returning += [cur_show]
premieres = [self._make_episode(r, r.show, **kwargs)
for r in sorted(premieres, key=lambda e: e.show.premiered)]
returning = [self._make_episode(r, r.show, **kwargs)
for r in sorted(returning, key=lambda e: e.airstamp)]
schedule = dict(premieres=premieres, returning=returning)
self._set_cache_entry(cache_name_key, schedule, expire=self.schedule_cache_expire)
return schedule

5
lib/tvinfo_base/base.py

@ -807,6 +807,7 @@ class TVInfoBase(object):
self.diskcache = diskcache.Cache(directory=self._cachedir, disk_pickle_protocol=2) # type: diskcache.Cache self.diskcache = diskcache.Cache(directory=self._cachedir, disk_pickle_protocol=2) # type: diskcache.Cache
self.cache_expire = 60 * 60 * 18 # type: integer_types self.cache_expire = 60 * 60 * 18 # type: integer_types
self.search_cache_expire = 60 * 15 # type: integer_types self.search_cache_expire = 60 * 15 # type: integer_types
self.schedule_cache_expire = 60 * 30 # type: integer_types
self.config = { self.config = {
'apikey': '', 'apikey': '',
'debug_enabled': False, 'debug_enabled': False,
@ -1168,14 +1169,14 @@ class TVInfoBase(object):
# type: (...) -> List[TVInfoEpisode] # type: (...) -> List[TVInfoEpisode]
return [] return []
def get_premieres(self, result_count=100, **kwargs): def get_premieres(self, **kwargs):
# type: (...) -> List[TVInfoEpisode] # type: (...) -> List[TVInfoEpisode]
""" """
get all premiering shows get all premiering shows
""" """
return [] return []
def get_returning(self, result_count=100, get_extra_images=False, **kwargs): def get_returning(self, **kwargs):
# type: (...) -> List[TVInfoShow] # type: (...) -> List[TVInfoShow]
""" """
get all returning shows get all returning shows

34
sickbeard/webserve.py

@ -5187,28 +5187,19 @@ class AddShows(Home):
footnote = None footnote = None
filtered = [] filtered = []
def card_cache(mem_key):
# noinspection PyProtectedMember
from lib.dateutil.tz.tz import _datetime_to_timestamp
now = int(_datetime_to_timestamp(datetime.datetime.now()))
if (sickbeard.MEMCACHE.get(mem_key, {}).get('data')
and (now < sickbeard.MEMCACHE.get(mem_key, {}).get('expire', 0))):
return sickbeard.MEMCACHE.get(mem_key).get('data')
tvinfo_config = sickbeard.TVInfoAPI(TVINFO_TVMAZE).api_params.copy() tvinfo_config = sickbeard.TVInfoAPI(TVINFO_TVMAZE).api_params.copy()
t = sickbeard.TVInfoAPI(TVINFO_TVMAZE).setup(**tvinfo_config) t = sickbeard.TVInfoAPI(TVINFO_TVMAZE).setup(**tvinfo_config)
if 'prem' in mem_key:
data = t.get_premieres()
else:
data = t.get_returning()
sickbeard.MEMCACHE[mem_key] = dict(expire=(30*60) + now, data=data)
return data
if 'New' in browse_title: if 'New' in browse_title:
episodes = card_cache('tvmaze_premiere') episodes = t.get_premieres()
else: else:
episodes = card_cache('tvmaze_returning') episodes = t.get_returning()
# handle switching between returning and premieres
sickbeard.BROWSELIST_MRU.setdefault(browse_type, dict())
showfilter = ('by_returning', 'by_premiered')['New' in browse_title]
saved_showsort = sickbeard.BROWSELIST_MRU[browse_type].get('tvm_%s' % kwargs['mode']) or '*,asc'
showsort = saved_showsort + (',%s' % showfilter, '')[3 == len(saved_showsort.split(','))]
sickbeard.BROWSELIST_MRU[browse_type].update(dict(showfilter=showfilter, showsort=showsort))
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 = []
@ -5680,6 +5671,10 @@ class AddShows(Home):
save_config = False save_config = False
if browse_type in ('AniDB', 'IMDb', 'Metacritic', 'Trakt', 'TVCalendar', 'TVmaze', 'Nextepisode'): if browse_type in ('AniDB', 'IMDb', 'Metacritic', 'Trakt', 'TVCalendar', 'TVmaze', 'Nextepisode'):
save_config = True save_config = True
if browse_type in ('TVmaze',) and kwargs.get('showfilter') and kwargs.get('showsort'):
sickbeard.BROWSELIST_MRU.setdefault(browse_type, dict()) \
.update({kwargs.get('showfilter'): kwargs.get('showsort')})
else:
sickbeard.BROWSELIST_MRU[browse_type] = dict( sickbeard.BROWSELIST_MRU[browse_type] = dict(
showfilter=kwargs.get('showfilter', ''), showsort=kwargs.get('showsort', '')) showfilter=kwargs.get('showfilter', ''), showsort=kwargs.get('showsort', ''))
if save_config: if save_config:
@ -5700,8 +5695,7 @@ class AddShows(Home):
showsort = t.saved_showsort.split(',') showsort = t.saved_showsort.split(',')
t.saved_showsort_sortby = 3 == len(showsort) and showsort[2] or 'by_order' t.saved_showsort_sortby = 3 == len(showsort) and showsort[2] or 'by_order'
t.reset_showsort_sortby = ('votes' in t.saved_showsort_sortby and not kwargs.get('use_votes', True) t.reset_showsort_sortby = ('votes' in t.saved_showsort_sortby and not kwargs.get('use_votes', True)
or 'rating' in t.saved_showsort_sortby and not kwargs.get('use_ratings', True) or 'rating' in t.saved_showsort_sortby and not kwargs.get('use_ratings', True))
or 'returning' in t.saved_showsort_sortby and 'Returning' not in browse_title)
t.is_showsort_desc = ('desc' == (2 <= len(showsort) and showsort[1] or 'asc')) and not t.reset_showsort_sortby t.is_showsort_desc = ('desc' == (2 <= len(showsort) and showsort[1] or 'asc')) and not t.reset_showsort_sortby
t.saved_showsort_view = 1 <= len(showsort) and showsort[0] or '*' t.saved_showsort_view = 1 <= len(showsort) and showsort[0] or '*'
t.all_shows = [] t.all_shows = []

Loading…
Cancel
Save