Skip to content

Commit

Permalink
always use programUrl (instead of programName)
Browse files Browse the repository at this point in the history
  • Loading branch information
mediaminister committed Jun 11, 2019
1 parent 7104fd9 commit e82a84a
Show file tree
Hide file tree
Showing 9 changed files with 155 additions and 135 deletions.
55 changes: 24 additions & 31 deletions resources/lib/favorites.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
''' Implementation of Favorites class '''

from __future__ import absolute_import, division, unicode_literals
from resources.lib import statichelper

try: # Python 3
from urllib.request import build_opener, install_opener, ProxyHandler, Request, urlopen
Expand Down Expand Up @@ -54,12 +55,12 @@ def get_favorites(self, ttl=None):
self._kodi.update_cache('favorites.json', api_json)
self._favorites = api_json

def set_favorite(self, program, path, value=True):
def set_favorite(self, title, program, value=True):
''' Set a program as favorite, and update local copy '''
import json

self.get_favorites(ttl=60 * 60)
if value is self.is_favorite(path):
if value is self.is_favorite(program):
# Already followed/unfollowed, nothing to do
return True

Expand All @@ -74,63 +75,55 @@ def set_favorite(self, program, path, value=True):
'content-type': 'application/json',
'Referer': 'https://www.vrt.be/vrtnu',
}
payload = dict(isFavorite=value, programUrl=path, title=program)
payload = dict(isFavorite=value, programUrl=statichelper.program_to_url(program, 'short'), title=title)
data = json.dumps(payload).encode('utf-8')
self._kodi.log_notice('URL post: https://video-user-data.vrt.be/favorites/%s' % self.uuid(path), 'Verbose')
req = Request('https://video-user-data.vrt.be/favorites/%s' % self.uuid(path), data=data, headers=headers)
self._kodi.log_notice('URL post: https://video-user-data.vrt.be/favorites/%s' % self.uuid(program), 'Verbose')
req = Request('https://video-user-data.vrt.be/favorites/%s' % self.uuid(program), data=data, headers=headers)
result = urlopen(req)
if result.getcode() != 200:
self._kodi.show_notification(message="Failed to (un)follow program '%s' at VRT NU" % path)
self._kodi.log_error("Failed to (un)follow program '%s' at VRT NU" % path)
self._kodi.show_notification(message="Failed to (un)follow program '%s' at VRT NU" % program)
self._kodi.log_error("Failed to (un)follow program '%s' at VRT NU" % program)
return False
# NOTE: Updates to favorites take a longer time to take effect, so we keep our own cache and use it
self._favorites[self.uuid(path)] = dict(value=payload)
self._favorites[self.uuid(program)] = dict(value=payload)
self._kodi.update_cache('favorites.json', self._favorites)
self.invalidate_caches()
return True

def is_favorite(self, path):
def is_favorite(self, program):
''' Is a program a favorite ? '''
value = False
favorite = self._favorites.get(self.uuid(path))
favorite = self._favorites.get(self.uuid(program))
if favorite is not None:
value = favorite.get('value', dict(isFavorite=False)).get('isFavorite', False)
return value

def follow(self, program, path):
def follow(self, title, program):
''' Follow your favorite program '''
ok = self.set_favorite(program, path, True)
ok = self.set_favorite(title, program, True)
if ok:
self._kodi.show_notification(message='Follow ' + program)
self._kodi.show_notification(message='Follow ' + title)
self._kodi.container_refresh()

def unfollow(self, program, path):
def unfollow(self, title, program):
''' Unfollow your favorite program '''
ok = self.set_favorite(program, path, False)
ok = self.set_favorite(title, program, False)
if ok:
self._kodi.show_notification(message='Unfollow ' + program)
self._kodi.show_notification(message='Unfollow ' + title)
self._kodi.container_refresh()

def uuid(self, path):
''' Return a favorite uuid, used for lookups in favorites dict '''
return path.replace('/', '').replace('-', '')

def name(self, path):
''' Return the favorite name '''
try:
return path.replace('.relevant/', '/').split('/')[-2]
except IndexError:
# FIXME: Investigate when this fails !
return path

def names(self):
''' Return all favorite names '''
return [self.name(p.get('value').get('programUrl')) for p in self._favorites.values() if p.get('value').get('isFavorite')]
def uuid(self, program):
''' Convert a program url component (e.g. de-campus-cup) to a favorite uuid (e.g. vrtnuazdecampuscup), used for lookups in favorites dict '''
return 'vrtnuaz' + program.replace('-', '')

def titles(self):
''' Return all favorite titles '''
return [p.get('value').get('title') for p in self._favorites.values() if p.get('value').get('isFavorite')]

