예제 #1
0
    def login(self, refresh=False, token_variant=None):
        """Kodi GUI login flow"""
        # If no credentials, ask user for credentials
        if not has_credentials():
            if refresh:
                return open_settings()
            open_settings()
            if not self._credentials_changed():
                return None

        # Check credentials
        login_json = self._get_login_json()

        # Bad credentials
        while login_json.get('errorCode') != 0:
            # Show localized login error messages in Kodi GUI
            message = login_json.get('errorDetails')
            log_error('Login failed: {msg}', msg=message)
            if message == 'invalid loginID or password':
                message = localize(30953)  # Invalid login!
            elif message == 'loginID must be provided':
                message = localize(30955)  # Please fill in username
            elif message == 'Missing required parameter: password':
                message = localize(30956)  # Please fill in password
            ok_dialog(heading=localize(30951), message=message)  # Login failed!
            if refresh:
                return open_settings()
            open_settings()
            if not self._credentials_changed():
                return None
            login_json = self._get_login_json()

        # Get token
        return self._get_new_xvrttoken(login_json, token_variant)
    def manage(self):
        """Allow the user to unselect favorites to be removed from the listing"""
        self.refresh(ttl=0)
        if not self._favorites:
            ok_dialog(heading=localize(30418),
                      message=localize(30419))  # No favorites found
            return

        def by_title(tup):
            """Sort by title"""
            _, value = tup
            return value.get('title')

        items = [
            dict(program_id=value.get('program_id'),
                 program_name=key,
                 title=unquote(value.get('title')))
            for key, value in sorted(self._favorites.items(), key=by_title)
        ]
        titles = [item['title'] for item in items]
        preselect = list(range(0, len(items)))
        selected = multiselect(
            localize(30420), options=titles,
            preselect=preselect)  # Please select/unselect to follow/unfollow
        if selected is not None:
            for idx in set(preselect).difference(set(selected)):
                self.unfollow(program_name=items[idx]['program_name'],
                              title=items[idx]['title'],
                              program_id=items[idx]['program_id'])
            for idx in set(selected).difference(set(preselect)):
                self.follow(program_name=items[idx]['program_name'],
                            title=items[idx]['title'],
                            program_id=items[idx]['program_id'])
예제 #3
0
    def manage(self):
        """Allow the user to unselect favorites to be removed from the listing"""
        from utils import url_to_program
        self.refresh(ttl=0)
        if not self._data:
            ok_dialog(heading=localize(30418),
                      message=localize(30419))  # No favorites found
            return

        def by_title(item):
            """Sort by title"""
            return item.get('value').get('title')

        items = [
            dict(program=url_to_program(value.get('value').get('programUrl')),
                 title=unquote(value.get('value').get('title')),
                 enabled=value.get('value').get('isFavorite'))
            for value in list(sorted(list(self._data.values()), key=by_title))
        ]
        titles = [item['title'] for item in items]
        preselect = [
            idx for idx in range(0,
                                 len(items) - 1) if items[idx]['enabled']
        ]
        selected = multiselect(
            localize(30420), options=titles,
            preselect=preselect)  # Please select/unselect to follow/unfollow
        if selected is not None:
            for idx in set(preselect).difference(set(selected)):
                self.unfollow(program=items[idx]['program'],
                              title=items[idx]['title'])
            for idx in set(selected).difference(set(preselect)):
                self.follow(program=items[idx]['program'],
                            title=items[idx]['title'])
