Fix checks and tests

This commit is contained in:
Michaël Arnauts 2020-03-20 13:53:21 +01:00
parent 007e684065
commit f1463e9887
13 changed files with 146 additions and 119 deletions

View File

@ -7,7 +7,7 @@
<import addon="script.module.requests" version="2.22.0"/> <import addon="script.module.requests" version="2.22.0"/>
<import addon="script.module.routing" version="0.2.0"/> <import addon="script.module.routing" version="0.2.0"/>
</requires> </requires>
<extension point="xbmc.python.pluginsource" library="addon.py"> <extension point="xbmc.python.pluginsource" library="addon_entry.py">
<provides>video</provides> <provides>video</provides>
</extension> </extension>
<extension point="xbmc.addon.metadata"> <extension point="xbmc.addon.metadata">

View File

@ -1,7 +1,7 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
"""Log handler for Kodi""" """Log handler for Kodi"""
from __future__ import unicode_literals from __future__ import absolute_import, division, unicode_literals
import logging import logging

View File

@ -113,17 +113,17 @@ def addon_profile():
def url_for(name, *args, **kwargs): def url_for(name, *args, **kwargs):
"""Wrapper for routing.url_for() to lookup by name""" """Wrapper for routing.url_for() to lookup by name"""
from resources.lib import addon import addon # pylint: disable=import-error
return addon.routing.url_for(getattr(addon, name), *args, **kwargs) return addon.routing.url_for(getattr(addon, name), *args, **kwargs)
def show_listing(title_items, category=None, sort=None, content=None, cache=True): def show_listing(title_items, category=None, sort=None, content=None, cache=True):
""" Show a virtual directory in Kodi """ """ Show a virtual directory in Kodi """
from resources.lib import addon from addon import routing # pylint: disable=import-error
if content: if content:
# content is one of: files, songs, artists, albums, movies, tvshows, episodes, musicvideos, videos, images, games # content is one of: files, songs, artists, albums, movies, tvshows, episodes, musicvideos, videos, images, games
xbmcplugin.setContent(addon.routing.handle, content=content) xbmcplugin.setContent(routing.handle, content=content)
# Jump through hoops to get a stable breadcrumbs implementation # Jump through hoops to get a stable breadcrumbs implementation
category_label = '' category_label = ''
@ -137,7 +137,7 @@ def show_listing(title_items, category=None, sort=None, content=None, cache=True
elif not content: elif not content:
category_label = addon_name() category_label = addon_name()
xbmcplugin.setPluginCategory(handle=addon.routing.handle, category=category_label) xbmcplugin.setPluginCategory(handle=routing.handle, category=category_label)
# Add all sort methods to GUI (start with preferred) # Add all sort methods to GUI (start with preferred)
if sort is None: if sort is None:
@ -146,7 +146,7 @@ def show_listing(title_items, category=None, sort=None, content=None, cache=True
sort = [sort] + DEFAULT_SORT_METHODS sort = [sort] + DEFAULT_SORT_METHODS
for key in sort: for key in sort:
xbmcplugin.addSortMethod(handle=addon.routing.handle, sortMethod=SORT_METHODS[key]) xbmcplugin.addSortMethod(handle=routing.handle, sortMethod=SORT_METHODS[key])
# Add the listings # Add the listings
listing = [] listing = []
@ -184,13 +184,13 @@ def show_listing(title_items, category=None, sort=None, content=None, cache=True
url = title_item.path if title_item.path else None url = title_item.path if title_item.path else None
listing.append((url, list_item, is_folder)) listing.append((url, list_item, is_folder))
succeeded = xbmcplugin.addDirectoryItems(addon.routing.handle, listing, len(listing)) succeeded = xbmcplugin.addDirectoryItems(routing.handle, listing, len(listing))
xbmcplugin.endOfDirectory(addon.routing.handle, succeeded, cacheToDisc=cache) xbmcplugin.endOfDirectory(routing.handle, succeeded, cacheToDisc=cache)
def play(stream, title=None, art_dict=None, info_dict=None, prop_dict=None): def play(stream, title=None, art_dict=None, info_dict=None, prop_dict=None):
"""Play the given stream""" """Play the given stream"""
from resources.lib.addon import routing from addon import routing # pylint: disable=import-error
play_item = xbmcgui.ListItem(label=title, path=stream) play_item = xbmcgui.ListItem(label=title, path=stream)
if art_dict: if art_dict:
@ -476,7 +476,7 @@ def container_update(url):
def end_of_directory(): def end_of_directory():
"""Close a virtual directory, required to avoid a waiting Kodi""" """Close a virtual directory, required to avoid a waiting Kodi"""
from resources.lib.addon import routing from addon import routing # pylint: disable=import-error
xbmcplugin.endOfDirectory(handle=routing.handle, succeeded=False, updateListing=False, cacheToDisc=False) xbmcplugin.endOfDirectory(handle=routing.handle, succeeded=False, updateListing=False, cacheToDisc=False)
@ -510,8 +510,8 @@ def get_cache(key, ttl=None):
""" Get an item from the cache """ """ Get an item from the cache """
import time import time
path = get_cache_path() path = get_cache_path()
file = '.'.join(key) filename = '.'.join(key)
fullpath = path + file fullpath = path + filename
if not exists(fullpath): if not exists(fullpath):
return None return None
@ -521,7 +521,7 @@ def get_cache(key, ttl=None):
with open_file(fullpath, 'r') as fdesc: with open_file(fullpath, 'r') as fdesc:
try: try:
_LOGGER.info('Fetching {file} from cache', file=file) _LOGGER.info('Fetching {file} from cache', file=filename)
import json import json
value = json.load(fdesc) value = json.load(fdesc)
return value return value
@ -532,13 +532,13 @@ def get_cache(key, ttl=None):
def set_cache(key, data): def set_cache(key, data):
""" Store an item in the cache """ """ Store an item in the cache """
path = get_cache_path() path = get_cache_path()
file = '.'.join(key) filename = '.'.join(key)
fullpath = path + file fullpath = path + filename
if not exists(path): if not exists(path):
mkdirs(path) mkdirs(path)
with open_file(fullpath, 'w') as fdesc: with open_file(fullpath, 'w') as fdesc:
_LOGGER.info('Storing to cache as {file}', file=file) _LOGGER.info('Storing to cache as {file}', file=filename)
import json import json
json.dump(data, fdesc) json.dump(data, fdesc)

View File

@ -70,7 +70,7 @@ class Catalog:
kodiutils.end_of_directory() kodiutils.end_of_directory()
return return
if len(program.episodes) == 0: if not program.episodes:
kodiutils.ok_dialog(message=kodiutils.localize(30717)) # This program is not available in the Vier/Vijf/Zes catalogue. kodiutils.ok_dialog(message=kodiutils.localize(30717)) # This program is not available in the Vier/Vijf/Zes catalogue.
kodiutils.end_of_directory() kodiutils.end_of_directory()
return return
@ -87,37 +87,41 @@ class Catalog:
# Add an '* All seasons' entry when configured in Kodi # Add an '* All seasons' entry when configured in Kodi
if kodiutils.get_global_setting('videolibrary.showallitems') is True: if kodiutils.get_global_setting('videolibrary.showallitems') is True:
listing.append( listing.append(
TitleItem(title='* %s' % kodiutils.localize(30204), # * All seasons TitleItem(
path=kodiutils.url_for('show_catalog_program_season', channel=channel, program=program_id, season=-1), title='* %s' % kodiutils.localize(30204), # * All seasons
art_dict={ path=kodiutils.url_for('show_catalog_program_season', channel=channel, program=program_id, season=-1),
'thumb': program.cover, art_dict={
'fanart': program.background, 'thumb': program.cover,
}, 'fanart': program.background,
info_dict={ },
'tvshowtitle': program.title, info_dict={
'title': kodiutils.localize(30204), # All seasons 'tvshowtitle': program.title,
'plot': program.description, 'title': kodiutils.localize(30204), # All seasons
'set': program.title, 'plot': program.description,
'studio': studio, 'set': program.title,
}) 'studio': studio,
}
)
) )
# Add the seasons # Add the seasons
for s in list(program.seasons.values()): for s in list(program.seasons.values()):
listing.append( listing.append(
TitleItem(title=s.title, # kodiutils.localize(30205, season=s.number), # Season {season} TitleItem(
path=kodiutils.url_for('show_catalog_program_season', channel=channel, program=program_id, season=s.number), title=s.title, # kodiutils.localize(30205, season=s.number), # Season {season}
art_dict={ path=kodiutils.url_for('show_catalog_program_season', channel=channel, program=program_id, season=s.number),
'thumb': s.cover, art_dict={
'fanart': program.background, 'thumb': s.cover,
}, 'fanart': program.background,
info_dict={ },
'tvshowtitle': program.title, info_dict={
'title': kodiutils.localize(30205, season=s.number), # Season {season} 'tvshowtitle': program.title,
'plot': s.description, 'title': kodiutils.localize(30205, season=s.number), # Season {season}
'set': program.title, 'plot': s.description,
'studio': studio, 'set': program.title,
}) 'studio': studio,
}
)
) )
# Sort by label. Some programs return seasons unordered. # Sort by label. Some programs return seasons unordered.

View File

@ -38,21 +38,23 @@ class Channels:
] ]
listing.append( listing.append(
TitleItem(title=channel.get('name'), TitleItem(
path=kodiutils.url_for('show_channel_menu', channel=key), title=channel.get('name'),
art_dict={ path=kodiutils.url_for('show_channel_menu', channel=key),
'icon': icon, art_dict={
'thumb': icon, 'icon': icon,
'fanart': fanart, 'thumb': icon,
}, 'fanart': fanart,
info_dict={ },
'plot': None, info_dict={
'playcount': 0, 'plot': None,
'mediatype': 'video', 'playcount': 0,
'studio': channel.get('studio_icon'), 'mediatype': 'video',
}, 'studio': channel.get('studio_icon'),
stream_dict=STREAM_DICT, },
context_menu=context_menu), stream_dict=STREAM_DICT,
context_menu=context_menu
),
) )
kodiutils.show_listing(listing, 30007) kodiutils.show_listing(listing, 30007)
@ -68,35 +70,41 @@ class Channels:
fanart = '{path}/resources/logos/{logo}'.format(path=kodiutils.addon_path(), logo=channel.get('background')) fanart = '{path}/resources/logos/{logo}'.format(path=kodiutils.addon_path(), logo=channel.get('background'))
listing = [ listing = [
TitleItem(title=kodiutils.localize(30053, channel=channel.get('name')), # TV Guide for {channel} TitleItem(
path=kodiutils.url_for('show_tvguide_channel', channel=key), title=kodiutils.localize(30053, channel=channel.get('name')), # TV Guide for {channel}
art_dict={ path=kodiutils.url_for('show_tvguide_channel', channel=key),
'icon': 'DefaultAddonTvInfo.png', art_dict={
'fanart': fanart, 'icon': 'DefaultAddonTvInfo.png',
}, 'fanart': fanart,
info_dict={ },
'plot': kodiutils.localize(30054, channel=channel.get('name')), # Browse the TV Guide for {channel} info_dict={
}), 'plot': kodiutils.localize(30054, channel=channel.get('name')), # Browse the TV Guide for {channel}
TitleItem(title=kodiutils.localize(30055, channel=channel.get('name')), # Catalog for {channel} }
path=kodiutils.url_for('show_catalog_channel', channel=key), ),
art_dict={ TitleItem(
'icon': 'DefaultMovieTitle.png', title=kodiutils.localize(30055, channel=channel.get('name')), # Catalog for {channel}
'fanart': fanart, path=kodiutils.url_for('show_catalog_channel', channel=key),
}, art_dict={
info_dict={ 'icon': 'DefaultMovieTitle.png',
'plot': kodiutils.localize(30056, channel=channel.get('name')), # Browse the Catalog for {channel} 'fanart': fanart,
}) },
info_dict={
'plot': kodiutils.localize(30056, channel=channel.get('name')), # Browse the Catalog for {channel}
}
)
] ]
# Add YouTube channels # Add YouTube channels
if kodiutils.get_cond_visibility('System.HasAddon(plugin.video.youtube)') != 0: if kodiutils.get_cond_visibility('System.HasAddon(plugin.video.youtube)') != 0:
for youtube in channel.get('youtube', []): for youtube in channel.get('youtube', []):
listing.append( listing.append(
TitleItem(title=kodiutils.localize(30206, label=youtube.get('label')), # Watch {label} on YouTube TitleItem(
path=youtube.get('path'), title=kodiutils.localize(30206, label=youtube.get('label')), # Watch {label} on YouTube
info_dict={ path=youtube.get('path'),
'plot': kodiutils.localize(30206, label=youtube.get('label')), # Watch {label} on YouTube info_dict={
}) 'plot': kodiutils.localize(30206, label=youtube.get('label')), # Watch {label} on YouTube
}
)
) )
kodiutils.show_listing(listing, 30007, sort=['unsorted']) kodiutils.show_listing(listing, 30007, sort=['unsorted'])

