Skip to content

Commit ca5c8c2

Browse files
authored
Attempt to use json.load(fd) again (#624)
* Attempt to use json.load(fdesc) again This PR includes: - Use json.load(fdesc) - Early exit in tokenresolver * Support json HTTP error responses * Attempt to use json.load(fdesc) again This PR includes: - Use json.load(fdesc) - Early exit in tokenresolver - Move caching functionality to utils.py - Fix 2 issues - Return default value on failure - Fix more json.load() calls for Python 3.5
1 parent 2d04db2 commit ca5c8c2

File tree

17 files changed

+457
-467
lines changed

17 files changed

+457
-467
lines changed

resources/lib/addon.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111
from urllib import unquote_plus
1212

1313
from kodiutils import localize, log_access, notification, refresh_caches
14-
from statichelper import from_unicode, to_unicode
14+
from utils import from_unicode, to_unicode
1515

1616
plugin = Plugin() # pylint: disable=invalid-name
1717

resources/lib/addon_entry.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,8 @@
33
''' This is the actual VRT NU video plugin entry point '''
44

55
from __future__ import absolute_import, division, unicode_literals
6-
import kodiutils
76
import xbmcaddon
7+
import kodiutils
88

99
kodiutils.ADDON = xbmcaddon.Addon()
1010

resources/lib/apihelper.py

Lines changed: 26 additions & 57 deletions
Original file line numberDiff line numberDiff line change
@@ -5,21 +5,20 @@
55
from __future__ import absolute_import, division, unicode_literals
66

77
try: # Python 3
8-
from urllib.error import HTTPError
98
from urllib.parse import quote_plus, unquote
10-
from urllib.request import build_opener, install_opener, ProxyHandler, Request, urlopen
9+
from urllib.request import build_opener, install_opener, ProxyHandler, urlopen
1110
except ImportError: # Python 2
1211
from urllib import quote_plus
13-
from urllib2 import build_opener, install_opener, ProxyHandler, Request, HTTPError, unquote, urlopen
12+
from urllib2 import build_opener, install_opener, ProxyHandler, unquote, urlopen
1413

1514
from data import CHANNELS
1615
from helperobjects import TitleItem
17-
from kodiutils import (delete_cached_thumbnail, get_cache, get_global_setting, get_proxies, get_setting,
18-
has_addon, localize, localize_from_data, log, log_error, ok_dialog, ttl, update_cache,
19-
url_for)
20-
from statichelper import (add_https_method, convert_html_to_kodilabel, find_entry, from_unicode, play_url_to_id,
21-
program_to_url, realpage, to_unicode, strip_newlines, url_to_program)
16+
from kodiutils import (delete_cached_thumbnail, get_cache, get_cached_url_json, get_global_setting,
17+
get_proxies, get_setting, get_url_json, has_addon, localize, localize_from_data,
18+
log, ttl, update_cache, url_for)
2219
from metadata import Metadata
20+
from utils import (add_https_proto, html_to_kodilabel, find_entry, from_unicode, play_url_to_id,
21+
program_to_url, realpage, strip_newlines, url_to_program)
2322

2423

2524
class ApiHelper:
@@ -39,7 +38,7 @@ def __init__(self, _favorites, _resumepoints):
3938

4039
def get_tvshows(self, category=None, channel=None, feature=None):
4140
''' Get all TV shows for a given category, channel or feature, optionally filtered by favorites '''
42-
params = dict()
41+
params = {}
4342

4443
if category:
4544
params['facets[categories]'] = category
@@ -57,16 +56,10 @@ def get_tvshows(self, category=None, channel=None, feature=None):
5756
if not category and not channel and not feature:
5857
params['facets[transcodingStatus]'] = 'AVAILABLE' # Required for getting results in Suggests API
5958
cache_file = 'programs.json'
60-
tvshows = get_cache(cache_file, ttl=ttl('indirect')) # Try the cache if it is fresh
61-
if not tvshows:
62-
from json import loads
63-
querystring = '&'.join('{}={}'.format(key, value) for key, value in list(params.items()))
64-
suggest_url = self._VRTNU_SUGGEST_URL + '?' + querystring
65-
log(2, 'URL get: {url}', url=unquote(suggest_url))
66-
tvshows = loads(to_unicode(urlopen(suggest_url).read()))
67-
update_cache(cache_file, tvshows)
6859

69-
return tvshows
60+
querystring = '&'.join('{}={}'.format(key, value) for key, value in list(params.items()))
61+
suggest_url = self._VRTNU_SUGGEST_URL + '?' + querystring
62+
return get_cached_url_json(url=suggest_url, cache=cache_file, ttl=ttl('indirect'), fail=[])
7063

7164
def list_tvshows(self, category=None, channel=None, feature=None, use_favorites=False):
7265
''' List all TV shows for a given category, channel or feature, optionally filtered by favorites '''
@@ -151,7 +144,7 @@ def __map_episodes(self, episodes, titletype=None, season=None, use_favorites=Fa
151144
highlight = episode.get('highlight')
152145
if highlight:
153146
for key in highlight:
154-
episode[key] = convert_html_to_kodilabel(highlight.get(key)[0])
147+
episode[key] = html_to_kodilabel(highlight.get(key)[0])
155148

156149
list_item, sort, ascending = self.episode_to_listitem(episode, program, cache_file, titletype)
157150
episode_items.append(list_item)
@@ -268,7 +261,7 @@ def get_upnext(self, info):
268261

269262
# Get all episodes from current program and sort by program, seasonTitle and episodeNumber
270263
episodes = sorted(self.get_episodes(keywords=program), key=lambda k: (k.get('program'), k.get('seasonTitle'), k.get('episodeNumber')))
271-
upnext = dict()
264+
upnext = {}
272265
for episode in episodes:
273266
if ep_id.get('whatson_id') == episode.get('whatsonId') or \
274267
ep_id.get('video_id') == episode.get('videoId') or \
@@ -413,8 +406,7 @@ def get_episode_by_air_date(self, channel_name, start_date, end_date=None):
413406
schedule_date = onairdate
414407
schedule_datestr = schedule_date.isoformat().split('T')[0]
415408
url = 'https://www.vrt.be/bin/epg/schedule.%s.json' % schedule_datestr
416-
from json import loads
417-
schedule_json = loads(to_unicode(urlopen(url).read()))
409+
schedule_json = get_url_json(url, fail={})
418410
episodes = schedule_json.get(channel.get('id'), [])
419411
if not episodes:
420412
return None
@@ -569,41 +561,17 @@ def get_episodes(self, program=None, season=None, episodes=None, category=None,
569561
# Construct VRT NU Search API Url and get api data
570562
querystring = '&'.join('{}={}'.format(key, value) for key, value in list(params.items()))
571563
search_url = self._VRTNU_SEARCH_URL + '?' + querystring.replace(' ', '%20') # Only encode spaces to minimize url length
572-
573-
from json import loads
574564
if cache_file:
575-
# Get api data from cache if it is fresh
576-
search_json = get_cache(cache_file, ttl=ttl('indirect'))
577-
if not search_json:
578-
log(2, 'URL get: {url}', url=unquote(search_url))
579-
req = Request(search_url)
580-
try:
581-
search_json = loads(to_unicode(urlopen(req).read()))
582-
except (TypeError, ValueError): # No JSON object could be decoded
583-
return []
584-
except HTTPError as exc:
585-
url_length = len(req.get_selector())
586-
if exc.code == 413 and url_length > 8192:
587-
ok_dialog(heading='HTTP Error 413', message=localize(30967))
588-
log_error('HTTP Error 413: Exceeded maximum url length: '
589-
'VRT Search API url has a length of {length} characters.', length=url_length)
590-
return []
591-
if exc.code == 400 and 7600 <= url_length <= 8192:
592-
ok_dialog(heading='HTTP Error 400', message=localize(30967))
593-
log_error('HTTP Error 400: Probably exceeded maximum url length: '
594-
'VRT Search API url has a length of {length} characters.', length=url_length)
595-
return []
596-
raise
597-
update_cache(cache_file, search_json)
565+
search_json = get_cached_url_json(url=search_url, cache=cache_file, ttl=ttl('indirect'), fail={})
598566
else:
599-
log(2, 'URL get: {url}', url=unquote(search_url))
600-
search_json = loads(to_unicode(urlopen(search_url).read()))
567+
search_json = get_url_json(url=search_url, fail={})
601568

602569
# Check for multiple seasons
603-
seasons = None
570+
seasons = []
604571
if 'facets[seasonTitle]' not in unquote(search_url):
605-
facets = search_json.get('facets', dict()).get('facets')
606-
seasons = next((f.get('buckets', []) for f in facets if f.get('name') == 'seasons' and len(f.get('buckets', [])) > 1), None)
572+
facets = search_json.get('facets', {}).get('facets')
573+
if facets:
574+
seasons = next((f.get('buckets', []) for f in facets if f.get('name') == 'seasons' and len(f.get('buckets', [])) > 1), None)
607575

608576
episodes = search_json.get('results', [{}])
609577
show_seasons = bool(season != 'allseasons')
@@ -619,8 +587,9 @@ def get_episodes(self, program=None, season=None, episodes=None, category=None,
619587
if all_items and total_results > api_page_size:
620588
for api_page in range(1, api_pages):
621589
api_page_url = search_url + '&from=' + str(api_page * api_page_size + 1)
622-
api_page_json = loads(to_unicode(urlopen(api_page_url).read()))
623-
episodes += api_page_json.get('results', [{}])
590+
api_page_json = get_url_json(api_page_url)
591+
if api_page_json is not None:
592+
episodes += api_page_json.get('results', [{}])
624593

625594
# Return episodes
626595
return episodes
@@ -642,7 +611,7 @@ def list_channels(self, channels=None, live=True):
642611
continue
643612

644613
context_menu = []
645-
art_dict = dict()
614+
art_dict = {}
646615

647616
# Try to use the white icons for thumbnails (used for icons as well)
648617
if has_addon('resource.images.studios.white'):
@@ -713,7 +682,7 @@ def list_youtube(channels=None):
713682
continue
714683

715684
context_menu = []
716-
art_dict = dict()
685+
art_dict = {}
717686

718687
# Try to use the white icons for thumbnails (used for icons as well)
719688
if has_addon('resource.images.studios.white'):
@@ -850,7 +819,7 @@ def get_category_thumbnail(element):
850819
''' Return a category thumbnail, if available '''
851820
if get_setting('showfanart', 'true') == 'true':
852821
raw_thumbnail = element.find(class_='media').get('data-responsive-image', 'DefaultGenre.png')
853-
return add_https_method(raw_thumbnail)
822+
return add_https_proto(raw_thumbnail)
854823
return 'DefaultGenre.png'
855824

856825
@staticmethod

resources/lib/favorites.py

Lines changed: 10 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -11,9 +11,9 @@
1111
except ImportError: # Python 2
1212
from urllib2 import build_opener, install_opener, ProxyHandler, Request, unquote, urlopen
1313

14-
from kodiutils import (container_refresh, get_cache, get_proxies, get_setting, has_credentials,
15-
input_down, invalidate_caches, localize, log, log_error, multiselect,
16-
notification, ok_dialog, to_unicode, update_cache)
14+
from kodiutils import (container_refresh, get_cache, get_proxies, get_setting, get_url_json,
15+
has_credentials, input_down, invalidate_caches, localize, log, log_error,
16+
multiselect, notification, ok_dialog, update_cache)
1717

1818

1919
class Favorites:
@@ -43,17 +43,9 @@ def refresh(self, ttl=None):
4343
'content-type': 'application/json',
4444
'Referer': 'https://www.vrt.be/vrtnu',
4545
}
46-
req = Request('https://video-user-data.vrt.be/favorites', headers=headers)
47-
log(2, 'URL get: https://video-user-data.vrt.be/favorites')
48-
from json import loads
49-
try:
50-
favorites_json = loads(to_unicode(urlopen(req).read()))
51-
except (TypeError, ValueError): # No JSON object could be decoded
52-
# Force favorites from cache
53-
favorites_json = get_cache('favorites.json', ttl=None)
54-
else:
55-
update_cache('favorites.json', favorites_json)
56-
if favorites_json:
46+
favorites_url = 'https://video-user-data.vrt.be/favorites'
47+
favorites_json = get_url_json(url=favorites_url, cache='favorites.json', headers=headers)
48+
if favorites_json is not None:
5749
self._favorites = favorites_json
5850

5951
def update(self, program, title, value=True):
@@ -78,9 +70,9 @@ def update(self, program, title, value=True):
7870
'Referer': 'https://www.vrt.be/vrtnu',
7971
}
8072

81-
from statichelper import program_to_url
82-
payload = dict(isFavorite=value, programUrl=program_to_url(program, 'short'), title=title)
8373
from json import dumps
74+
from utils import program_to_url
75+
payload = dict(isFavorite=value, programUrl=program_to_url(program, 'short'), title=title)
8476
data = dumps(payload).encode('utf-8')
8577
program_id = self.program_to_id(program)
8678
log(2, 'URL post: https://video-user-data.vrt.be/favorites/{program_id}', program_id=program_id)
@@ -132,12 +124,12 @@ def titles(self):
132124

133125
def programs(self):
134126
''' Return all favorite programs '''
135-
from statichelper import url_to_program
127+
from utils import url_to_program
136128
return [url_to_program(value.get('value').get('programUrl')) for value in list(self._favorites.values()) if value.get('value').get('isFavorite')]
137129

138130
def manage(self):
139131
''' Allow the user to unselect favorites to be removed from the listing '''
140-
from statichelper import url_to_program
132+
from utils import url_to_program
141133
self.refresh(ttl=0)
142134
if not self._favorites:
143135
ok_dialog(heading=localize(30418), message=localize(30419)) # No favorites found

0 commit comments

Comments
 (0)