예제 #4
0
    def show_favorites_menu(self):
        ''' The VRT NU addon 'My programs' menu '''
        self._favorites.refresh(ttl=60 * 60)
        favorites_items = [
            TitleItem(
                title=localize(30040),  # My programs
                path=url_for('favorites_programs'),
                art_dict=dict(thumb='DefaultMovieTitle.png'),
                info_dict=dict(plot=localize(30041))),
            TitleItem(
                title=localize(30046),  # My recent items
                path=url_for('favorites_recent'),
                art_dict=dict(thumb='DefaultRecentlyAddedEpisodes.png'),
                info_dict=dict(plot=localize(30047))),
            TitleItem(
                title=localize(30048),  # My soon offline
                path=url_for('favorites_offline'),
                art_dict=dict(thumb='DefaultYear.png'),
                info_dict=dict(plot=localize(30049))),
        ]

        # Only add 'My watch later' and 'Continue watching' when it has been activated
        if self._resumepoints.is_activated():
            favorites_items.append(
                TitleItem(
                    title=localize(30050),  # My watch later
                    path=url_for('resumepoints_watchlater'),
                    art_dict=dict(thumb='DefaultVideoPlaylists.png'),
                    info_dict=dict(plot=localize(30051)),
                ))
            favorites_items.append(
                TitleItem(
                    title=localize(30052),  # Continue Watching
                    path=url_for('resumepoints_continue'),
                    art_dict=dict(thumb='DefaultInProgressShows.png'),
                    info_dict=dict(plot=localize(30053)),
                ))

        if get_setting('addmymovies', 'true') == 'true':
            favorites_items.append(
                TitleItem(
                    title=localize(30042),  # My movies
                    path=url_for('categories', category='films'),
                    art_dict=dict(thumb='DefaultAddonVideo.png'),
                    info_dict=dict(plot=localize(30043))), )

        if get_setting('addmydocu', 'true') == 'true':
            favorites_items.append(
                TitleItem(
                    title=localize(30044),  # My documentaries
                    path=url_for('favorites_docu'),
                    art_dict=dict(thumb='DefaultMovies.png'),
                    info_dict=dict(plot=localize(30045))), )

        show_listing(favorites_items, category=30010,
                     cache=False)  # My favorites

        # Show dialog when no favorites were found
        if not self._favorites.titles():
            ok_dialog(heading=localize(30415), message=localize(30416))
예제 #5
0
 def play_whatson(self, whatson_id):
     ''' Play a video by whatson_id '''
     video = self._apihelper.get_single_episode(whatson_id)
     if not video:
         log_error('Play by whatson_id {id} failed', id=whatson_id)
         ok_dialog(message=localize(30954))
         end_of_directory()
         return
     self.play(video)
예제 #6
0
 def play_latest_episode(self, program):
     """A hidden feature in the VRT NU add-on to play the latest episode of a program"""
     video = self._apihelper.get_latest_episode(program)
     if not video:
         log_error('Play latest episode failed, program {program}', program=program)
         ok_dialog(message=localize(30954))
         end_of_directory()
         return
     self.play(video)
예제 #7
0
 def play_episode_by_whatson_id(self, whatson_id):
     """Play an episode of a program given the whatson_id"""
     video = self._apihelper.get_single_episode(whatson_id=whatson_id)
     if not video:
         log_error('Play episode by whatson_id failed, whatson_id {whatson_id}', whatson_id=whatson_id)
         ok_dialog(message=localize(30954))
         end_of_directory()
         return
     self.play(video)
    def _select_hls_substreams(self, master_hls_url, protocol):
        """Select HLS substreams to speed up Kodi player start, workaround for slower Kodi selection"""
        hls_variant_url = None
        subtitle_url = None
        hls_audio_id = None
        hls_subtitle_id = None
        hls_base_url = master_hls_url.split('.m3u8')[0]
        try:
            response = open_url(master_hls_url, raise_errors=[415])
        except HTTPError as exc:
            self._handle_bad_stream_error(protocol, exc.code, exc.reason)
            return None
        if response is None:
            return None
        hls_playlist = to_unicode(response.read())
        max_bandwidth = get_max_bandwidth()
        stream_bandwidth = None

        # Get hls variant url based on max_bandwidth setting
        import re
        hls_variant_regex = re.compile(r'#EXT-X-STREAM-INF:[\w\-.,=\"]*?BANDWIDTH=(?P<BANDWIDTH>\d+),'
                                       r'[\w\-.,=\"]+\d,(?:AUDIO=\"(?P<AUDIO>[\w\-]+)\",)?(?:SUBTITLES=\"'
                                       r'(?P<SUBTITLES>\w+)\",)?[\w\-.,=\"]+?[\r\n](?P<URI>[\w:\/\-.=?&]+)')
        # reverse sort by bandwidth
        for match in sorted(re.finditer(hls_variant_regex, hls_playlist), key=lambda m: int(m.group('BANDWIDTH')), reverse=True):
            stream_bandwidth = int(match.group('BANDWIDTH')) // 1000
            if max_bandwidth == 0 or stream_bandwidth < max_bandwidth:
                if match.group('URI').startswith('http'):
                    hls_variant_url = match.group('URI')
                else:
                    hls_variant_url = hls_base_url + match.group('URI')
                hls_audio_id = match.group('AUDIO')
                hls_subtitle_id = match.group('SUBTITLES')
                break

        if stream_bandwidth > max_bandwidth and not hls_variant_url:
            message = localize(30057, max=max_bandwidth, min=stream_bandwidth)
            ok_dialog(message=message)
            open_settings()

        # Get audio url
        if hls_audio_id:
            audio_regex = re.compile(r'#EXT-X-MEDIA:TYPE=AUDIO[\w\-=,\.\"\/]+?GROUP-ID=\"' + hls_audio_id + ''
                                     r'\"[\w\-=,\.\"\/]+?URI=\"(?P<AUDIO_URI>[\w\-=]+)\.m3u8\"')
            match_audio = re.search(audio_regex, hls_playlist)
            if match_audio:
                hls_variant_url = hls_base_url + match_audio.group('AUDIO_URI') + '-' + hls_variant_url.split('-')[-1]

        # Get subtitle url, works only for on demand streams
        if get_setting_bool('showsubtitles', default=True) and '/live/' not in master_hls_url and hls_subtitle_id:
            subtitle_regex = re.compile(r'#EXT-X-MEDIA:TYPE=SUBTITLES[\w\-=,\.\"\/]+?GROUP-ID=\"' + hls_subtitle_id + ''
                                        r'\"[\w\-=,\.\"\/]+URI=\"(?P<SUBTITLE_URI>[\w\-=]+)\.m3u8\"')
            match_subtitle = re.search(subtitle_regex, hls_playlist)
            if match_subtitle:
                subtitle_url = hls_base_url + match_subtitle.group('SUBTITLE_URI') + '.webvtt'

        return StreamURLS(hls_variant_url, subtitle_url)