def programs(self):
''' Return all favorite programs '''
return [statichelper.url_to_program(p.get('value').get('programUrl')) for p in self._favorites.values() if p.get('value').get('isFavorite')]

def invalidate_caches(self):
''' Invalidate caches that rely on favorites '''
# NOTE/ Do not invalidate favorites cache as we manage it ourselves
Expand Down
8 changes: 4 additions & 4 deletions resources/lib/router.py
Original file line number Diff line number Diff line change
Expand Up @@ -49,10 +49,10 @@ def router(argv):

# Actions requiring _favorites as well
if action == actions.FOLLOW:
_favorites.follow(program=params.get('program'), path=params.get('path'))
_favorites.follow(title=params.get('title'), program=params.get('program'))
return
if action == actions.UNFOLLOW:
_favorites.unfollow(program=params.get('program'), path=params.get('path'))
_favorites.unfollow(title=params.get('title'), program=params.get('program'))
return
if action == actions.REFRESH_FAVORITES:
_favorites.get_favorites(ttl=0)
Expand Down Expand Up @@ -109,11 +109,11 @@ def router(argv):
return
if action == actions.LISTING_EPISODES:
_favorites.get_favorites(ttl=60 * 60)
_vrtplayer.show_episodes(path=params.get('video_url'))
_vrtplayer.show_episodes(program=params.get('program'), season=params.get('season'))
return
if action == actions.LISTING_ALL_EPISODES:
_favorites.get_favorites(ttl=60 * 60)
_vrtplayer.show_all_episodes(path=params.get('video_url'))
_vrtplayer.show_all_episodes(program=params.get('program'))
return
if action == actions.SEARCH:
_favorites.get_favorites(ttl=60 * 60)
Expand Down
35 changes: 30 additions & 5 deletions resources/lib/statichelper.py
Original file line number Diff line number Diff line change
Expand Up @@ -34,11 +34,36 @@ def convert_html_to_kodilabel(text):
return unescape(text).strip()


def unique_path(path):
''' Create a unique path to be used in VRT favorites '''
if path.startswith('//www.vrt.be/vrtnu'):
return path.replace('//www.vrt.be/vrtnu/', '/vrtnu/').replace('.relevant/', '/')
return path
def program_to_url(program, url_type):
''' Convert a program url component (e.g. de-campus-cup) to a short programUrl (e.g. /vrtnu/a-z/de-campus-cup/)
or to a long programUrl (e.g. //www.vrt.be/vrtnu/a-z/de-campus-cup/)
'''
url = None
if program:
# short programUrl
if url_type == 'short':
url = '/vrtnu/a-z/' + program + '/'
# long programUrl
elif url_type == 'long':
url = '//www.vrt.be/vrtnu/a-z/' + program + '/'
return url


def url_to_program(url):
''' Convert a targetUrl (e.g. //www.vrt.be/vrtnu/a-z/de-campus-cup.relevant/), a short programUrl (e.g. /vrtnu/a-z/de-campus-cup/)
or a long programUrl (e.g. //www.vrt.be/vrtnu/a-z/de-campus-cup/) to a program url component (e.g. de-campus-cup)
'''
program = None
# targetUrl
if url.startswith('//www.vrt.be/vrtnu/a-z/') and url.endswith('.relevant/'):
program = url.replace('//www.vrt.be/vrtnu/a-z/', '').replace('.relevant/', '')
# short programUrl
elif url.startswith('/vrtnu/a-z/'):
program = url.replace('/vrtnu/a-z/', '').rstrip('/')
# long programUrl
elif url.startswith('//www.vrt.be/vrtnu/a-z/'):
program = url.replace('//www.vrt.be/vrtnu/a-z/', '').rstrip('/')
return program