View File

@ -19,33 +19,39 @@ class Menu:
def show_mainmenu(): def show_mainmenu():
""" Show the main menu """ """ Show the main menu """
listing = [ listing = [
TitleItem(title=kodiutils.localize(30001), # A-Z TitleItem(
path=kodiutils.url_for('show_catalog'), title=kodiutils.localize(30001), # A-Z
art_dict=dict( path=kodiutils.url_for('show_catalog'),
icon='DefaultMovieTitle.png', art_dict=dict(
fanart=kodiutils.get_addon_info('fanart'), icon='DefaultMovieTitle.png',
), fanart=kodiutils.get_addon_info('fanart'),
info_dict=dict( ),
plot=kodiutils.localize(30002), info_dict=dict(
)), plot=kodiutils.localize(30002),
TitleItem(title=kodiutils.localize(30007), # TV Channels )
path=kodiutils.url_for('show_channels'), ),
art_dict=dict( TitleItem(
icon='DefaultAddonPVRClient.png', title=kodiutils.localize(30007), # TV Channels
fanart=kodiutils.get_addon_info('fanart'), path=kodiutils.url_for('show_channels'),
), art_dict=dict(
info_dict=dict( icon='DefaultAddonPVRClient.png',
plot=kodiutils.localize(30008), fanart=kodiutils.get_addon_info('fanart'),
)), ),
TitleItem(title=kodiutils.localize(30009), # Search info_dict=dict(
path=kodiutils.url_for('show_search'), plot=kodiutils.localize(30008),
art_dict=dict( )
icon='DefaultAddonsSearch.png', ),
fanart=kodiutils.get_addon_info('fanart'), TitleItem(
), title=kodiutils.localize(30009), # Search
info_dict=dict( path=kodiutils.url_for('show_search'),
plot=kodiutils.localize(30010), art_dict=dict(
)) icon='DefaultAddonsSearch.png',
fanart=kodiutils.get_addon_info('fanart'),
),
info_dict=dict(
plot=kodiutils.localize(30010),
)
)
] ]
kodiutils.show_listing(listing, sort=['unsorted']) kodiutils.show_listing(listing, sort=['unsorted'])