예제 #9
0
 def play_upnext(self, video_id):
     """Play the next episode of a program by video_id"""
     video = self._apihelper.get_single_episode(video_id=video_id)
     if not video:
         log_error('Play Up Next with video_id {video_id} failed', video_id=video_id)
         ok_dialog(message=localize(30954))
         end_of_directory()
         return
     self.play(video)
예제 #10
0
def update_repos():
    """Force an update of the repositories"""
    if get_global_setting(
            'general.addonupdates') == 0:  # Automatic updates is enabled
        execute_builtin('UpdateAddonRepos')
        ok_dialog(heading=localize(30450),
                  message=localize(30451))  # Repositories are being updated
    else:
        ok_dialog(heading=localize(30452),
                  message=localize(30453))  # Automatic updates is disabled
        show_settings_addons()
 def _get_fresh_token(self, refresh_token, name):
     """Refresh an expired X-VRT-Token, vrtlogin-at or vrtlogin-rt token"""
     refresh_url = self._TOKEN_GATEWAY_URL + '/refreshtoken?legacy=true'
     cookie_value = 'vrtlogin-rt=' + refresh_token
     headers = {'Cookie': cookie_value}
     cookiejar = cookielib.CookieJar()
     try:
         open_url(refresh_url, headers=headers, cookiejar=cookiejar, raise_errors=[401])
     except HTTPError:
         ok_dialog(heading=localize(30970), message=localize(30971))
     return TokenResolver._create_token_dictionary(cookiejar, name)
예제 #12
0
 def play_episode_by_air_date(self, channel, start_date, end_date):
     """Play an episode of a program given the channel and the air date in iso format (2019-07-06T19:35:00)"""
     video = self._apihelper.get_episode_by_air_date(channel, start_date, end_date)
     if video and video.get('errorlabel'):
         ok_dialog(message=localize(30986, title=video.get('errorlabel')))
         end_of_directory()
         return
     if not video:
         log_error('Play episode by air date failed, channel {channel}, start_date {start}', channel=channel, start=start_date)
         ok_dialog(message=localize(30954))
         end_of_directory()
         return
     self.play(video)
    def _version_check(self):
        first_run, settings_version, addon_version = self._first_run()
        if first_run:
            # 2.0.0 version: changed plugin:// url interface: show warning that Kodi favourites and what-was-watched will break
            if settings_version == '' and has_credentials():
                ok_dialog(localize(30978), localize(30979))

            if addon_version == '2.2.1':
                # 2.2.1 version: changed artwork: delete old cached artwork
                delete_cached_thumbnail(
                    get_addon_info('fanart').replace('.png', '.jpg'))
                delete_cached_thumbnail(get_addon_info('icon'))
                # 2.2.1 version: moved tokens: delete old tokens
                from tokenresolver import TokenResolver
                TokenResolver().delete_tokens()
