Improve artwork (#79)

* Update channel logo's
* Improve artwork selection
* Filter out <br /> in descriptions
This commit is contained in:
Michaël Arnauts 2021-03-19 16:45:26 +01:00 committed by GitHub
parent d8b95cd2e9
commit 8f59c16eab
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
12 changed files with 52 additions and 39 deletions

View File

@ -44,6 +44,7 @@ HTML_MAPPING = [
(re.compile(r'<li>', re.I), '- '), (re.compile(r'<li>', re.I), '- '),
(re.compile(r'</?(li|ul|ol)(|\s[^>]+)>', re.I), '\n'), (re.compile(r'</?(li|ul|ol)(|\s[^>]+)>', re.I), '\n'),
(re.compile(r'</?(code|div|p|pre|span)(|\s[^>]+)>', re.I), ''), (re.compile(r'</?(code|div|p|pre|span)(|\s[^>]+)>', re.I), ''),
(re.compile(r'<br />', re.I), '\n'), # Remove newlines
(re.compile('(&nbsp;\n){2,}', re.I), '\n'), # Remove repeating non-blocking spaced newlines (re.compile('(&nbsp;\n){2,}', re.I), '\n'), # Remove repeating non-blocking spaced newlines
(re.compile(' +', re.I), ' '), # Remove double spaces (re.compile(' +', re.I), ' '), # Remove double spaces
] ]

View File

