diff --git a/.travis.yml b/.travis.yml
index 5a1d1576b..b3f931a6f 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -20,3 +20,4 @@ script:
- python test/vrtplayertests.py
- python test/apihelpertests.py
- python test/tvguidetests.py
+- python test/searchtests.py
diff --git a/Makefile b/Makefile
index 9edf3f36c..8bb816f14 100644
--- a/Makefile
+++ b/Makefile
@@ -42,6 +42,7 @@ unit:
PYTHONPATH=$(pwd) python test/apihelpertests.py
PYTHONPATH=$(pwd) python test/tvguidetests.py
PYTHONPATH=$(pwd) python test/searchtests.py
+ PYTHONPATH=$(pwd) python test/favoritestests.py
@echo -e "$(white)=$(blue) Unit tests finished successfully.$(reset)"
zip: test
diff --git a/addon.py b/addon.py
index 0e1aa8fd2..e2ed9e56f 100644
--- a/addon.py
+++ b/addon.py
@@ -39,6 +39,21 @@ def router(params_string):
_tvguide = tvguide.TVGuide(_kodiwrapper)
_tvguide.show_tvguide(params)
return
+ if action == actions.FOLLOW:
+ from resources.lib.vrtplayer import favorites
+ _favorites = favorites.Favorites(_kodiwrapper)
+ _favorites.follow(program=params.get('program'), path=params.get('path'))
+ return
+ if action == actions.UNFOLLOW:
+ from resources.lib.vrtplayer import favorites
+ _favorites = favorites.Favorites(_kodiwrapper)
+ _favorites.unfollow(program=params.get('program'), path=params.get('path'))
+ return
+ if action == actions.REFRESH_FAVORITES:
+ from resources.lib.vrtplayer import favorites
+ _favorites = favorites.Favorites(_kodiwrapper)
+ _favorites.update_favorites()
+ return
from resources.lib.vrtplayer import vrtapihelper, vrtplayer
_apihelper = vrtapihelper.VRTApiHelper(_kodiwrapper)
@@ -47,13 +62,15 @@ def router(params_string):
if action == actions.PLAY:
_vrtplayer.play(params)
elif action == actions.LISTING_AZ_TVSHOWS:
- _vrtplayer.show_tvshow_menu_items()
+ _vrtplayer.show_tvshow_menu_items(filtered=params.get('filtered'))
elif action == actions.LISTING_CATEGORIES:
_vrtplayer.show_category_menu_items()
elif action == actions.LISTING_CATEGORY_TVSHOWS:
_vrtplayer.show_tvshow_menu_items(category=params.get('category'))
elif action == actions.LISTING_CHANNELS:
_vrtplayer.show_channels_menu_items(channel=params.get('channel'))
+ elif action == actions.LISTING_FAVORITES:
+ _vrtplayer.show_favorites_menu_items()
elif action == actions.LISTING_LIVE:
_vrtplayer.show_livestream_items()
elif action == actions.LISTING_EPISODES:
@@ -61,7 +78,7 @@ def router(params_string):
elif action == actions.LISTING_ALL_EPISODES:
_vrtplayer.show_all_episodes(path=params.get('video_url'))
elif action == actions.LISTING_RECENT:
- _vrtplayer.show_recent(page=params.get('page', 1))
+ _vrtplayer.show_recent(page=params.get('page', 1), filtered=params.get('filtered'))
elif action == actions.SEARCH:
_vrtplayer.search(search_string=params.get('query'), page=params.get('page', 1))
else:
diff --git a/addon.xml b/addon.xml
index 59b4294a5..d652b4ceb 100644
--- a/addon.xml
+++ b/addon.xml
@@ -15,6 +15,7 @@
video
+
Watch videos from VRT NU
diff --git a/resources/language/resource.language.en_gb/strings.po b/resources/language/resource.language.en_gb/strings.po
index faae7aa35..b4acc91fd 100644
--- a/resources/language/resource.language.en_gb/strings.po
+++ b/resources/language/resource.language.en_gb/strings.po
@@ -20,10 +20,14 @@ msgid "Interface"
msgstr "Interface"
msgctxt "#30001"
+msgid "Enable My programs"
+msgstr "Enable My programs"
+
+msgctxt "#30002"
msgid "Show episode permalink in plot"
msgstr "Show episode permalink in plot"
-msgctxt "#30002"
+msgctxt "#30003"
msgid "Enable menu caching"
msgstr "Enable menu caching"
@@ -75,6 +79,10 @@ msgctxt "#30042"
msgid "Install Widevine (for DRM content)"
msgstr "Install Widevine (for DRM content)"
+msgctxt "#30047"
+msgid "Refresh favorites"
+msgstr "Refresh favorites"
+
msgctxt "#30048"
msgid "Clear VRT cookies"
msgstr "Clear VRT cookies"
@@ -115,6 +123,14 @@ msgctxt "#30061"
msgid "Using a SOCKS proxy requires the PySocks library (script.module.pysocks) installed."
msgstr "Using a SOCKS proxy requires the PySocks library (script.module.pysocks) installed."
+msgctxt "#30078"
+msgid "My programs"
+msgstr "My programs"
+
+msgctxt "#30079"
+msgid "Browse only the programs you follow"
+msgstr "Browse only the programs you follow"
+
msgctxt "#30080"
msgid "A-Z"
msgstr "A-Z"
@@ -251,3 +267,34 @@ msgctxt "#30334"
msgid "In 2 days"
msgstr "In 2 days"
+msgctxt "#30411"
+msgid "Follow"
+msgstr "Follow"
+
+msgctxt "#30412"
+msgid "Unfollow"
+msgstr "Unfollow"
+
+msgctxt "#30415"
+msgid "No followed programs found"
+msgstr "No followed programs found"
+
+msgctxt "#30416"
+msgid "We could not find any programs that were followed.\n\nEither right-click on a program or an episode to follow a program, or follow a program on the VRT NU website."
+msgstr "We could not find any programs that were followed.\n\nEither right-click on a program or an episode to follow a program, or follow a program on the VRT NU website."
+
+msgctxt "#30420"
+msgid "My A-Z"
+msgstr "My A-Z"
+
+msgctxt "#30421"
+msgid "Alphabetically sorted list of My TV programs"
+msgstr "Alphabetically sorted list of My TV programs"
+
+msgctxt "#30422"
+msgid "My recent items"
+msgstr "My recent items"
+
+msgctxt "#30423"
+msgid "Recently published episodes of My TV programs"
+msgstr "Recently published episodes of My TV programs"
diff --git a/resources/language/resource.language.nl_nl/strings.po b/resources/language/resource.language.nl_nl/strings.po
index 412ccc029..26bb958b7 100644
--- a/resources/language/resource.language.nl_nl/strings.po
+++ b/resources/language/resource.language.nl_nl/strings.po
@@ -21,10 +21,14 @@ msgid "Interface"
msgstr "Interface"
msgctxt "#30001"
+msgid "Enable My programs"
+msgstr "Toon Mijn TV programma's"
+
+msgctxt "#30002"
msgid "Show episode permalink in plot"
msgstr "Toon aflevering permalink in beschrijving"
-msgctxt "#30002"
+msgctxt "#30003"
msgid "Enable menu caching"
msgstr "Gebruik menu caching"
@@ -84,6 +88,10 @@ msgctxt "#30042"
msgid "Install Widevine (for DRM content)"
msgstr "Installeer Widevine (voor DRM content)"
+msgctxt "#30047"
+msgid "Refresh favorites"
+msgstr "Ververs gevolgde programma's"
+
msgctxt "#30048"
msgid "Clear VRT cookies"
msgstr "Verwijder VRT cookies"
@@ -124,6 +132,14 @@ msgctxt "#30061"
msgid "Using a SOCKS proxy requires the PySocks library (script.module.pysocks) installed."
msgstr "Het gebruik van SOCKS proxies vereist dat de PySocks library (script.module.pysocks) geïnstalleerd is."
+msgctxt "#30078"
+msgid "My programs"
+msgstr "Mijn TV programma's"
+
+msgctxt "#30079"
+msgid "Browse only the programs you follow"
+msgstr "Bekijk enkel de programma's die je volgt"
+
msgctxt "#30080"
msgid "A-Z"
msgstr "A-Z"
@@ -259,3 +275,35 @@ msgstr "Morgen"
msgctxt "#30334"
msgid "In 2 days"
msgstr "Overmorgen"
+
+msgctxt "#30411"
+msgid "Follow"
+msgstr "Volg"
+
+msgctxt "#30412"
+msgid "Unfollow"
+msgstr "Vergeet"
+
+msgctxt "#30415"
+msgid "No followed programs found"
+msgstr "Geen programma's worden gevolgd"
+
+msgctxt "#30416"
+msgid "We could not find any programs that were followed.\n\nEither right-click on a program or an episode to follow a program, or follow a program on the VRT NU website."
+msgstr "We konden geen programma's vonden die je volgt.\n\nJe kan een programma volgen door rechts te klikken op een programma of aflevering, of om ze op de VRT NU website to volgen."
+
+msgctxt "#30420"
+msgid "My A-Z"
+msgstr "Mijn TV programma's"
+
+msgctxt "#30421"
+msgid "Alphabetically sorted list of My TV programs"
+msgstr "Alle TV-programma's die je volgt in alfabetische volgorde"
+
+msgctxt "#30422"
+msgid "My recent items"
+msgstr "Mijn recente afleveringen"
+
+msgctxt "#30423"
+msgid "Recently published episodes of My TV programs"
+msgstr "Recent gepubliceerde afleveringen van TV-programma's die je volgt"
diff --git a/resources/lib/helperobjects/helperobjects.py b/resources/lib/helperobjects/helperobjects.py
index 0b00ac577..10ce7abdc 100644
--- a/resources/lib/helperobjects/helperobjects.py
+++ b/resources/lib/helperobjects/helperobjects.py
@@ -7,12 +7,13 @@
class TitleItem:
- def __init__(self, title, url_dict, is_playable, art_dict=None, video_dict=None):
+ def __init__(self, title, url_dict, is_playable, art_dict=None, video_dict=None, context_menu=None):
self.title = title
self.url_dict = url_dict
self.is_playable = is_playable
self.art_dict = art_dict
self.video_dict = video_dict
+ self.context_menu = context_menu
class Credentials:
diff --git a/resources/lib/kodiwrappers/kodiwrapper.py b/resources/lib/kodiwrappers/kodiwrapper.py
index 999b905d2..cdb7b2357 100644
--- a/resources/lib/kodiwrappers/kodiwrapper.py
+++ b/resources/lib/kodiwrappers/kodiwrapper.py
@@ -104,6 +104,9 @@ def show_listing(self, list_items, sort='unsorted', ascending=True, content=None
if title_item.video_dict:
list_item.setInfo(type='video', infoLabels=title_item.video_dict)
+ if title_item.context_menu:
+ list_item.addContextMenuItems(title_item.context_menu)
+
listing.append((url, list_item, not title_item.is_playable))
ok = xbmcplugin.addDirectoryItems(self._handle, listing, len(listing))
@@ -148,7 +151,13 @@ def get_search_string(self):
def show_ok_dialog(self, title, message):
import xbmcgui
- xbmcgui.Dialog().ok(self._addon.getAddonInfo('name'), title, message)
+ if not title:
+ title = self._addon.getAddonInfo('name')
+ xbmcgui.Dialog().ok(title, message)
+
+ def show_notification(self, message, time=4000):
+ import xbmcgui
+ xbmcgui.Dialog().notification(self._addon.getAddonInfo('name'), message, xbmcgui.NOTIFICATION_INFO, time)
def set_locale(self):
import locale
@@ -204,8 +213,7 @@ def get_proxies(self):
if httpproxytype != 0 and not socks_supported:
# Only open the dialog the first time (to avoid multiple popups)
if socks_supported is None:
- message = self.get_localized_string(30061)
- self.show_ok_dialog('', message)
+ self.show_ok_dialog('', self.get_localized_string(30061))
return None
proxy_types = ['http', 'socks4', 'socks4a', 'socks5', 'socks5h']
@@ -264,10 +272,17 @@ def open_file(self, path, flags='r'):
yield f
f.close()
+ def stat_file(self, path):
+ import xbmcvfs
+ return xbmcvfs.Stat(path)
+
def delete_file(self, path):
import xbmcvfs
return xbmcvfs.delete(path)
+ def container_refresh(self):
+ xbmc.executebuiltin('Container.Refresh')
+
def log_access(self, url, query_string, log_level='Verbose'):
''' Log addon access '''
if log_levels.get(log_level, 0) <= self._max_log_level:
diff --git a/resources/lib/vrtplayer/actions.py b/resources/lib/vrtplayer/actions.py
index 8a4310c67..c42c85362 100644
--- a/resources/lib/vrtplayer/actions.py
+++ b/resources/lib/vrtplayer/actions.py
@@ -5,14 +5,18 @@
from __future__ import absolute_import, division, unicode_literals
CLEAR_COOKIES = 'clearcookies'
+FOLLOW = 'follow'
LISTING_ALL_EPISODES = 'listingallepisodes'
LISTING_AZ_TVSHOWS = 'listingaztvshows'
LISTING_CATEGORIES = 'listingcategories'
LISTING_CATEGORY_TVSHOWS = 'listingcategorytvshows'
LISTING_CHANNELS = 'listingchannels'
LISTING_EPISODES = 'listingepisodes'
+LISTING_FAVORITES = 'favorites'
LISTING_LIVE = 'listinglive'
LISTING_RECENT = 'listingrecent'
LISTING_TVGUIDE = 'listingtvguide'
PLAY = 'play'
+REFRESH_FAVORITES = 'refreshfavorites'
SEARCH = 'search'
+UNFOLLOW = 'unfollow'
diff --git a/resources/lib/vrtplayer/favorites.py b/resources/lib/vrtplayer/favorites.py
new file mode 100644
index 000000000..69716baa1
--- /dev/null
+++ b/resources/lib/vrtplayer/favorites.py
@@ -0,0 +1,104 @@
+# -*- coding: utf-8 -*-
+
+# GNU General Public License v3.0 (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
+
+from __future__ import absolute_import, division, unicode_literals
+import json
+import time
+
+from resources.lib.vrtplayer import tokenresolver
+
+try:
+ from urllib.request import build_opener, install_opener, ProxyHandler, Request, urlopen
+except ImportError:
+ from urllib2 import build_opener, install_opener, ProxyHandler, Request, urlopen
+
+
+class Favorites:
+
+ def __init__(self, _kodiwrapper):
+ self._kodiwrapper = _kodiwrapper
+ self._tokenresolver = tokenresolver.TokenResolver(_kodiwrapper)
+ self._proxies = _kodiwrapper.get_proxies()
+ install_opener(build_opener(ProxyHandler(self._proxies)))
+ self._cache_file = _kodiwrapper.get_userdata_path() + 'favorites.json'
+ self._favorites = {}
+ self.get_favorites()
+
+ def get_favorites(self):
+ if self._kodiwrapper.check_if_path_exists(self._cache_file):
+ if self._kodiwrapper.stat_file(self._cache_file).st_mtime() > time.mktime(time.localtime()) - (2 * 60):
+ self._kodiwrapper.log_notice('CACHE: %s vs %s' % (self._kodiwrapper.stat_file(self._cache_file).st_mtime(), time.mktime(time.localtime()) - (5 * 60)), 'Debug')
+ with self._kodiwrapper.open_file(self._cache_file) as f:
+ self._favorites = json.loads(f.read())
+ return
+ self.update_favorites()
+
+ def update_favorites(self):
+ xvrttoken = self._tokenresolver.get_xvrttoken()
+ headers = {
+ 'accept': 'application/json',
+ 'authorization': 'Bearer ' + xvrttoken,
+ 'content-type': 'application/json',
+ 'Cookie': 'X-VRT-Token=' + xvrttoken,
+ 'DNT': '1',
+ 'Referer': 'https://www.vrt.be/vrtnu',
+ }
+ req = Request('https://video-user-data.vrt.be/favorites', headers=headers)
+ self._favorites = json.loads(urlopen(req).read())
+ self.write_favorites()
+
+ def set_favorite(self, program, path, value=True):
+ if value is not self.is_favorite(path):
+ xvrttoken = self._tokenresolver.get_xvrttoken()
+ headers = {
+ 'accept': 'application/json',
+ 'authorization': 'Bearer ' + xvrttoken,
+ 'content-type': 'application/json',
+ 'Cookie': 'X-VRT-Token=' + xvrttoken,
+ 'DNT': '1',
+ 'Referer': 'https://www.vrt.be/vrtnu',
+ }
+ payload = dict(isFavorite=value, programUrl=path, title=program)
+ self._kodiwrapper.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=json.dumps(payload), headers=headers)
+ # TODO: Test that we get a HTTP 200, otherwise log and fail graceful
+ result = urlopen(req)
+ if result.getcode() != 200:
+ self._kodiwrapper.log_error("Failed to follow program '%s' at VRT NU" % path)
+ # 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.write_favorites()
+
+ def write_favorites(self):
+ with self._kodiwrapper.open_file(self._cache_file, 'w') as f:
+ f.write(json.dumps(self._favorites))
+
+ def is_favorite(self, path):
+ value = False
+ favorite = self._favorites.get(self.uuid(path))
+ if favorite:
+ value = favorite.get('value', dict(isFavorite=False)).get('isFavorite', False)
+ return value
+
+ def follow(self, program, path):
+ self._kodiwrapper.show_notification('Follow ' + program)
+ self.set_favorite(program, path, True)
+ self._kodiwrapper.container_refresh()
+
+ def unfollow(self, program, path):
+ self._kodiwrapper.show_notification('Unfollow ' + program)
+ self.set_favorite(program, path, False)
+ self._kodiwrapper.container_refresh()
+
+ def uuid(self, path):
+ return path.replace('/', '').replace('-', '')
+
+ def name(self, path):
+ return path.replace('.relevant/', '/').split('/')[-2]
+
+ def names(self):
+ return [self.name(p.get('value').get('programUrl')) for p in self._favorites.values() if p.get('value').get('isFavorite')]
+
+ def titles(self):
+ return [p.get('value').get('title') for p in self._favorites.values() if p.get('value').get('isFavorite')]
diff --git a/resources/lib/vrtplayer/statichelper.py b/resources/lib/vrtplayer/statichelper.py
index cb5a7a042..311ceaa1c 100644
--- a/resources/lib/vrtplayer/statichelper.py
+++ b/resources/lib/vrtplayer/statichelper.py
@@ -29,6 +29,12 @@ def convert_html_to_kodilabel(text):
return unescape(text).strip()
+def unique_path(path):
+ if path.startswith('//www.vrt.be/vrtnu'):
+ return path.replace('//www.vrt.be/vrtnu/', '/vrtnu/').replace('.relevant/', '/')
+ return path
+
+
def shorten_link(url):
if url is None:
return None
diff --git a/resources/lib/vrtplayer/tokenresolver.py b/resources/lib/vrtplayer/tokenresolver.py
index 02c34bc72..4cc9b2eb1 100644
--- a/resources/lib/vrtplayer/tokenresolver.py
+++ b/resources/lib/vrtplayer/tokenresolver.py
@@ -163,15 +163,16 @@ def _get_roaming_xvrttoken(self, xvrttoken):
cookie_value = 'X-VRT-Token=' + xvrttoken.get('X-VRT-Token')
headers = {'Cookie': cookie_value}
opener = build_opener(NoRedirection, ProxyHandler(self._proxies))
- self._kodiwrapper.log_notice('URL post: ' + unquote(url), 'Verbose')
+ self._kodiwrapper.log_notice('URL get: ' + unquote(url), 'Verbose')
req = Request(url, headers=headers)
req_info = opener.open(req).info()
cookie_value += '; state=' + req_info.getheader('Set-Cookie').split('state=')[1].split('; ')[0]
url = req_info.getheader('Location')
+ self._kodiwrapper.log_notice('URL get: ' + unquote(url), 'Verbose')
url = opener.open(url).info().getheader('Location')
headers = {'Cookie': cookie_value}
if url is not None:
- self._kodiwrapper.log_notice('URL post: ' + unquote(url), 'Verbose')
+ self._kodiwrapper.log_notice('URL get: ' + unquote(url), 'Verbose')
req = Request(url, headers=headers)
cookie_data = opener.open(req).info().getheader('Set-Cookie').split('X-VRT-Token=')[1].split('; ')
roaming_xvrttoken = TokenResolver._create_token_dictionary_from_urllib(cookie_data)
diff --git a/resources/lib/vrtplayer/tvguide.py b/resources/lib/vrtplayer/tvguide.py
index eb170c158..711edf7ff 100644
--- a/resources/lib/vrtplayer/tvguide.py
+++ b/resources/lib/vrtplayer/tvguide.py
@@ -142,7 +142,7 @@ def show_episodes(self, date, channel):
metadata.title = label
else:
# FIXME: Find a better solution for non-actionable items
- url_dict = dict(action=actions.LISTING_TVGUIDE, date=date, channel=channel)
+ url_dict = dict(action=actions.LISTING_TVGUIDE, date=date, channel=channel.get('name'))
if start_date < now <= end_date: # Now playing
metadata.title = '[COLOR brown]%s[/COLOR] %s' % (label, self._kodiwrapper.get_localized_string(30302))
else:
diff --git a/resources/lib/vrtplayer/vrtapihelper.py b/resources/lib/vrtplayer/vrtapihelper.py
index 745d691f0..80926ba5a 100644
--- a/resources/lib/vrtplayer/vrtapihelper.py
+++ b/resources/lib/vrtplayer/vrtapihelper.py
@@ -4,7 +4,7 @@
from __future__ import absolute_import, division, unicode_literals
from resources.lib.helperobjects.helperobjects import TitleItem
-from resources.lib.vrtplayer import actions, metadatacreator, statichelper
+from resources.lib.vrtplayer import actions, favorites, metadatacreator, statichelper
try:
from urllib.parse import urlencode, unquote
@@ -26,28 +26,37 @@ def __init__(self, _kodiwrapper):
self._proxies = _kodiwrapper.get_proxies()
install_opener(build_opener(ProxyHandler(self._proxies)))
self._showpermalink = _kodiwrapper.get_setting('showpermalink') == 'true'
+ if _kodiwrapper.get_setting('usefavorites') == 'true':
+ self._favorites = favorites.Favorites(self._kodiwrapper)
+ else:
+ self._favorites = None
- def get_tvshow_items(self, category=None, channel=None):
+ def get_tvshow_items(self, category=None, channel=None, filtered=False):
import json
params = dict()
if category:
params['facets[categories]'] = category
- else:
- # If no path is provided, we return the A-Z listing
- params['facets[transcodingStatus]'] = 'AVAILABLE'
if channel:
params['facets[programBrands]'] = channel
+ # If no facet-selection is done, we return the A-Z listing
+ if not category and not channel:
+ params['facets[transcodingStatus]'] = 'AVAILABLE'
+
api_url = self._VRTNU_SUGGEST_URL + '?' + urlencode(params)
self._kodiwrapper.log_notice('URL get: ' + unquote(api_url), 'Verbose')
api_json = json.loads(urlopen(api_url).read())
- return self._map_to_tvshow_items(api_json)
+ return self._map_to_tvshow_items(api_json, filtered=filtered)
- def _map_to_tvshow_items(self, tvshows):
+ def _map_to_tvshow_items(self, tvshows, filtered=False):
tvshow_items = []
+ if filtered:
+ favorite_names = self._favorites.names()
for tvshow in tvshows:
+ if filtered and tvshow.get('programName') not in favorite_names:
+ continue
metadata = metadatacreator.MetadataCreator()
metadata.mediatype = 'tvshow'
metadata.tvshowtitle = tvshow.get('title', '???')
@@ -58,6 +67,16 @@ def _map_to_tvshow_items(self, tvshows):
# title = '%s [LIGHT][COLOR yellow]%s[/COLOR][/LIGHT]' % (tvshow.get('title', '???'), tvshow.get('episode_count', '?'))
label = tvshow.get('title', '???')
thumbnail = statichelper.add_https_method(tvshow.get('thumbnail', 'DefaultAddonVideo.png'))
+ program_path = statichelper.unique_path(tvshow.get('targetUrl'))
+ if self._favorites:
+ if self._favorites.is_favorite(program_path):
+ params = dict(action='unfollow', program=tvshow.get('title'), path=program_path)
+ context_menu = [(self._kodiwrapper.get_localized_string(30412), 'RunPlugin(plugin://plugin.video.vrt.nu?%s)' % urlencode(params))]
+ else:
+ params = dict(action='follow', program=tvshow.get('title'), path=program_path)
+ context_menu = [(self._kodiwrapper.get_localized_string(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, '')
@@ -67,6 +86,7 @@ def _map_to_tvshow_items(self, tvshows):
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
@@ -86,7 +106,7 @@ def _get_season_items(self, api_url, api_json):
season_items, sort, ascending = self._map_to_season_items(api_url, facet.get('buckets', []), episode)
return season_items, sort, ascending
- def get_episode_items(self, path=None, page=None, all_seasons=False):
+ def get_episode_items(self, path=None, page=None, all_seasons=False, filtered=False):
import json
episode_items = []
sort = 'episode'
@@ -95,16 +115,22 @@ def get_episode_items(self, path=None, page=None, all_seasons=False):
# Recent items
if page:
params = {
- 'from': (page - 1) * 50,
+ 'from': ((page - 1) * 50) + 1,
'i': 'video',
'size': 50,
- 'facets[transcodingStatus]': 'AVAILABLE',
- 'facets[programBrands]': '[een,canvas,sporza,vrtnws,vrtnxt,radio1,radio2,klara,stubru,mnm]',
+ # 'facets[transcodingStatus]': 'AVAILABLE',
}
+
+ if filtered:
+ params['facets[programName]'] = '[%s]' % (','.join(self._favorites.names()))
+ else:
+ params['facets[programBrands]'] = '[een,canvas,sporza,vrtnws,vrtnxt,radio1,radio2,klara,stubru,mnm]'
+
api_url = self._VRTNU_SEARCH_URL + '?' + urlencode(params)
self._kodiwrapper.log_notice('URL get: ' + unquote(api_url), 'Verbose')
api_json = json.loads(urlopen(api_url).read())
- episode_items, sort, ascending = self._map_to_episode_items(api_json.get('results', []), titletype='recent')
+ episode_items, sort, ascending = self._map_to_episode_items(api_json.get('results', []), titletype='recent', filtered=filtered)
+ content = 'episodes'
if path:
if '.relevant/' in path:
@@ -131,28 +157,34 @@ def get_episode_items(self, path=None, page=None, all_seasons=False):
# Look for seasons items if not yet done
season_key = None
+
# path = requests.utils.unquote(path)
path = unquote(path)
if all_seasons is True:
episode_items, sort, ascending = self._map_to_episode_items(episodes, season_key=None)
+ content = 'episodes'
elif 'facets[seasonTitle]' in path:
season_key = path.split('facets[seasonTitle]=')[1]
elif display_options.get('showSeason') is True:
episode_items, sort, ascending = self._get_season_items(api_url, api_json)
+ content = 'seasons'
# No season items, generate episode items
if not episode_items:
episode_items, sort, ascending = self._map_to_episode_items(episodes, season_key=season_key)
+ content = 'episodes'
- return episode_items, sort, ascending
+ return episode_items, sort, ascending, content
- def _map_to_episode_items(self, episodes, titletype=None, season_key=None):
+ def _map_to_episode_items(self, episodes, titletype=None, season_key=None, filtered=False):
from datetime import datetime
import dateutil.parser
import dateutil.tz
now = datetime.now(dateutil.tz.tzlocal())
sort = 'episode'
ascending = True
+ if filtered:
+ favorite_names = self._favorites.names()
episode_items = []
for episode in episodes:
# VRT API workaround: seasonTitle facet behaves as a partial match regex,
@@ -160,6 +192,9 @@ def _map_to_episode_items(self, episodes, titletype=None, season_key=None):
if season_key and episode.get('seasonTitle') != season_key:
continue
+ if filtered and episode.get('programName') not in favorite_names:
+ continue
+
display_options = episode.get('displayOptions', dict())
# NOTE: Hard-code showing seasons because it is unreliable (i.e; Thuis or Down the Road have it disabled)
@@ -214,6 +249,17 @@ def _map_to_episode_items(self, episodes, titletype=None, season_key=None):
if self._showpermalink and metadata.permalink:
metadata.plot = '%s\n\n[COLOR yellow]%s[/COLOR]' % (metadata.plot, metadata.permalink)
+ program_path = statichelper.unique_path(episode.get('programUrl'))
+ if self._favorites:
+ if self._favorites.is_favorite(program_path):
+ params = dict(action='unfollow', program=episode.get('program'), path=program_path)
+ context_menu = [(self._kodiwrapper.get_localized_string(30412), 'RunPlugin(plugin://plugin.video.vrt.nu?%s)' % urlencode(params))]
+ else:
+ params = dict(action='follow', program=episode.get('program'), path=program_path)
+ context_menu = [(self._kodiwrapper.get_localized_string(30411), 'RunPlugin(plugin://plugin.video.vrt.nu?%s)' % urlencode(params))]
+ else:
+ context_menu = []
+
thumb = statichelper.add_https_method(episode.get('videoThumbnailUrl', 'DefaultAddonVideo.png'))
fanart = statichelper.add_https_method(episode.get('programImageUrl', thumb))
video_url = statichelper.add_https_method(episode.get('url'))
@@ -225,6 +271,7 @@ def _map_to_episode_items(self, episodes, titletype=None, season_key=None):
is_playable=True,
art_dict=dict(thumb=thumb, icon='DefaultAddonVideo.png', fanart=fanart),
video_dict=metadata.get_video_dict(),
+ context_menu=context_menu,
))
return episode_items, sort, ascending
@@ -274,7 +321,7 @@ def search(self, search_string, page=1):
import json
params = {
- 'from': (page - 1) * 50,
+ 'from': ((page - 1) * 50) + 1,
'i': 'video',
'size': 50,
'q': search_string,
diff --git a/resources/lib/vrtplayer/vrtplayer.py b/resources/lib/vrtplayer/vrtplayer.py
index 353c33537..cd7cebd5c 100644
--- a/resources/lib/vrtplayer/vrtplayer.py
+++ b/resources/lib/vrtplayer/vrtplayer.py
@@ -21,7 +21,19 @@ def __init__(self, _kodiwrapper, _apihelper):
self._apihelper = _apihelper
def show_main_menu_items(self):
- main_items = [
+ main_items = []
+
+ # Only add 'My programs' when this is enabled in config
+ if self._kodiwrapper.get_setting('usefavorites') == 'true':
+ main_items.append(TitleItem(
+ title=self._kodiwrapper.get_localized_string(30078),
+ url_dict=dict(action=actions.LISTING_FAVORITES),
+ is_playable=False,
+ art_dict=dict(thumb='icons/settings/profiles.png', icon='icons/settings/profiles.png', fanart='icons/settings/profiles.png'),
+ video_dict=dict(plot=self._kodiwrapper.get_localized_string(30079))
+ ))
+
+ main_items.extend([
TitleItem(title=self._kodiwrapper.get_localized_string(30080),
url_dict=dict(action=actions.LISTING_AZ_TVSHOWS),
is_playable=False,
@@ -57,11 +69,31 @@ def show_main_menu_items(self):
is_playable=False,
art_dict=dict(thumb='DefaultAddonsSearch.png', icon='DefaultAddonsSearch.png', fanart='DefaultAddonsSearch.png'),
video_dict=dict(plot=self._kodiwrapper.get_localized_string(30093))),
- ]
+ ])
self._kodiwrapper.show_listing(main_items)
- def show_tvshow_menu_items(self, category=None):
- tvshow_items = self._apihelper.get_tvshow_items(category=category)
+ def show_favorites_menu_items(self):
+ favorites_items = [
+ TitleItem(title=self._kodiwrapper.get_localized_string(30420),
+ url_dict=dict(action=actions.LISTING_AZ_TVSHOWS, filtered=True),
+ is_playable=False,
+ art_dict=dict(thumb='DefaultMovieTitle.png', icon='DefaultMovieTitle.png', fanart='DefaultMovieTitle.png'),
+ video_dict=dict(plot=self._kodiwrapper.get_localized_string(30421))),
+ TitleItem(title=self._kodiwrapper.get_localized_string(30422),
+ url_dict=dict(action=actions.LISTING_RECENT, page='1', filtered=True),
+ is_playable=False,
+ art_dict=dict(thumb='DefaultYear.png', icon='DefaultYear.png', fanart='DefaultYear.png'),
+ video_dict=dict(plot=self._kodiwrapper.get_localized_string(30423))),
+ ]
+ self._kodiwrapper.show_listing(favorites_items)
+
+ # Show dialog when no favorites were found
+ from resources.lib.vrtplayer import favorites
+ if not favorites.Favorites(self._kodiwrapper).names():
+ self._kodiwrapper.show_ok_dialog(self._kodiwrapper.get_localized_string(30415), self._kodiwrapper.get_localized_string(30416))
+
+ def show_tvshow_menu_items(self, category=None, filtered=False):
+ tvshow_items = self._apihelper.get_tvshow_items(category=category, filtered=filtered)
self._kodiwrapper.show_listing(tvshow_items, sort='label', content='tvshows')
def show_category_menu_items(self):
@@ -133,31 +165,32 @@ def show_channels(self, action=actions.PLAY, channels=None):
self._kodiwrapper.show_listing(channel_items, cache=False)
def show_episodes(self, path):
- episode_items, sort, ascending = self._apihelper.get_episode_items(path=path)
- self._kodiwrapper.show_listing(episode_items, sort=sort, ascending=ascending, content='episodes')
+ episode_items, sort, ascending, content = self._apihelper.get_episode_items(path=path)
+ self._kodiwrapper.show_listing(episode_items, sort=sort, ascending=ascending, content=content)
def show_all_episodes(self, path):
- episode_items, sort, ascending = self._apihelper.get_episode_items(path=path, all_seasons=True)
- self._kodiwrapper.show_listing(episode_items, sort=sort, ascending=ascending, content='episodes')
+ episode_items, sort, ascending, content = self._apihelper.get_episode_items(path=path, all_seasons=True)
+ self._kodiwrapper.show_listing(episode_items, sort=sort, ascending=ascending, content=content)
- def show_recent(self, page):
+ def show_recent(self, page, filtered=False):
try:
page = int(page)
except TypeError:
page = 1
- episode_items, sort, ascending = self._apihelper.get_episode_items(page=page)
+ episode_items, sort, ascending, content = self._apihelper.get_episode_items(page=page, filtered=filtered)
# Add 'More...' entry at the end
- episode_items.append(TitleItem(
- title=self._kodiwrapper.get_localized_string(30300),
- url_dict=dict(action=actions.LISTING_RECENT, page=page + 1),
- is_playable=False,
- art_dict=dict(thumb='DefaultYear.png', icon='DefaultYear.png', fanart='DefaultYear.png'),
- video_dict=dict(),
- ))
-
- self._kodiwrapper.show_listing(episode_items, sort=sort, ascending=ascending, content='episodes', cache=False)
+ if len(episode_items) == 50:
+ episode_items.append(TitleItem(
+ title=self._kodiwrapper.get_localized_string(30300),
+ url_dict=dict(action=actions.LISTING_RECENT, page=page + 1, filtered=filtered),
+ is_playable=False,
+ art_dict=dict(thumb='DefaultYear.png', icon='DefaultYear.png', fanart='DefaultYear.png'),
+ video_dict=dict(),
+ ))
+
+ self._kodiwrapper.show_listing(episode_items, sort=sort, ascending=ascending, content=content, cache=False)
def play(self, params):
from resources.lib.vrtplayer import streamservice, tokenresolver
diff --git a/resources/settings.xml b/resources/settings.xml
index 87df01f72..6645c8fe4 100644
--- a/resources/settings.xml
+++ b/resources/settings.xml
@@ -1,8 +1,9 @@
-
+
+
@@ -18,6 +19,7 @@
+
diff --git a/service.py b/service.py
index 5663c74c5..f8b52be45 100644
--- a/service.py
+++ b/service.py
@@ -22,10 +22,10 @@ def __init__(self):
def onSettingsChanged(self):
''' Handler for changes to settings '''
addon = xbmcaddon.Addon(id='plugin.video.vrt.nu')
- kodi_wrapper = kodiwrapper.KodiWrapper(None, None, addon)
- kodi_wrapper.log_notice('VRT NU Addon: settings changed')
- token_resolver = tokenresolver.TokenResolver(kodi_wrapper)
- token_resolver.reset_cookies()
+ _kodiwrapper = kodiwrapper.KodiWrapper(None, None, addon)
+ _kodiwrapper.log_notice('VRT NU Addon: settings changed')
+ _tokenresolver = tokenresolver.TokenResolver(_kodiwrapper)
+ _tokenresolver.reset_cookies()
if __name__ == '__main__':
diff --git a/test/__init__.py b/test/__init__.py
index e69de29bb..4381791cc 100644
--- a/test/__init__.py
+++ b/test/__init__.py
@@ -0,0 +1,52 @@
+# -*- coding: utf-8 -*-
+
+# GNU General Public License v3.0 (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
+
+from __future__ import absolute_import, division, print_function, unicode_literals
+from contextlib import contextmanager
+import os
+import polib
+
+PO = polib.pofile('resources/language/resource.language.en_gb/strings.po')
+SETTINGS = dict(
+ username='qsdfdsq',
+ password='qsdfqsdfds',
+ log_level='Verbose',
+ showpermalink='true',
+ showsubtitles='true',
+ usedrm='false',
+ usefavorites='false',
+)
+
+
+def get_localized_string(msgctxt):
+ for entry in PO:
+ if entry.msgctxt == '#%s' % msgctxt:
+ return entry.msgstr
+ return 'vrttest'
+
+
+def get_setting(key):
+ return SETTINGS[key]
+
+
+def log_notice(msg, level='Info'):
+ print('%s: %s' % (level, msg))
+
+
+@contextmanager
+def open_file(path, flags='r'):
+ f = open(path, flags)
+ yield f
+ f.close()
+
+
+def stat_file(path):
+ class stat:
+ def __init__(self, path):
+ self._stat = os.stat(path)
+
+ def st_mtime(self):
+ return self._stat.st_mtime
+
+ return stat(path)
diff --git a/test/apihelpertests.py b/test/apihelpertests.py
index ff26a8288..fea4aaf24 100644
--- a/test/apihelpertests.py
+++ b/test/apihelpertests.py
@@ -5,60 +5,53 @@
from __future__ import absolute_import, division, print_function, unicode_literals
import mock
import os
-import polib
import unittest
from resources.lib.vrtplayer import vrtapihelper
-
-PO = polib.pofile('resources/language/resource.language.en_gb/strings.po')
-
-
-def get_localized_string(msgctxt):
- for entry in PO:
- if entry.msgctxt == '#%s' % msgctxt:
- return entry.msgstr
- return 'vrttest'
-
-
-def log_notice(msg, level):
- print('%s: %s' % (level, msg))
+from test import get_localized_string, get_setting, log_notice, open_file
class ApiHelperTests(unittest.TestCase):
_kodiwrapper = mock.MagicMock()
-
_kodiwrapper.check_if_path_exists = mock.MagicMock(side_effect=os.path.exists)
_kodiwrapper.get_localized_dateshort = mock.MagicMock(return_value='%d-%m-%Y')
_kodiwrapper.get_localized_string = mock.MagicMock(side_effect=get_localized_string)
_kodiwrapper.get_proxies = mock.MagicMock(return_value=dict())
+ _kodiwrapper.get_setting = mock.MagicMock(side_effect=get_setting)
+ _kodiwrapper.get_userdata_path.return_value = './userdata/'
_kodiwrapper.log_notice = mock.MagicMock(side_effect=log_notice)
_kodiwrapper.make_dir.return_value = None
+ _kodiwrapper.open_file = mock.MagicMock(side_effect=open_file)
_apihelper = vrtapihelper.VRTApiHelper(_kodiwrapper)
def test_get_api_data_single_season(self):
- title_items, sort, ascending = self._apihelper.get_episode_items(path='/vrtnu/a-z/het-journaal.relevant/')
+ title_items, sort, ascending, content = self._apihelper.get_episode_items(path='/vrtnu/a-z/het-journaal.relevant/')
self.assertTrue(123 < len(title_items) < 129, 'We got %s items instead.' % len(title_items))
self.assertEqual(sort, 'dateadded')
self.assertFalse(ascending)
+ self.assertEqual(content, 'episodes')
def test_get_api_data_multiple_seasons(self):
- title_items, sort, ascending = self._apihelper.get_episode_items(path='/vrtnu/a-z/thuis.relevant/')
+ title_items, sort, ascending, content = self._apihelper.get_episode_items(path='/vrtnu/a-z/thuis.relevant/')
self.assertTrue(len(title_items) < 5)
self.assertEqual(sort, 'label')
self.assertFalse(ascending)
+ self.assertEqual(content, 'seasons')
def test_get_api_data_specific_season(self):
- title_items, sort, ascending = self._apihelper.get_episode_items(path='/vrtnu/a-z/pano.relevant/')
+ title_items, sort, ascending, content = self._apihelper.get_episode_items(path='/vrtnu/a-z/pano.relevant/')
self.assertEqual(len(title_items), 4)
self.assertEqual(sort, 'label')
self.assertFalse(ascending)
+ self.assertEqual(content, 'seasons')
def test_get_api_data_specific_season_without_broadcastdate(self):
- title_items, sort, ascending = self._apihelper.get_episode_items(path='/vrtnu/a-z/postbus-x.relevant/')
+ title_items, sort, ascending, content = self._apihelper.get_episode_items(path='/vrtnu/a-z/postbus-x.relevant/')
self.assertEqual(len(title_items), 3)
self.assertEqual(sort, 'label')
self.assertTrue(ascending)
+ self.assertEqual(content, 'seasons')
if __name__ == '__main__':
diff --git a/test/favoritestests.py b/test/favoritestests.py
new file mode 100644
index 000000000..44ac93c4a
--- /dev/null
+++ b/test/favoritestests.py
@@ -0,0 +1,53 @@
+# -*- coding: utf-8 -*-
+
+# GNU General Public License v3.0 (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
+
+from __future__ import absolute_import, division, print_function, unicode_literals
+import mock
+import os
+import unittest
+
+from resources.lib.vrtplayer import favorites
+from test import SETTINGS, get_setting, log_notice, open_file, stat_file
+
+SETTINGS['usefavorites'] = 'true'
+
+
+class TestFavorites(unittest.TestCase):
+
+ _kodiwrapper = mock.MagicMock()
+ _kodiwrapper.check_if_path_exists = mock.MagicMock(side_effect=os.path.exists)
+ _kodiwrapper.get_proxies = mock.MagicMock(return_value=dict())
+ _kodiwrapper.get_setting = mock.MagicMock(side_effect=get_setting)
+ _kodiwrapper.get_userdata_path.return_value = './userdata/'
+ _kodiwrapper.log_notice = mock.MagicMock(side_effect=log_notice)
+ _kodiwrapper.make_dir.return_value = None
+ _kodiwrapper.open_file = mock.MagicMock(side_effect=open_file)
+ _kodiwrapper.stat_file = mock.MagicMock(side_effect=stat_file)
+ _favorites = favorites.Favorites(_kodiwrapper)
+
+ def test_follow_unfollow(self):
+ program = 'Winteruur'
+ program_path = '/vrtnu/a-z/winteruur/'
+ self._favorites.follow(program, program_path)
+ self.assertTrue(self._favorites.is_favorite(program_path))
+
+ self._favorites.unfollow(program, program_path)
+ self.assertFalse(self._favorites.is_favorite(program_path))
+
+ self._favorites.follow(program, program_path)
+ self.assertTrue(self._favorites.is_favorite(program_path))
+
+ def test_names(self):
+ names = self._favorites.names()
+ self.assertTrue(names)
+ print(names)
+
+ def test_titles(self):
+ titles = self._favorites.titles()
+ self.assertTrue(titles)
+ print(sorted(titles))
+
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/test/searchtests.py b/test/searchtests.py
index f7ac62761..1c75e85c1 100644
--- a/test/searchtests.py
+++ b/test/searchtests.py
@@ -3,37 +3,27 @@
# GNU General Public License v3.0 (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
from __future__ import absolute_import, division, print_function, unicode_literals
-from contextlib import contextmanager
import mock
import os
import unittest
from resources.lib.vrtplayer import vrtapihelper
+from test import get_setting, log_notice, open_file, stat_file
-@contextmanager
-def open_file(path, flags='r'):
- f = open(path, flags)
- yield f
- f.close()
-
-
-def log_notice(msg, level):
- print('%s: %s' % (level, msg))
-
-
-class TestVRTPlayer(unittest.TestCase):
+class TestSearch(unittest.TestCase):
_kodiwrapper = mock.MagicMock()
_kodiwrapper.check_if_path_exists = mock.MagicMock(side_effect=os.path.exists)
+ _kodiwrapper.check_inputstream_adaptive.return_value = True
_kodiwrapper.get_localized_dateshort = mock.MagicMock(return_value='%d-%m-%Y')
- _kodiwrapper.get_localized_string.return_value = '"[B][COLOR blue]Available until %s[/COLOR][/B]\n"'
_kodiwrapper.get_proxies = mock.MagicMock(return_value=dict())
+ _kodiwrapper.get_setting = mock.MagicMock(side_effect=get_setting)
_kodiwrapper.get_userdata_path.return_value = './userdata/'
_kodiwrapper.log_notice = mock.MagicMock(side_effect=log_notice)
_kodiwrapper.make_dir.return_value = None
_kodiwrapper.open_file = mock.MagicMock(side_effect=open_file)
- _kodiwrapper.stat_file = mock.MagicMock(side_effect=os.stat)
+ _kodiwrapper.stat_file = mock.MagicMock(side_effect=stat_file)
_apihelper = vrtapihelper.VRTApiHelper(_kodiwrapper)
def test_search_journaal(self):
diff --git a/test/streamservicetests.py b/test/streamservicetests.py
index 517f449cb..96cee3692 100644
--- a/test/streamservicetests.py
+++ b/test/streamservicetests.py
@@ -8,39 +8,13 @@
from datetime import datetime, timedelta
import dateutil.tz
import mock
-import polib
import unittest
from urllib2 import HTTPError
from resources.lib.vrtplayer import CHANNELS, streamservice, tokenresolver, vrtapihelper
+from test import SETTINGS, get_setting, get_localized_string, log_notice
-SETTINGS = dict(
- username='qsdfdsq',
- password='qsdfqsdfds',
- showsubtitles='true',
- showpermalink='true',
- usedrm='false',
-)
-
-PO = polib.pofile('resources/language/resource.language.en_gb/strings.po')
-
-
-def get_settings(key):
- return SETTINGS[key]
-
-
-def get_localized_string(msgctxt):
- for entry in PO:
- if entry.msgctxt == '#%s' % msgctxt:
- return entry.msgstr
- return 'vrttest'
-
-
-def log_notice(msg, level):
- print('%s: %s' % (level, msg))
-
-
-use_drm = False
+SETTINGS['use_drm'] = 'false'
now = datetime.now(dateutil.tz.tzlocal())
yesterday = now + timedelta(days=-1)
@@ -53,8 +27,8 @@ class StreamServiceTests(unittest.TestCase):
_kodiwrapper.get_localized_dateshort = mock.MagicMock(return_value='%d-%m-%Y')
_kodiwrapper.get_localized_string = mock.MagicMock(side_effect=get_localized_string)
_kodiwrapper.get_proxies = mock.MagicMock(return_value=dict())
- _kodiwrapper.get_setting = mock.MagicMock(side_effect=get_settings)
- _kodiwrapper.get_userdata_path.return_value = 'vrttest'
+ _kodiwrapper.get_setting = mock.MagicMock(side_effect=get_setting)
+ _kodiwrapper.get_userdata_path.return_value = './userdata/'
_kodiwrapper.log_notice = mock.MagicMock(side_effect=log_notice)
_kodiwrapper.make_dir.return_value = None
_apihelper = vrtapihelper.VRTApiHelper(_kodiwrapper)
diff --git a/test/tvguidetests.py b/test/tvguidetests.py
index 4b65f2fd8..fb0bc05df 100644
--- a/test/tvguidetests.py
+++ b/test/tvguidetests.py
@@ -10,20 +10,19 @@
import unittest
from resources.lib.vrtplayer import tvguide
+from test import log_notice
channels = ['een', 'canvas', 'ketnet']
-def log_notice(msg, level):
- print('%s: %s' % (level, msg))
-
-
class TestTVGuide(unittest.TestCase):
_kodiwrapper = mock.MagicMock()
_kodiwrapper.get_localized_datelong = mock.MagicMock(return_value='%a %d-%m-%Y')
_kodiwrapper.get_proxies = mock.MagicMock(return_value=dict())
+ _kodiwrapper.get_userdata_path.return_value = './userdata/'
_kodiwrapper.log_notice = mock.MagicMock(side_effect=log_notice)
+ _kodiwrapper.make_dir.return_value = None
_tvguide = tvguide.TVGuide(_kodiwrapper)
def test_tvguide_date_menu(self):
diff --git a/test/vrtplayertests.py b/test/vrtplayertests.py
index 05e66f59a..d8d6f7d05 100644
--- a/test/vrtplayertests.py
+++ b/test/vrtplayertests.py
@@ -5,24 +5,13 @@
# pylint: disable=unused-variable
from __future__ import absolute_import, division, print_function, unicode_literals
-from contextlib import contextmanager
import mock
import os
import random
import unittest
from resources.lib.vrtplayer import CATEGORIES, CHANNELS, vrtapihelper, vrtplayer
-
-
-@contextmanager
-def open_file(path, flags='r'):
- f = open(path, flags)
- yield f
- f.close()
-
-
-def log_notice(msg, level):
- print('%s: %s' % (level, msg))
+from test import get_setting, log_notice, open_file
class TestVRTPlayer(unittest.TestCase):
@@ -31,10 +20,10 @@ class TestVRTPlayer(unittest.TestCase):
_kodiwrapper.check_if_path_exists = mock.MagicMock(side_effect=os.path.exists)
_kodiwrapper.get_localized_dateshort = mock.MagicMock(return_value='%d-%m-%Y')
_kodiwrapper.get_proxies = mock.MagicMock(return_value=dict())
+ _kodiwrapper.get_setting = mock.MagicMock(side_effect=get_setting)
_kodiwrapper.get_userdata_path.return_value = './userdata/'
_kodiwrapper.log_notice = mock.MagicMock(side_effect=log_notice)
_kodiwrapper.open_file = mock.MagicMock(side_effect=open_file)
- # _kodiwrapper.stat_file = mock.MagicMock(side_effect=os.stat)
_apihelper = vrtapihelper.VRTApiHelper(_kodiwrapper)
_vrtplayer = vrtplayer.VRTPlayer(_kodiwrapper, _apihelper)
@@ -53,58 +42,64 @@ def test_tvshows(self):
def test_show_videos_single_episode_shows_videos(self):
path = '/vrtnu/a-z/marathonradio.relevant/'
- episode_items, sort, ascending = self._apihelper.get_episode_items(path=path)
+ episode_items, sort, ascending, content = self._apihelper.get_episode_items(path=path)
self.assertTrue(episode_items, msg=path)
self.assertEqual(sort, 'dateadded')
self.assertFalse(ascending)
+ self.assertEqual(content, 'episodes')
self._vrtplayer.show_episodes(path)
self.assertTrue(self._kodiwrapper.show_listing.called)
def test_show_videos_single_season_shows_videos(self):
path = '/vrtnu/a-z/het-weer.relevant/'
- episode_items, sort, ascending = self._apihelper.get_episode_items(path=path)
+ episode_items, sort, ascending, content = self._apihelper.get_episode_items(path=path)
self.assertTrue(episode_items, msg=path)
self.assertEqual(sort, 'dateadded')
self.assertFalse(ascending)
+ self.assertEqual(content, 'episodes')
self._vrtplayer.show_episodes(path)
self.assertTrue(self._kodiwrapper.show_listing.called)
def test_show_videos_multiple_seasons_shows_videos(self):
path = '/vrtnu/a-z/pano.relevant/'
- episode_items, sort, ascending = self._apihelper.get_episode_items(path=path)
+ episode_items, sort, ascending, content = self._apihelper.get_episode_items(path=path)
self.assertTrue(episode_items)
self.assertEqual(sort, 'label')
self.assertFalse(ascending)
+ self.assertEqual(content, 'seasons')
self._vrtplayer.show_episodes(path)
self.assertTrue(self._kodiwrapper.show_listing.called)
def test_show_videos_specific_seasons_shows_videos(self):
path = '/vrtnu/a-z/thuis.relevant/'
- episode_items, sort, ascending = self._apihelper.get_episode_items(path=path)
+ episode_items, sort, ascending, content = self._apihelper.get_episode_items(path=path)
self.assertTrue(episode_items, msg=path)
self.assertEqual(sort, 'label')
self.assertFalse(ascending)
+ self.assertEqual(content, 'seasons')
self._vrtplayer.show_episodes(path)
self.assertTrue(self._kodiwrapper.show_listing.called)
def test_get_recent_episodes(self):
''' Test items, sort and order '''
- episode_items, sort, ascending = self._apihelper.get_episode_items(page=1)
+ episode_items, sort, ascending, content = self._apihelper.get_episode_items(page=1)
self.assertEqual(len(episode_items), 50)
self.assertEqual(sort, 'dateadded')
self.assertFalse(ascending)
+ self.assertEqual(content, 'episodes')
def test_get_program_episodes(self):
''' Test items, sort and order '''
path = '/vrtnu/a-z/het-journaal.relevant/'
- episode_items, sort, ascending = self._apihelper.get_episode_items(path=path)
+ episode_items, sort, ascending, content = self._apihelper.get_episode_items(path=path)
self.assertTrue(episode_items)
self.assertEqual(sort, 'dateadded')
self.assertFalse(ascending)
+ self.assertEqual(content, 'episodes')
def test_get_tvshows(self):
''' Test items, sort and order '''
@@ -128,8 +123,9 @@ def test_random_tvshow_episodes(self):
self.assertTrue(tvshow_items, msg=category['id'])
tvshow = random.choice(tvshow_items)
- episode_items, sort, ascending = self._apihelper.get_episode_items(tvshow.url_dict['video_url'])
+ episode_items, sort, ascending, content = self._apihelper.get_episode_items(tvshow.url_dict['video_url'])
self.assertTrue(episode_items, msg=tvshow.url_dict['video_url'])
+ self.assertTrue(content in ['episodes', 'seasons'], "Content for '%s' is '%s'" % (tvshow.title, content))
if __name__ == '__main__':