예제 #14
0
    def _get_usertoken(self, name=None, login_json=None, roaming=False):
        """Get a user X-VRT-Token, vrtlogin-at, vrtlogin-expiry, vrtlogin-rt, SESSION, OIDCXSRF or state token"""
        if not login_json:
            login_json = self._get_login_json()
        cookiejar = cookielib.CookieJar()
        open_url(self._USER_TOKEN_GATEWAY_URL, cookiejar=cookiejar)
        xsrf = next(
            (cookie for cookie in cookiejar if cookie.name == 'OIDCXSRF'),
            None)
        if xsrf is None:
            return None
        payload = dict(UID=login_json.get('UID'),
                       UIDSignature=login_json.get('UIDSignature'),
                       signatureTimestamp=login_json.get('signatureTimestamp'),
                       client_id='vrtnu-site',
                       _csrf=xsrf.value)
        data = urlencode(payload).encode()
        response = open_url(self._VRT_LOGIN_URL,
                            data=data,
                            cookiejar=cookiejar)
        if response is None:
            return None

        destination = response.geturl()
        usertoken = TokenResolver._create_token_dictionary(cookiejar, name)
        if not usertoken and not destination.startswith(
                'https://www.vrt.be/vrtnu'):
            if roaming is False:
                ok_dialog(heading=localize(30970), message=localize(30972))
            return None

        # Cache additional tokens for later use
        refreshtoken = TokenResolver._create_token_dictionary(
            cookiejar, cookie_name='vrtlogin-rt')
        accesstoken = TokenResolver._create_token_dictionary(
            cookiejar, cookie_name='vrtlogin-at')
        if refreshtoken is not None:
            from json import dumps
            cache_file = self._get_token_filename('vrtlogin-rt')
            update_cache(cache_file, dumps(refreshtoken),
                         self._TOKEN_CACHE_DIR)
        if accesstoken is not None:
            from json import dumps
            cache_file = self._get_token_filename('vrtlogin-at')
            update_cache(cache_file, dumps(accesstoken), self._TOKEN_CACHE_DIR)
        return usertoken
예제 #15
0
    def _version_check(self):
        first_run, settings_version, addon_version = self._first_run()
        if first_run:
            # 2.0.0 version: changed plugin:// url interface: show warning that Kodi favourites and what-was-watched will break
            if settings_version == '' and has_credentials():
                ok_dialog(localize(30978), localize(30979))

            if addon_version == '2.2.1':
                # 2.2.1 version: changed artwork: delete old cached artwork
                delete_cached_thumbnail(get_addon_info('fanart').replace('.png', '.jpg'))
                delete_cached_thumbnail(get_addon_info('icon'))
                # 2.2.1 version: moved tokens: delete old tokens
                from tokenresolver import TokenResolver
                TokenResolver().delete_tokens()

            # Make user aware that timeshift functionality will not work without ISA when user starts up the first time
            if settings_version == '' and kodi_version_major() > 17 and not has_inputstream_adaptive():
                ok_dialog(message=localize(30988))
예제 #16
0
    def search(self, keywords=None, page=None):
        ''' The VRT NU add-on Search functionality and results '''
        if keywords is None:
            keywords = get_search_string()

        if not keywords:
            end_of_directory()
            return

        from statichelper import realpage
        page = realpage(page)

        self.add(keywords)

        from apihelper import ApiHelper
        search_items, sort, ascending, content = ApiHelper(
            self._favorites, self._resumepoints).list_search(keywords,
                                                             page=page)
        if not search_items:
            ok_dialog(heading=localize(30135),
                      message=localize(30136, keywords=keywords))
            end_of_directory()
            return

        # Add 'More...' entry at the end
        from helperobjects import TitleItem
        if len(search_items) == 50:
            search_items.append(
                TitleItem(
                    title=localize(30300),
                    path=url_for('search_query',
                                 keywords=keywords,
                                 page=page + 1),
                    art_dict=dict(thumb='DefaultAddonSearch.png'),
                    info_dict=dict(),
                ))

        self._favorites.refresh(ttl=60 * 60)
        show_listing(search_items,
                     category=30032,
                     sort=sort,
                     ascending=ascending,
                     content=content,
                     cache=False)
 def _handle_bad_stream_error(protocol, code=None, reason=None):
     """Show a localized error message in Kodi GUI for a failing VRT NU stream based on protocol: hls, hls_aes, mpeg_dash)
         message: VRT NU stream <stream_type> problem, try again with (InputStream Adaptive) (and) (DRM) enabled/disabled:
             30959=and DRM, 30960=disabled, 30961=enabled
    """
     # HLS AES DRM failed
     if protocol == 'hls_aes' and not supports_drm():
         message = localize(30962, protocol=protocol.upper(), version=kodi_version_major())
     elif protocol == 'hls_aes' and not has_inputstream_adaptive() and not get_setting_bool('usedrm', default=True):
         message = localize(30958, protocol=protocol.upper(), component=localize(30959), state=localize(30961))
     elif protocol == 'hls_aes' and has_inputstream_adaptive():
         message = localize(30958, protocol=protocol.upper(), component='Widevine DRM', state=localize(30961))
     elif protocol == 'hls_aes' and get_setting_bool('usedrm', default=True):
         message = localize(30958, protocol=protocol.upper(), component='InputStream Adaptive', state=localize(30961))
     else:
         message = localize(30958, protocol=protocol.upper(), component='InputStream Adaptive', state=localize(30960))
     heading = 'HTTP Error {code}: {reason}'.format(code=code, reason=reason) if code and reason else None
     log_error('Unable to play stream. {error}', error=heading)
     ok_dialog(heading=heading, message=message)
     end_of_directory()