@ -87,7 +87,9 @@ class Catalog:
title='* %s' % kodiutils.localize(30204), # * All seasons title='* %s' % kodiutils.localize(30204), # * All seasons
path=kodiutils.url_for('show_catalog_program_season', program=program_id, season='-1'), path=kodiutils.url_for('show_catalog_program_season', program=program_id, season='-1'),
art_dict={ art_dict={
'fanart': program.background, 'fanart': program.fanart,
'poster': program.poster,
'landscape': program.thumb,
}, },
info_dict={ info_dict={
'tvshowtitle': program.title, 'tvshowtitle': program.title,
@ -105,7 +107,9 @@ class Catalog:
title=season.title, # kodiutils.localize(30205, season=season.number), # Season {season} title=season.title, # kodiutils.localize(30205, season=season.number), # Season {season}
path=kodiutils.url_for('show_catalog_program_season', program=program_id, season=season.uuid), path=kodiutils.url_for('show_catalog_program_season', program=program_id, season=season.uuid),
art_dict={ art_dict={
'fanart': program.background, 'fanart': program.fanart,
'poster': program.poster,
'landscape': program.thumb,
}, },
info_dict={ info_dict={
'tvshowtitle': program.title, 'tvshowtitle': program.title,
@ -123,7 +127,9 @@ class Catalog:
title=kodiutils.localize(30059, program=program.title), # Clips for {program} title=kodiutils.localize(30059, program=program.title), # Clips for {program}
path=kodiutils.url_for('show_catalog_program_clips', program=program_id), path=kodiutils.url_for('show_catalog_program_clips', program=program_id),
art_dict={ art_dict={
'fanart': program.background, 'fanart': program.fanart,
'poster': program.poster,
'landscape': program.thumb,
}, },
info_dict={ info_dict={
'tvshowtitle': program.title, 'tvshowtitle': program.title,

View File

@ -83,7 +83,7 @@ class IPTVManager:
episode='S%sE%s' % (program.season, program.number) if program.season and program.number else None, episode='S%sE%s' % (program.season, program.number) if program.season and program.number else None,
genre=program.genre, genre=program.genre,
genre_id=program.genre_id, genre_id=program.genre_id,
image=program.cover, image=program.thumb,
stream=kodiutils.url_for('play_from_page', stream=kodiutils.url_for('play_from_page',
channel=key, channel=key,
page=quote(program.video_url, safe='')) if program.video_url else None) page=quote(program.video_url, safe='')) if program.video_url else None)

View File

@ -100,11 +100,6 @@ class Menu:
:type item: Union[Program, Episode] :type item: Union[Program, Episode]
:rtype TitleItem :rtype TitleItem
""" """
art_dict = {
'thumb': item.cover,
'cover': item.cover,
'fanart': item.background or item.cover,
}
info_dict = { info_dict = {
'title': item.title, 'title': item.title,
'plot': item.description, 'plot': item.description,
@ -121,6 +116,13 @@ class Menu:
'season': len(item.seasons) if item.seasons else None, 'season': len(item.seasons) if item.seasons else None,
}) })
art_dict = {
'poster': item.poster,
'landscape': item.thumb,
'thumb': item.thumb,
'fanart': item.fanart,
}
visible = True visible = True
if isinstance(item.episodes, list) and not item.episodes: if isinstance(item.episodes, list) and not item.episodes:
# We know that we don't have episodes # We know that we don't have episodes
@ -171,6 +173,12 @@ class Menu:
'episode': item.number, 'episode': item.number,
}) })
art_dict = {
'landscape': item.thumb,
'thumb': item.thumb,
'fanart': item.thumb,
}
stream_dict = STREAM_DICT.copy() stream_dict = STREAM_DICT.copy()
stream_dict.update({ stream_dict.update({
'duration': item.duration, 'duration': item.duration,

View File

@ -154,8 +154,7 @@ class TvGuide:
TitleItem(title=title, TitleItem(title=title,
path=path, path=path,
art_dict={ art_dict={
'icon': program.cover, 'thumb': program.thumb,
'thumb': program.cover,
}, },
info_dict=info_dict, info_dict=info_dict,
stream_dict=stream_dict, stream_dict=stream_dict,

View File

@ -45,7 +45,8 @@ class GeoblockedException(Exception):
class Program: class Program:
""" Defines a Program. """ """ Defines a Program. """
def __init__(self, uuid=None, path=None, channel=None, title=None, description=None, aired=None, cover=None, background=None, seasons=None, episodes=None, def __init__(self, uuid=None, path=None, channel=None, title=None, description=None, aired=None, poster=None, thumb=None, fanart=None, seasons=None,
episodes=None,
clips=None, my_list=False): clips=None, my_list=False):
""" """
:type uuid: str :type uuid: str
@ -54,8 +55,9 @@ class Program:
:type title: str :type title: str
:type description: str :type description: str
:type aired: datetime :type aired: datetime
:type cover: str :type poster: str
:type background: str :type thumb: str
:type fanart: str
:type seasons: list[Season] :type seasons: list[Season]
:type episodes: list[Episode] :type episodes: list[Episode]
:type clips: list[Episode] :type clips: list[Episode]
@ -67,8 +69,9 @@ class Program:
self.title = title self.title = title
self.description = description self.description = description
self.aired = aired self.aired = aired
self.cover = cover self.poster = poster
self.background = background self.thumb = thumb
self.fanart = fanart
self.seasons = seasons self.seasons = seasons
self.episodes = episodes self.episodes = episodes
self.clips = clips self.clips = clips
@ -81,14 +84,13 @@ class Program:
class Season: class Season:
""" Defines a Season. """ """ Defines a Season. """
def __init__(self, uuid=None, path=None, channel=None, title=None, description=None, cover=None, number=None): def __init__(self, uuid=None, path=None, channel=None, title=None, description=None, number=None):
""" """
:type uuid: str :type uuid: str
:type path: str :type path: str
:type channel: str :type channel: str
:type title: str :type title: str
:type description: str :type description: str
:type cover: str
:type number: int :type number: int
""" """
@ -97,7 +99,6 @@ class Season:
self.channel = channel self.channel = channel
self.title = title self.title = title
self.description = description self.description = description
self.cover = cover
self.number = number self.number = number
def __repr__(self): def __repr__(self):
@ -107,8 +108,8 @@ class Season:
class Episode: class Episode:
""" Defines an Episode. """ """ Defines an Episode. """
def __init__(self, uuid=None, nodeid=None, path=None, channel=None, program_title=None, title=None, description=None, cover=None, background=None, def __init__(self, uuid=None, nodeid=None, path=None, channel=None, program_title=None, title=None, description=None, thumb=None, duration=None,
duration=None, season=None, season_uuid=None, number=None, rating=None, aired=None, expiry=None, stream=None): season=None, season_uuid=None, number=None, rating=None, aired=None, expiry=None, stream=None):
""" """
:type uuid: str :type uuid: str
:type nodeid: str :type nodeid: str
@ -117,8 +118,7 @@ class Episode:
:type program_title: str :type program_title: str
:type title: str :type title: str
:type description: str :type description: str
:type cover: str :type thumb: str
:type background: str
:type duration: int :type duration: int
:type season: int :type season: int
:type season_uuid: str :type season_uuid: str
@ -135,8 +135,7 @@ class Episode:
self.program_title = program_title self.program_title = program_title
self.title = title self.title = title
self.description = description self.description = description
self.cover = cover self.thumb = thumb
self.background = background
self.duration = duration self.duration = duration
self.season = season self.season = season
self.season_uuid = season_uuid self.season_uuid = season_uuid
@ -501,7 +500,7 @@ class ContentApi:
programs.append(Program( programs.append(Program(
path=path.lstrip('/'), path=path.lstrip('/'),
title=unescape(item.group('title')), title=unescape(item.group('title')),
cover=unescape(item.group('image')), poster=unescape(item.group('image')),
)) ))
return programs return programs
@ -579,7 +578,7 @@ class ContentApi:
description=html_to_kodi(description), description=html_to_kodi(description),
duration=episode_duration, duration=episode_duration,
uuid=episode_video_id, uuid=episode_video_id,
cover=episode_image, thumb=episode_image,
program_title=episode_program, program_title=episode_program,
)) ))
@ -599,8 +598,9 @@ class ContentApi:
title=data['title'], title=data['title'],
description=html_to_kodi(data['description']), description=html_to_kodi(data['description']),
aired=datetime.fromtimestamp(data.get('pageInfo', {}).get('publishDate')), aired=datetime.fromtimestamp(data.get('pageInfo', {}).get('publishDate')),
cover=data['images']['poster'], poster=data['images']['poster'],
background=data['images']['hero'], thumb=data['images']['teaser'],
fanart=data['images']['hero'],
) )
# Create Season info # Create Season info
@ -651,8 +651,7 @@ class ContentApi:
program_title=data.get('program', {}).get('title') if data.get('program') else data.get('title'), program_title=data.get('program', {}).get('title') if data.get('program') else data.get('title'),
title=data.get('title'), title=data.get('title'),
description=html_to_kodi(data.get('description')), description=html_to_kodi(data.get('description')),
cover=data.get('image'), thumb=data.get('image'),
background=data.get('image'),
duration=data.get('duration'), duration=data.get('duration'),
season=data.get('seasonNumber'), season=data.get('seasonNumber'),
season_uuid=season_uuid, season_uuid=season_uuid,