def shorten_link(url):
Expand Down
84 changes: 37 additions & 47 deletions resources/lib/vrtapihelper.py
Original file line number Diff line number Diff line change
Expand Up @@ -65,9 +65,10 @@ def _map_to_tvshow_items(self, tvshows, use_favorites=False):
''' Construct a list of TV show TitleItems based on Suggests API query and filtered by favorites '''
tvshow_items = []
if statichelper.boolean(use_favorites):
favorite_names = self._favorites.names()
programs = self._favorites.programs()
for tvshow in tvshows:
if statichelper.boolean(use_favorites) and tvshow.get('programName') not in favorite_names:
program = statichelper.url_to_program(tvshow.get('targetUrl'))
if statichelper.boolean(use_favorites) and program not in programs:
continue
metadata = metadatacreator.MetadataCreator()
metadata.tvshowtitle = tvshow.get('title', '???')
Expand All @@ -82,35 +83,31 @@ def _map_to_tvshow_items(self, tvshows, use_favorites=False):
else:
thumbnail = 'DefaultAddonVideo.png'
if self._favorites.is_activated():
program_path = statichelper.unique_path(tvshow.get('targetUrl'))
program = tvshow.get('title').encode('utf-8')
if self._favorites.is_favorite(program_path):
params = dict(action='unfollow', program=program, path=program_path)
title = tvshow.get('title').encode('utf-8')
if self._favorites.is_favorite(program):
params = dict(action='unfollow', title=title, program=program)
context_menu = [(self._kodi.localize(30412), 'RunPlugin(plugin://plugin.video.vrt.nu?%s)' % urlencode(params))]
else:
params = dict(action='follow', program=program, path=program_path)
params = dict(action='follow', title=title, program=program)
context_menu = [(self._kodi.localize(30411), 'RunPlugin(plugin://plugin.video.vrt.nu?%s)' % urlencode(params))]
else:
context_menu = []
# Cut vrtbase url off since it will be added again when searching for episodes
# (with a-z we dont have the full url)
video_url = statichelper.add_https_method(tvshow.get('targetUrl')).replace(self._VRT_BASE, '')
tvshow_items.append(TitleItem(
title=label,
url_dict=dict(action=actions.LISTING_EPISODES, video_url=video_url),
url_dict=dict(action=actions.LISTING_EPISODES, program=program),
is_playable=False,
art_dict=dict(thumb=thumbnail, icon='DefaultAddonVideo.png', fanart=thumbnail),
video_dict=metadata.get_video_dict(),
context_menu=context_menu,
))
return tvshow_items

def get_latest_episode(self, tvshow):
def get_latest_episode(self, program):
''' Get the latest episode of a program '''
import json
video = None
params = {
'facets[programName]': tvshow,
'facets[programUrl]': statichelper.program_to_url(program, 'long'),
'i': 'video',
'size': '1',
}
Expand All @@ -122,10 +119,9 @@ def get_latest_episode(self, tvshow):
video = dict(video_id=episode.get('videoId'), publication_id=episode.get('publicationId'))
return video