예제 #18
0
def build_menu(items_url):
    from xbmcplugin import addDirectoryItem, endOfDirectory, setContent
    setContent(plugin.handle, 'videos')
    list_items = []

    try:
        content = redbull.get_content(items_url)
    except IOError:
        ok_dialog(localize(30220),
                  localize(30221))  # Error getting data from Redbull server
        return

    if content.get('links'):
        for link in content.get('links'):
            list_items.append(generate_list_item(link, PRODUCT))

    if content.get('collections'):
        collections = content.get('collections')
        if collections[0].get(
                'collection_type') == 'top_results':  # Handle search results
            content['items'] = collections[0].get('items')
        else:
            for collection in collections:
                list_items.append(generate_list_item(collection, COLLECTION))

    if content.get('items'):
        for item in content.get('items'):
            list_items.append(generate_list_item(item, PRODUCT))

    if not list_items:
        ok_dialog(localize(30222), localize(30223))  # No results found
        return

    for list_item in list_items:
        addDirectoryItem(handle=plugin.handle,
                         url=list_item.getPath(),
                         listitem=list_item,
                         isFolder=('/play/' not in list_item.getPath()))

    endOfDirectory(plugin.handle)
예제 #19
0
    def search(self, keywords=None, page=0, edit=False):
        """The VRT NU add-on Search functionality and results"""
        if keywords is None or edit is True:
            keywords = get_search_string(keywords)

        if not keywords:
            end_of_directory()
            return
        if edit is True:
            container_update(url_for('search_query', keywords=keywords))
            return

        from apihelper import ApiHelper
        from utils import realpage
        page = realpage(page)

        self.add(keywords)

        search_items, sort, ascending, content = ApiHelper(self._favorites, self._resumepoints).list_search(keywords, page=page)
        if not search_items:
            ok_dialog(heading=localize(30135), message=localize(30136, keywords=keywords))
            end_of_directory()
            return

        # Add 'More…' entry at the end
        from helperobjects import TitleItem
        if len(search_items) == get_setting_int('itemsperpage', default=50):
            search_items.append(TitleItem(
                label=colour(localize(30300)),  # More…
                path=url_for('search_query', keywords=keywords, page=page + 1),
                art_dict=dict(thumb='DefaultAddonSearch.png'),
                info_dict={},
            ))

        self._favorites.refresh(ttl=ttl('indirect'))
        show_listing(search_items, category=30032, sort=sort, ascending=ascending, content=content, cache=False)