View File

@ -72,11 +72,12 @@ class AuthApi:
# Store new tokens in cache # Store new tokens in cache
with open(self._cache + self.TOKEN_FILE, 'wb') as f: with open(self._cache + self.TOKEN_FILE, 'wb') as f:
f.write(json.dumps(dict( data = json.dumps(dict(
id_token=self._id_token, id_token=self._id_token,
refresh_token=self._refresh_token, refresh_token=self._refresh_token,
expiry=self._expiry, expiry=self._expiry,
))) ))
f.write(data.encode('utf8'))
return self._id_token return self._id_token

View File

@ -185,10 +185,11 @@ class AwsIdp:
secret_block_bytes = base64.standard_b64decode(secret_block) secret_block_bytes = base64.standard_b64decode(secret_block)
# the message is a combo of the pool_id, provided SRP userId, the Secret and Timestamp # the message is a combo of the pool_id, provided SRP userId, the Secret and Timestamp
msg = bytearray(self.pool_id.split('_')[1], 'utf-8') + \ msg = \
bytearray(user_id_for_srp, 'utf-8') + \ bytearray(self.pool_id.split('_')[1], 'utf-8') + \
bytearray(secret_block_bytes) + \ bytearray(user_id_for_srp, 'utf-8') + \
bytearray(timestamp, 'utf-8') bytearray(secret_block_bytes) + \
bytearray(timestamp, 'utf-8')
hmac_obj = hmac.new(hkdf, msg, digestmod=hashlib.sha256) hmac_obj = hmac.new(hkdf, msg, digestmod=hashlib.sha256)
signature_string = base64.standard_b64encode(hmac_obj.digest()).decode('utf-8') signature_string = base64.standard_b64encode(hmac_obj.digest()).decode('utf-8')
challenge_request = { challenge_request = {

View File

@ -8,8 +8,8 @@ import logging
import re import re
from datetime import datetime from datetime import datetime
import requests
from six.moves.html_parser import HTMLParser from six.moves.html_parser import HTMLParser
import requests
from resources.lib.viervijfzes import CHANNELS from resources.lib.viervijfzes import CHANNELS

View File

@ -26,6 +26,9 @@ class SearchApi:
:type query: str :type query: str
:rtype list[Program] :rtype list[Program]
""" """
if not query:
return []
response = self._session.post( response = self._session.post(
self.API_ENDPOINT, self.API_ENDPOINT,
json={ json={
@ -35,10 +38,11 @@ class SearchApi:
"mode": "byDate" "mode": "byDate"
} }
) )
data = json.loads(response.content)
if data['timed_out']: if response.status_code != 200:
raise TimeoutError() raise Exception('Could not search')
data = json.loads(response.content)
results = [] results = []
for hit in data['hits']['hits']: for hit in data['hits']['hits']:

View File

@ -1,6 +1,8 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
""" Tests """ """ Tests """
from __future__ import absolute_import, division, unicode_literals
import logging import logging
logging.basicConfig(level=logging.DEBUG) logging.basicConfig(level=logging.DEBUG)

View File

@ -132,6 +132,7 @@ class Player:
''' A stub implementation for the xbmc Player class getPlayingFile() method ''' ''' A stub implementation for the xbmc Player class getPlayingFile() method '''
return '' return ''
class VideoInfoTag: class VideoInfoTag:
''' A stub implementation of the xbmc VideoInfoTag class ''' ''' A stub implementation of the xbmc VideoInfoTag class '''