def get_episode_items(self, path=None, page=None, show_seasons=False, use_favorites=False, variety=None):
def get_episode_items(self, program=None, season=None, page=None, show_seasons=False, use_favorites=False, variety=None):
''' Construct a list of TV show episodes TitleItems based on API query and filtered by favorites '''
titletype = None
season_key = None
all_items = True
episode_items = []
sort = 'episode'
Expand All @@ -150,7 +146,8 @@ def get_episode_items(self, path=None, page=None, show_seasons=False, use_favori
params['facets[assetOffTime]'] = datetime.now(dateutil.tz.gettz('Europe/Brussels')).strftime('%Y-%m-%d')

if statichelper.boolean(use_favorites):
params['facets[programName]'] = '[%s]' % (','.join(self._favorites.names()))
program_urls = [statichelper.program_to_url(p, 'long') for p in self._favorites.programs()]
params['facets[programUrl]'] = '[%s]' % (','.join(program_urls))
cache_file = 'my-%s-%s.json' % (variety, page)
else:
params['facets[programBrands]'] = '[%s]' % (','.join(self._channel_filter))
Expand All @@ -165,28 +162,23 @@ def get_episode_items(self, path=None, page=None, show_seasons=False, use_favori
api_json = json.load(urlopen(api_url))
self._kodi.update_cache(cache_file, api_json)
return self._map_to_episode_items(api_json.get('results', []), titletype=variety, use_favorites=use_favorites)
if program:
params = {
'facets[programUrl]': statichelper.program_to_url(program, 'long'),
'i': 'video',
'size': '150',
}
if season:
params.update({'facets[seasonTitle]': season})

if path:
if '.relevant/' in path:
params = {
'facets[programUrl]': '//www.vrt.be' + path.replace('.relevant/', '/'),
'i': 'video',
'size': '150',
}
api_url = self._VRTNU_SEARCH_URL + '?' + urlencode(params)
else:
api_url = path

path = unquote(path)
if 'facets[seasonTitle]' in path:
season_key = path.split('facets[seasonTitle]=')[1]
api_url = self._VRTNU_SEARCH_URL + '?' + urlencode(params)

results, episodes = self._get_season_episode_data(api_url, show_seasons=show_seasons, all_items=all_items)

if results.get('episodes'):
return self._map_to_episode_items(results.get('episodes', []), titletype=titletype, season_key=season_key, use_favorites=use_favorites)
return self._map_to_episode_items(results.get('episodes', []), titletype=titletype, season=season, use_favorites=use_favorites)
if results.get('seasons'):
return self._map_to_season_items(api_url, results.get('seasons'), episodes)
return self._map_to_season_items(program, results.get('seasons'), episodes)

return episode_items, sort, ascending, content

Expand All @@ -201,7 +193,7 @@ def _get_season_episode_data(self, api_url, show_seasons, all_items=True):
import json
self._kodi.log_notice('URL get: ' + unquote(api_url), 'Verbose')
api_json = json.load(urlopen(api_url))
seasons = self._get_season_data(api_json)
seasons = self._get_season_data(api_json) if 'facets[seasonTitle]' not in unquote(api_url) else None
episodes = api_json.get('results', [{}])
if show_seasons and seasons:
return dict(seasons=seasons), episodes
Expand All @@ -216,7 +208,7 @@ def _get_season_episode_data(self, api_url, show_seasons, all_items=True):
episodes += page_json.get('results', [{}])
return dict(episodes=episodes), None

def _map_to_episode_items(self, episodes, titletype=None, season_key=None, use_favorites=False):
def _map_to_episode_items(self, episodes, titletype=None, season=None, use_favorites=False):
''' Construct a list of TV show episodes TitleItems based on Search API query and filtered by favorites '''
from datetime import datetime
import dateutil.parser
Expand All @@ -225,15 +217,16 @@ def _map_to_episode_items(self, episodes, titletype=None, season_key=None, use_f
sort = 'episode'
ascending = True
if statichelper.boolean(use_favorites):
favorite_names = self._favorites.names()
programs = self._favorites.programs()
episode_items = []
for episode in episodes:
# VRT API workaround: seasonTitle facet behaves as a partial match regex,
# so we have to filter out the episodes from seasons that don't exactly match.
if season_key and episode.get('seasonTitle') != season_key:
if season and episode.get('seasonTitle') != season:
continue

if statichelper.boolean(use_favorites) and episode.get('programName') not in favorite_names:
program = statichelper.url_to_program(episode.get('programUrl'))
if statichelper.boolean(use_favorites) and program not in programs:
continue

# Support search highlights
Expand Down Expand Up @@ -297,13 +290,12 @@ def _map_to_episode_items(self, episodes, titletype=None, season_key=None, use_f
metadata.plot = '%s\n\n[COLOR yellow]%s[/COLOR]' % (metadata.plot, metadata.permalink)

if self._favorites.is_activated():
program_path = statichelper.unique_path(episode.get('programUrl'))
program = episode.get('program').encode('utf-8')
if self._favorites.is_favorite(program_path):
params = dict(action='unfollow', program=program, path=program_path)
program_title = episode.get('program').encode('utf-8')
if self._favorites.is_favorite(program):
params = dict(action='unfollow', title=program_title, program=program)
context_menu = [(self._kodi.localize(30412), 'RunPlugin(plugin://plugin.video.vrt.nu?%s)' % urlencode(params))]
else:
params = dict(action='follow', program=program, path=program_path)
params = dict(action='follow', title=program_title, program=program)
context_menu = [(self._kodi.localize(30411), 'RunPlugin(plugin://plugin.video.vrt.nu?%s)' % urlencode(params))]
else:
context_menu = []
Expand All @@ -328,7 +320,7 @@ def _map_to_episode_items(self, episodes, titletype=None, season_key=None, use_f

return episode_items, sort, ascending, 'episodes'

def _map_to_season_items(self, api_url, seasons, episodes):
def _map_to_season_items(self, program, seasons, episodes):
''' Construct a list of TV show season TitleItems based on Search API query and filtered by favorites '''
import random

Expand Down Expand Up @@ -366,7 +358,7 @@ def _map_to_season_items(self, api_url, seasons, episodes):
if self._kodi.get_global_setting('videolibrary.showallitems') is True:
season_items.append(TitleItem(
title=self._kodi.localize(30096),
url_dict=dict(action=actions.LISTING_ALL_EPISODES, video_url=api_url),
url_dict=dict(action=actions.LISTING_ALL_EPISODES, program=program),
is_playable=False,
art_dict=dict(thumb=fanart, icon='DefaultSets.png', fanart=fanart),
video_dict=metadata.get_video_dict(),
Expand All @@ -389,11 +381,9 @@ def _map_to_season_items(self, api_url, seasons, episodes):
fanart = 'DefaultSets.png'
thumbnail = 'DefaultSets.png'
label = '%s %s' % (self._kodi.localize(30094), season_key)
params = {'facets[seasonTitle]': season_key}
path = api_url + '&' + urlencode(params)
season_items.append(TitleItem(
title=label,
url_dict=dict(action=actions.LISTING_EPISODES, video_url=path),
url_dict=dict(action=actions.LISTING_EPISODES, program=program, season=season_key),
is_playable=False,
art_dict=dict(thumb=thumbnail, icon='DefaultSets.png', fanart=fanart),
video_dict=metadata.get_video_dict(),
Expand Down
Loading

0 comments on commit e82a84a

Please sign in to comment.