예제 #20
0
    def get_episodes(self, program=None, season=None, episodes=None, category=None, feature=None, programtype=None, keywords=None,
                     whatson_id=None, video_id=None, video_url=None, page=None, use_favorites=False, variety=None, cache_file=None):
        ''' Get episodes or season data from VRT NU Search API '''

        # Contruct params
        if page:
            page = statichelper.realpage(page)
            all_items = False
            params = {
                'from': ((page - 1) * 50) + 1,
                'i': 'video',
                'size': 50,
            }
        elif variety == 'single':
            all_items = False
            params = {
                'i': 'video',
                'size': '1',
            }
        else:
            all_items = True
            params = {
                'i': 'video',
                'size': '300',
            }

        if variety:
            season = 'allseasons'

            if variety == 'offline':
                from datetime import datetime
                import dateutil.tz
                params['facets[assetOffTime]'] = datetime.now(dateutil.tz.gettz('Europe/Brussels')).strftime('%Y-%m-%d')

            if variety == 'oneoff':
                params['facets[programType]'] = 'oneoff'

            if variety == 'watchlater':
                self._resumepoints.refresh(ttl=5 * 60)
                episode_urls = self._resumepoints.watchlater_urls()
                params['facets[url]'] = '[%s]' % (','.join(episode_urls))

            if variety == 'continue':
                self._resumepoints.refresh(ttl=5 * 60)
                episode_urls = self._resumepoints.resumepoints_urls()
                params['facets[url]'] = '[%s]' % (','.join(episode_urls))

            if use_favorites:
                program_urls = [statichelper.program_to_url(p, 'medium') for p in self._favorites.programs()]
                params['facets[programUrl]'] = '[%s]' % (','.join(program_urls))
            elif variety in ('offline', 'recent'):
                channel_filter = [channel.get('name') for channel in CHANNELS if get_setting(channel.get('name'), 'true') == 'true']
                params['facets[programBrands]'] = '[%s]' % (','.join(channel_filter))

        if program:
            params['facets[programUrl]'] = statichelper.program_to_url(program, 'medium')

        if season and season != 'allseasons':
            params['facets[seasonTitle]'] = season

        if episodes:
            params['facets[episodeNumber]'] = '[%s]' % (','.join(str(episode) for episode in episodes))

        if category:
            params['facets[categories]'] = category

        if feature:
            params['facets[programTags.title]'] = feature

        if programtype:
            params['facets[programType]'] = programtype

        if keywords:
            if not season:
                season = 'allseasons'
            params['q'] = quote_plus(statichelper.from_unicode(keywords))
            params['highlight'] = 'true'

        if whatson_id:
            params['facets[whatsonId]'] = whatson_id

        if video_id:
            params['facets[videoId]'] = video_id

        if video_url:
            params['facets[url]'] = video_url

        # Construct VRT NU Search API Url and get api data
        querystring = '&'.join('{}={}'.format(key, value) for key, value in list(params.items()))
        search_url = self._VRTNU_SEARCH_URL + '?' + querystring.replace(' ', '%20')  # Only encode spaces to minimize url length

        from json import load
        if cache_file:
            # Get api data from cache if it is fresh
            search_json = get_cache(cache_file, ttl=60 * 60)
            if not search_json:
                log(2, 'URL get: {url}', url=unquote(search_url))
                req = Request(search_url)
                try:
                    search_json = load(urlopen(req))
                except (TypeError, ValueError):  # No JSON object could be decoded
                    return []
                except HTTPError as exc:
                    url_length = len(req.get_selector())
                    if exc.code == 413 and url_length > 8192:
                        ok_dialog(heading='HTTP Error 413', message=localize(30967))
                        log_error('HTTP Error 413: Exceeded maximum url length: '
                                  'VRT Search API url has a length of {length} characters.', length=url_length)
                        return []
                    if exc.code == 400 and 7600 <= url_length <= 8192:
                        ok_dialog(heading='HTTP Error 400', message=localize(30967))
                        log_error('HTTP Error 400: Probably exceeded maximum url length: '
                                  'VRT Search API url has a length of {length} characters.', length=url_length)
                        return []
                    raise
                update_cache(cache_file, search_json)
        else:
            log(2, 'URL get: {url}', url=unquote(search_url))
            search_json = load(urlopen(search_url))

        # Check for multiple seasons
        seasons = None
        if 'facets[seasonTitle]' not in unquote(search_url):
            facets = search_json.get('facets', dict()).get('facets')
            seasons = next((f.get('buckets', []) for f in facets if f.get('name') == 'seasons' and len(f.get('buckets', [])) > 1), None)

        episodes = search_json.get('results', [{}])
        show_seasons = bool(season != 'allseasons')

        # Return seasons
        if show_seasons and seasons:
            return (seasons, episodes)

        api_pages = search_json.get('meta').get('pages').get('total')
        api_page_size = search_json.get('meta').get('pages').get('size')
        total_results = search_json.get('meta').get('total_results')

        if all_items and total_results > api_page_size:
            for api_page in range(1, api_pages):
                api_page_url = search_url + '&from=' + str(api_page * api_page_size + 1)
                api_page_json = load(urlopen(api_page_url))
                episodes += api_page_json.get('results', [{}])

        # Return episodes
        return episodes
예제 #21
0
 def _handle_stream_api_error(message, video_json=None):
     ''' Show localized stream api error messages in Kodi GUI '''
     if video_json:
         log_error(video_json.get('message'))
     ok_dialog(message=message)
     end_of_directory()
예제 #22
0
def notify(msg):
    ok_dialog(msg)