Browse Source

Merge branch 'feature/ChangeDiskCacheTVmaze' into develop

tags/release_0.25.1
JackDandy 4 years ago
parent
commit
1cf2ae809b
  1. 2
      CHANGES.md
  2. 24
      gui/slick/interfaces/default/home_browseShows.tmpl
  3. 56
      lib/api_tvmaze/tvmaze_api.py
  4. 17
      lib/tvinfo_base/base.py
  5. 42
      sickbeard/webserve.py

2
CHANGES.md

@ -83,6 +83,7 @@
* Add show name/networks card user input filter
* Change only auto refresh card view if a recoverable error occurs
* Update Requests library 2.25.1 (bdc00eb) to 2.26.0 (b0e025a)
* Fix handling of card filters and sort states
[develop changelog]
@ -93,6 +94,7 @@
* Fix genre field in tvmaze_api
* Change api interface folders to api_* to fix legacy tmdb_api folder cleanup on new installs
* 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)

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

@ -102,7 +102,7 @@ $(document).ready(function(){
});
#raw
$('#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) {
case 'asc':
case 'desc':
@ -119,15 +119,13 @@ $(document).ready(function(){
#end if
break;
#if $use_ratings
case 'rating':
shuffle = !0;
break;
#if $use_votes
case 'rating_votes':
sortCriteria = ['rating', 'votes'];
#end if
case 'rating':
shuffle = !0;
break;
#end if
#end if
default:
sortCriteria = 'name'
@ -140,21 +138,21 @@ $(document).ready(function(){
option$ = showSort.filter('option[value="asc"].selected, option[value="desc"].selected');
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());
savePrefs();
el$.one('layoutComplete', llUpdate);
el$.isotope({
sortAscending: 'asc' === this.value,
sortAscending: 'asc' === elValue,
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$.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());
savePrefs();
@ -184,12 +182,12 @@ $(document).ready(function(){
option$ = showSort.filter($('option[value^="*"].selected, #showsort option[value^="."].selected'));
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());
savePrefs();
var showCards = $('.show-card'), filter = this.value;
var showCards = $('.show-card'), filter = elValue;
if('.hide' === filter){
showCards.filter($('.hide')).removeClass('hide').addClass('to-hide');
filter = '.to-hide';
@ -278,7 +276,7 @@ $(document).ready(function(){
}
});
});
$('.resetshows').click(function() {
$('.resetshows').click(function() {
var input = $('#search_show_name');
if ('' !== input.val()){
input.val('').trigger('input').change();
@ -324,7 +322,7 @@ $(document).ready(function(){
</optgroup>
<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>
# omit for TVMaze as Original == First Aired
## omit for TVMaze as original order == First Aired
#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>
#end if

56
lib/api_tvmaze/tvmaze_api.py

@ -14,6 +14,7 @@ import requests
from urllib3.util.retry import Retry
from requests.adapters import HTTPAdapter
from _23 import filter_iter
from six import integer_types, iteritems, string_types
from sg_helpers import get_url, try_int
from lib.dateutil.parser import parser
@ -549,18 +550,16 @@ class TvMaze(TVInfoBase):
if 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]
return self._filtered_schedule(lambda e: all([1 == e.season_number, 1 == e.episode_number]),
get_images=get_extra_images)
return self._filtered_schedule(**kwargs).get('premieres')
def get_returning(self, result_count=100, get_extra_images=False, **kwargs):
def get_returning(self, **kwargs):
# type: (...) -> List[TVInfoEpisode]
return self._filtered_schedule(lambda e: all([1 != e.season_number, 1 == e.episode_number]),
get_images=get_extra_images)
return self._filtered_schedule(**kwargs).get('returning')
def _make_episode(self, episode_data, show_data=None, get_images=False):
# type: (TVMazeEpisode, TVMazeShow, bool) -> TVInfoEpisode
def _make_episode(self, episode_data, show_data=None, get_images=False, get_akas=False):
# type: (TVMazeEpisode, TVMazeShow, bool, bool) -> TVInfoEpisode
"""
make out of TVMazeEpisode object and optionally TVMazeShow a TVInfoEpisode
"""
@ -581,7 +580,8 @@ class TvMaze(TVInfoBase):
ti_show.show_type = show_data.type
ti_show.lastupdated = show_data.updated
ti_show.poster = show_data.image and show_data.image.get('original')
ti_show.aliases = [a.name for a in show_data.akas]
if get_akas:
ti_show.aliases = [a.name for a in show_data.akas]
if 'days' in show_data.schedule:
ti_show.airs_dayofweek = ', '.join(show_data.schedule['days'])
network = show_data.network or show_data.web_channel
@ -656,12 +656,32 @@ class TvMaze(TVInfoBase):
ti_episode.show = ti_show
return ti_episode
def _filtered_schedule(self, condition, get_images=False):
try:
result = sorted([
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):
return []
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:
schedule = tvmaze.get_full_schedule()
except(BaseException, Exception):
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

17
lib/tvinfo_base/base.py

@ -384,6 +384,18 @@ class TVInfoShow(dict):
return results
def __getstate__(self):
d = dict(self.__dict__)
try:
del d['lock']
except (BaseException, Exception):
pass
return d
def __setstate__(self, d):
self.__dict__ = d
self.lock = threading.RLock()
__repr__ = __str__
__nonzero__ = __bool__
@ -795,6 +807,7 @@ class TVInfoBase(object):
self.diskcache = diskcache.Cache(directory=self._cachedir, disk_pickle_protocol=2) # type: diskcache.Cache
self.cache_expire = 60 * 60 * 18 # type: integer_types
self.search_cache_expire = 60 * 15 # type: integer_types
self.schedule_cache_expire = 60 * 30 # type: integer_types
self.config = {
'apikey': '',
'debug_enabled': False,
@ -1156,14 +1169,14 @@ class TVInfoBase(object):
# type: (...) -> List[TVInfoEpisode]
return []
def get_premieres(self, result_count=100, **kwargs):
def get_premieres(self, **kwargs):
# type: (...) -> List[TVInfoEpisode]
"""
get all premiering shows
"""
return []
def get_returning(self, result_count=100, get_extra_images=False, **kwargs):
def get_returning(self, **kwargs):
# type: (...) -> List[TVInfoShow]
"""
get all returning shows

42
sickbeard/webserve.py

@ -5187,28 +5187,19 @@ class AddShows(Home):
footnote = None
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()
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
tvinfo_config = sickbeard.TVInfoAPI(TVINFO_TVMAZE).api_params.copy()
t = sickbeard.TVInfoAPI(TVINFO_TVMAZE).setup(**tvinfo_config)
if 'New' in browse_title:
episodes = card_cache('tvmaze_premiere')
episodes = t.get_premieres()
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
dedupe = []
@ -5680,8 +5671,12 @@ class AddShows(Home):
save_config = False
if browse_type in ('AniDB', 'IMDb', 'Metacritic', 'Trakt', 'TVCalendar', 'TVmaze', 'Nextepisode'):
save_config = True
sickbeard.BROWSELIST_MRU[browse_type] = dict(
showfilter=kwargs.get('showfilter', ''), showsort=kwargs.get('showsort', ''))
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(
showfilter=kwargs.get('showfilter', ''), showsort=kwargs.get('showsort', ''))
if save_config:
sickbeard.save_config()
return json.dumps({'success': save_config})
@ -5700,8 +5695,7 @@ class AddShows(Home):
showsort = t.saved_showsort.split(',')
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)
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)
or 'rating' in t.saved_showsort_sortby and not kwargs.get('use_ratings', True))
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.all_shows = []

Loading…
Cancel
Save