View File

@ -37,7 +37,7 @@ class EpgProgram:
# pylint: disable=invalid-name # pylint: disable=invalid-name
def __init__(self, channel, program_title, episode_title, episode_title_original, number, season, genre, start, def __init__(self, channel, program_title, episode_title, episode_title_original, number, season, genre, start,
won_id, won_program_id, program_description, description, duration, program_url, video_url, cover, won_id, won_program_id, program_description, description, duration, program_url, video_url, thumb,
airing): airing):
self.channel = channel self.channel = channel
self.program_title = program_title self.program_title = program_title
@ -54,7 +54,7 @@ class EpgProgram:
self.duration = duration self.duration = duration
self.program_url = program_url self.program_url = program_url
self.video_url = video_url self.video_url = video_url
self.cover = cover self.thumb = thumb
self.airing = airing self.airing = airing
if GENRE_MAPPING.get(self.genre): if GENRE_MAPPING.get(self.genre):
@ -86,7 +86,7 @@ class EpgApi:
:type channel: str :type channel: str
:type date: str :type date: str
:rtype list[EpgProgram] :rtype list[EpgProgram]
""" """
if channel not in self.EPG_ENDPOINTS: if channel not in self.EPG_ENDPOINTS:
raise Exception('Unknown channel %s' % channel) raise Exception('Unknown channel %s' % channel)
@ -127,10 +127,10 @@ class EpgApi:
# Only allow direct playing if the linked video is the actual program # Only allow direct playing if the linked video is the actual program
if data.get('video_node', {}).get('latest_video'): if data.get('video_node', {}).get('latest_video'):
video_url = (data.get('video_node', {}).get('url') or '').lstrip('/') video_url = (data.get('video_node', {}).get('url') or '').lstrip('/')
cover = data.get('video_node', {}).get('image') thumb = data.get('video_node', {}).get('image')
else: else:
video_url = None video_url = None
cover = None thumb = None
return EpgProgram( return EpgProgram(
channel=channel, channel=channel,
@ -148,7 +148,7 @@ class EpgApi:
duration=duration, duration=duration,
program_url=(data.get('program_node', {}).get('url') or '').lstrip('/'), program_url=(data.get('program_node', {}).get('url') or '').lstrip('/'),
video_url=video_url, video_url=video_url,
cover=cover, thumb=thumb,
airing=airing, airing=airing,
) )

View File

@ -56,7 +56,7 @@ class SearchApi:
path=path, path=path,
title=hit['_source']['title'], title=hit['_source']['title'],
description=hit['_source']['intro'], description=hit['_source']['intro'],
cover=hit['_source']['img'], poster=hit['_source']['img'],
)) ))
return results return results

Binary file not shown.

Before

Width:  |  Height:  |  Size: 7.1 KiB

After

Width:  |  Height:  |  Size: 4.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.0 KiB

After

Width:  |  Height:  |  Size: 3.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 9.4 KiB

After

Width:  |  Height:  |  Size: 4.5 KiB

View File

@ -75,7 +75,7 @@ class TestApi(unittest.TestCase):
@unittest.skipUnless(kodiutils.get_setting('username') and kodiutils.get_setting('password'), 'Skipping since we have no credentials.') @unittest.skipUnless(kodiutils.get_setting('username') and kodiutils.get_setting('password'), 'Skipping since we have no credentials.')
def test_get_drm_stream(self): def test_get_drm_stream(self):
resolved_stream = self._api.get_stream_by_uuid('f6d2f756-e0bf-4caa-822c-7ff0d10cc8dd') # Hawaii Five-O 8x25 resolved_stream = self._api.get_stream_by_uuid('01998ce7-b2ad-4524-a786-33d419a29d7b') # CSI 12x22
self.assertIsInstance(resolved_stream, ResolvedStream) self.assertIsInstance(resolved_stream, ResolvedStream)