From c06f76e3b7d64f7060e70dfa2468f5afdf68fdae Mon Sep 17 00:00:00 2001 From: Lee Smith Date: Sun, 26 Nov 2017 22:17:45 +0000 Subject: [plugin.video.ecbtv] 0.6.0 (#1525) --- plugin.video.ecbtv/addon.py | 39 ++++-- plugin.video.ecbtv/addon.xml | 5 +- .../language/resource.language.en_gb/strings.po | 12 ++ plugin.video.ecbtv/resources/lib/api.py | 132 +++++++++++++-------- 4 files changed, 127 insertions(+), 61 deletions(-) diff --git a/plugin.video.ecbtv/addon.py b/plugin.video.ecbtv/addon.py index 03f86f0..1a64e53 100644 --- a/plugin.video.ecbtv/addon.py +++ b/plugin.video.ecbtv/addon.py @@ -24,7 +24,11 @@ # ############################################################################### +import itertools +import traceback + from kodiswift import Plugin +import rollbar.kodi from resources.lib import api @@ -34,18 +38,26 @@ PAGE_SIZE = 9 plugin = Plugin(addon_id='plugin.video.ecbtv') +def tournaments(): + return itertools.chain( + itertools.islice(api.england_tournaments(), 3), + api.county_tournaments() + ) + + def top_level_categories(): - yield {'label': u'[B]{}[/B]'.format(plugin.get_string(30002)), + for tournament in tournaments(): + yield {'label': tournament.name, + 'path': plugin.url_for('show_videos_by_reference_first_page', + reference=tournament.reference)} + yield {'label': plugin.get_string(30002), 'path': plugin.url_for('show_all_videos_first_page')} - yield {'label': u'[B]{}[/B]'.format(plugin.get_string(30001)), - 'path': plugin.url_for('search')} - yield {'label': 'England', + yield {'label': plugin.get_string(30005), 'path': plugin.url_for('show_videos_by_reference_first_page', reference=api.england().reference)} - yield {'label': 'Counties', - 'path': plugin.url_for('show_counties')} - yield {'label': 'Players', - 'path': plugin.url_for('show_player_categories')} + yield {'label': plugin.get_string(30006), 'path': plugin.url_for('show_player_categories')} + yield {'label': plugin.get_string(30007), 'path': plugin.url_for('show_counties')} + yield {'label': plugin.get_string(30001), 'path': plugin.url_for('search')} def subcategories(categories, route): @@ -163,4 +175,13 @@ def search(): if __name__ == '__main__': - plugin.run() + try: + plugin.run() + except Exception as exc: + if rollbar.kodi.error_report_requested(exc): + rollbar.kodi.report_error( + access_token='222e7ea9c2e74fd989c48b448a58978e', + version=plugin.addon.getAddonInfo('version'), + url=plugin.request.url + ) + plugin.log.error(traceback.format_exc()) diff --git a/plugin.video.ecbtv/addon.xml b/plugin.video.ecbtv/addon.xml index 89e2c17..b0dad41 100644 --- a/plugin.video.ecbtv/addon.xml +++ b/plugin.video.ecbtv/addon.xml @@ -1,10 +1,11 @@ - + + video @@ -21,6 +22,6 @@ resources/icon.png resources/fanart.jpg - Fixed and improved video browsing after website changes. + Added recent and future tournaments at the top level diff --git a/plugin.video.ecbtv/resources/language/resource.language.en_gb/strings.po b/plugin.video.ecbtv/resources/language/resource.language.en_gb/strings.po index 646d379..392e944 100644 --- a/plugin.video.ecbtv/resources/language/resource.language.en_gb/strings.po +++ b/plugin.video.ecbtv/resources/language/resource.language.en_gb/strings.po @@ -31,3 +31,15 @@ msgstr "" msgctxt "#30004" msgid "Next Page" msgstr "" + +msgctxt "#30005" +msgid "England" +msgstr "" + +msgctxt "#30006" +msgid "By England Player" +msgstr "" + +msgctxt "#30007" +msgid "By County" +msgstr "" diff --git a/plugin.video.ecbtv/resources/lib/api.py b/plugin.video.ecbtv/resources/lib/api.py index c8072c8..1eabc67 100644 --- a/plugin.video.ecbtv/resources/lib/api.py +++ b/plugin.video.ecbtv/resources/lib/api.py @@ -30,9 +30,8 @@ Module for extracting video links from the England and Wales Cricket Board websi import os import re -from urlparse import urljoin, urlparse, urlunparse -from urllib import urlencode -from datetime import datetime +from urlparse import urljoin +from datetime import datetime, date, timedelta import time from collections import namedtuple import math @@ -50,36 +49,48 @@ PLAYER_THUMB_URL_FMT = 'https://ecb-resources.s3.amazonaws.com/player-photos/{}/ SEARCH_URL = 'https://content-ecb.pulselive.com/search/ecb/' VIDEO_LIST_URL = 'https://content-ecb.pulselive.com/content/ecb/EN/' +TOURNAMENTS_URL = 'https://cricketapi-ecb.pulselive.com/tournaments/' -Video = namedtuple('Video', 'title url thumbnail date duration') -Entity = namedtuple('Entity', 'name reference thumbnail') +_Video = namedtuple('Video', 'title url thumbnail date duration') +_Entity = namedtuple('Entity', 'name id reference thumbnail') -def _video_list_url(reference, page, page_size=10): - '''Returns a URL for a list of videos''' - url_parts = list(urlparse(VIDEO_LIST_URL)) - query_params = dict( +def _video_query_params(reference, page, page_size=10): + '''Returns a dictionary of query params for a list of videos''' + return dict( contentTypes='video', references=reference if reference is not None else '', page=page - 1, pageSize=page_size ) - url_parts[4] = urlencode(query_params) - return urlunparse(url_parts) -def _search_url(term, page, page_size=10): - '''Returns a URL for the JSON search api''' - url_parts = list(urlparse(SEARCH_URL)) - query_params = dict( +def _search_query_params(term, page, page_size=10): + '''Returns a dictionary of query params for the JSON search api''' + return dict( type='VIDEO', fullObjectResponse=True, terms=term, size=page_size, start=(page - 1) * page_size ) - url_parts[4] = urlencode(query_params) - return urlunparse(url_parts) + + +def _tournaments_query_params(team_ids, + match_types, + weeks_ago, + weeks_ahead): + '''Returns a dictionary of query params for the list of tournaments''' + query_params = dict( + teamIds=','.join(map(str, team_ids)), + startDate=date.today() - timedelta(weeks=weeks_ago), + endDate=date.today() + timedelta(weeks=weeks_ahead), + sort='desc') + if match_types is not None: + query_params['matchTypes'] = ','.join( + str(t).replace(' ', '_').upper() for t in match_types + ) + return query_params def _soup(path=''): @@ -101,15 +112,14 @@ def _date_json(json_item): date_str = json_item['date'] for fmt in ['%Y-%m-%dT%H:%M', '%d/%m/%Y %H:%M']: try: - date = _date_from_str(date_str.strip(), fmt=fmt) + return _date_from_str(date_str.strip(), fmt=fmt) except ValueError as exc: continue - else: - return date raise exc def _thumbnail_variant(video): + '''Returns the url for the "Media Thumbnail - Squared Medium" thumbnail''' if video['thumbnail'] is None: return return (variant['url'] for variant in video['thumbnail']['variants'] @@ -117,46 +127,82 @@ def _thumbnail_variant(video): def england(): - return Entity( + '''Returns an Entity for the England Men team''' + return _Entity( name='England', + id=11, reference='cricket_team:11', thumbnail=None ) def counties(): + '''Generator for an Entity for each county team''' for county in _soup('/county-championship/teams')('div', 'partners__item'): team_id = int(os.path.basename(county.a['href'])) - yield Entity( + yield _Entity( name=county.a.text, + id=team_id, reference='cricket_team:{}'.format(team_id), thumbnail=county.img['src'] ) def player_categories(): + '''Generator for an Entity representing each form of the game''' for tab in _soup('/england/men/players').find_all( 'div', attrs={'data-ui-args': re.compile(r'{ "title": "\w+" }')}): - yield Entity( + yield _Entity( name=tab['data-ui-tab'], + id=None, reference=None, thumbnail=None ) def players(category='Test'): + '''Generator for England players currently playing in the provided form of the game''' soup = _soup('/england/men/players').find('div', attrs={'data-ui-tab': category}) for player in soup('section', 'profile-player-card'): player_id = player.img['data-player'] - yield Entity( + yield _Entity( name=player.img['alt'], + id=player_id, reference='cricket_player:{}'.format(player_id), thumbnail=PLAYER_THUMB_URL_FMT.format(category.lower(), player_id) ) +def _tournaments(team_ids, + match_types=None, + weeks_ago=26, + weeks_ahead=4): + for tournament in requests.get( + url=TOURNAMENTS_URL, + params=_tournaments_query_params(team_ids, match_types, weeks_ago, weeks_ahead) + ).json()['content']: + yield _Entity( + name=tournament['description'], + id=tournament['id'], + thumbnail=None, + reference='cricket_tournament:{}'.format(tournament['id']) + ) + + +def england_tournaments(): + '''Returns a generator for all tournaments played by the England Men''' + return _tournaments([england().id], ['Test', 'ODI', 'T20I']) + + +def county_tournaments(): + '''Generator for all tournaments played by a county, excluding tour matches''' + for tournament in _tournaments([county.id for county in counties()], weeks_ahead=0): + if not re.search(' in [A-Z]', tournament.name): + yield tournament + + def _video(video): - return Video( + return _Video( title=video['title'], url=HLS_URL_FMT.format(video['mediaId']), thumbnail=_thumbnail_variant(video), @@ -172,7 +218,12 @@ def _videos(videos_json): def videos(reference=None, page=1, page_size=10): - videos_json = requests.get(_video_list_url(reference, page, page_size)).json() + '''Returns a generator for videos matching a reference string, + and the number of pages''' + videos_json = requests.get( + url=VIDEO_LIST_URL, + params=_video_query_params(reference, page, page_size) + ).json() npages = videos_json['pageInfo']['numPages'] return _videos(videos_json), npages @@ -186,30 +237,11 @@ def _search_results(search_results_json): def search_results(term, page=1, page_size=10): - search_results_json = requests.get(_search_url(term, page, page_size)).json() + '''Returns a generator for search results and the number of pages''' + search_results_json = requests.get( + url=SEARCH_URL, + params=_search_query_params(term, page, page_size) + ).json() total = search_results_json['hits']['found'] npages = int(math.ceil(float(total) / page_size)) return _search_results(search_results_json), npages - - -def _print_team_videos(): - '''Test function to print all categories and videos''' - for team in [england()] + list(counties()): - print '{} ({})'.format(team.name, team.reference) - videos_page, _num_pages = videos(team.reference) - for video in videos_page: - print '\t', video.title - - -def _print_search_results(term): - '''Test function to print search results''' - print 'Search: {}'.format(term) - videos_page, _num_pages = search_results(term) - for video in videos_page: - print '\t', video.title - - -if __name__ == '__main__': - _print_team_videos() - print - _print_search_results('test cricket') -- cgit v1.2.3