diff --git a/resources/lib/vrtplayer/__init__.py b/resources/lib/vrtplayer/__init__.py index 0c4d2f33..9901b0f1 100644 --- a/resources/lib/vrtplayer/__init__.py +++ b/resources/lib/vrtplayer/__init__.py @@ -32,7 +32,7 @@ name='Eén', studio='Een', live_stream='https://www.vrt.be/vrtnu/kanalen/een/', - live_stream_id='vualto_een', + live_stream_id='vualto_een_geo', ), 'canvas': dict( id='1H', @@ -40,7 +40,7 @@ name='Canvas', studio='Canvas', live_stream='https://www.vrt.be/vrtnu/kanalen/canvas/', - live_stream_id='vualto_canvas', + live_stream_id='vualto_canvas_geo', ), 'ketnet': dict( id='O9', @@ -48,7 +48,7 @@ name='Ketnet', studio='Ketnet', live_stream='https://www.vrt.be/vrtnu/kanalen/ketnet/', - live_stream_id='vualto_ketnet', + live_stream_id='vualto_ketnet_geo', ), 'ketnet-jr': dict( id='1H', @@ -61,7 +61,7 @@ type='radio+tv', name='Sporza', studio='Sporza', - live_stream_id='vualto_sporza', + live_stream_id='vualto_sporza_geo', ), 'vrtnxt': dict( id='', diff --git a/resources/lib/vrtplayer/streamservice.py b/resources/lib/vrtplayer/streamservice.py index 0942c0fd..0f27a397 100644 --- a/resources/lib/vrtplayer/streamservice.py +++ b/resources/lib/vrtplayer/streamservice.py @@ -78,37 +78,58 @@ def _get_license_key(self, key_url, key_type='R', key_headers=None, key_value=No return '%s|%s|%s|' % (key_url, header, key_value) - def _get_api_data(self, video_url, video_id=None): + def _get_api_data(self, video): + '''Get and prepare api data object''' + video_url = video.get('video_url') + video_id = video.get('video_id') + publication_id = video.get('publication_id') + # Prepare api_data for on demand streams by video_id and publication_id + if video_id and publication_id: + xvrttoken = self.token_resolver.get_xvrttoken() + api_data = apidata.ApiData(self._CLIENT, self._VUALTO_API_URL, video_id, publication_id + requests.utils.quote('$'), xvrttoken, False) + # Prepare api_data for livestreams by video_id, e.g. vualto_strubru, vualto_mnm + elif video_id and not video_url: + api_data = apidata.ApiData(self._CLIENT, self._VUALTO_API_URL, video_id, '', None, True) + # Webscrape api_data with video_id fallback + elif video_url: + api_data = self._webscrape_api_data(video_url) or apidata.ApiData(self._CLIENT, self._VUALTO_API_URL, video_id, '', None, True) + return api_data + + def _webscrape_api_data(self, video_url): + '''Scrape api data from VRT NU html page''' html_page = requests.get(video_url, proxies=self._proxies).text strainer = SoupStrainer('div', {'class': 'cq-dd-vrtvideo'}) soup = BeautifulSoup(html_page, 'html.parser', parse_only=strainer) try: video_data = soup.find(lambda tag: tag.name == 'div' and tag.get('class') == ['vrtvideo']).attrs - except Exception: - # Web scraping failed - video_data = None + except Exception as e: + # Web scraping failed, log error + self._kodi_wrapper.log_error('Web scraping api data failed: %s' % e) + return None - # Web scraping failed, fall back to using video_id only - if not video_data and video_id: - return apidata.ApiData(self._CLIENT, self._VUALTO_API_URL, video_id, '', None, True) + # Web scraping failed, log error + if not video_data: + self._kodi_wrapper.log_error('Web scraping api data failed, empty video_data') + return None - # Store required data attributes + # Store required html data attributes client = video_data.get('data-client') media_api_url = video_data.get('data-mediaapiurl') - video_id = video_data.get('data-videoid') - # Is this a livestream instead ? + publication_id = video_data.get('data-publicationid', '') + # Live stream or on demand if video_id is None: is_live_stream = True - xvrttoken = None video_id = video_data.get('data-livestream') + xvrttoken = None else: is_live_stream = False + publication_id += requests.utils.quote('$') xvrttoken = self.token_resolver.get_xvrttoken() - publication_id = video_data.get('data-publicationid', '') - if publication_id: - publication_id += requests.utils.quote('$') + if client is None or media_api_url is None or (video_id is None and publication_id is None): + self._kodi_wrapper.log_error('Web scraping api data failed, required attributes missing') + return None return apidata.ApiData(client, media_api_url, video_id, publication_id, xvrttoken, is_live_stream) @@ -156,22 +177,9 @@ def _fix_virtualsubclip(stream_dict, duration): return stream_dict def get_stream(self, video, retry=False, api_data=None): - video_url = video.get('video_url') - video_id = video.get('video_id') - publication_id = video.get('publication_id') - # Prepare api_data for on demand streams by video_id and publication_id - if video_id and publication_id and not retry: - xvrttoken = self.token_resolver.get_xvrttoken() - api_data = apidata.ApiData(self._CLIENT, self._VUALTO_API_URL, video_id, publication_id + requests.utils.quote('$'), xvrttoken, False) - # Prepare api_data for livestreams by video_id, e.g. vualto_strubru, vualto_mnm - elif video_id and not video_url: - api_data = apidata.ApiData(self._CLIENT, self._VUALTO_API_URL, video_id, '', None, True) - # Support .mpd streams directly (only works on Kodi 18+ with inputstream.adaptive) - elif video_url.endswith('.mpd'): - return streamurls.StreamURLS(video_url, use_inputstream_adaptive=True) - # Webscrape api_data from html video_url - else: - api_data = api_data or self._get_api_data(video_url, video_id) + '''Main streamservice function''' + if not api_data: + api_data = self._get_api_data(video) vudrm_token = None video_json = self._get_video_json(api_data) diff --git a/resources/lib/vrtplayer/vrtplayer.py b/resources/lib/vrtplayer/vrtplayer.py index 20420f28..08ca5aa8 100644 --- a/resources/lib/vrtplayer/vrtplayer.py +++ b/resources/lib/vrtplayer/vrtplayer.py @@ -88,7 +88,7 @@ def show_category_menu_items(self): def show_livestream_items(self): livestream_items = [] - for channel in ['een', 'canvas', 'ketnet', 'stubru', 'mnm']: + for channel in ['een', 'canvas', 'ketnet', 'sporza', 'stubru', 'mnm']: if channel in ['een', 'canvas', 'ketnet']: thumbnail = self.__get_media(channel + '.png') fanart = self._api_helper.get_live_screenshot(channel)