Example #1
0
    def onNotification(self, sender, method, data):  # pylint: disable=invalid-name
        ''' Handler for notifications '''
        log(2,
            '[Notification] sender={sender}, method={method}, data={data}',
            sender=sender,
            method=method,
            data=to_unicode(data))
        if method.endswith('source_container'):
            from json import loads
            self._container = loads(data).get('container')
            return

        if not sender.startswith('upnextprovider'):
            return
        if not method.endswith('plugin.video.vrt.nu_play_action'):
            return

        from json import loads
        hexdata = loads(data)

        if not hexdata:
            return

        from binascii import unhexlify
        data = loads(unhexlify(hexdata[0]))
        log(2,
            '[Up Next notification] sender={sender}, method={method}, data={data}',
            sender=sender,
            method=method,
            data=to_unicode(data))
        jsonrpc(method='Player.Open',
                params=dict(item=dict(
                    file='plugin://plugin.video.vrt.nu/play/whatson/%s' %
                    data.get('whatson_id'))))
 def onPlayBackEnded(self):  # pylint: disable=invalid-name
     """Called when Kodi has ended playing a file"""
     if not self.listen:
         return
     self.last_pos = self.total
     self.quit.set()
     log(3, '[PlayerInfo {id}] Event onPlayBackEnded', id=self.thread_id)
Example #3
0
 def refresh(self, ttl=None):
     ''' Get a cached copy or a newer resumepoints from VRT, or fall back to a cached file '''
     if not self.is_activated():
         return
     resumepoints_json = get_cache('resume_points.json', ttl)
     if not resumepoints_json:
         from tokenresolver import TokenResolver
         xvrttoken = TokenResolver().get_xvrttoken(token_variant='user')
         if xvrttoken:
             headers = {
                 'authorization': 'Bearer ' + xvrttoken,
                 'content-type': 'application/json',
                 'Referer': 'https://www.vrt.be/vrtnu',
             }
             req = Request('https://video-user-data.vrt.be/resume_points',
                           headers=headers)
             log(2,
                 'URL post: https://video-user-data.vrt.be/resume_points')
             from json import load
             try:
                 resumepoints_json = load(urlopen(req))
             except (TypeError,
                     ValueError):  # No JSON object could be decoded
                 # Force resumepoints from cache
                 resumepoints_json = get_cache('resume_points.json',
                                               ttl=None)
             else:
                 update_cache('resume_points.json', resumepoints_json)
     if resumepoints_json:
         self._resumepoints = resumepoints_json
Example #4
0
def get_own_pictures(path):
    _, files = xbmcvfs.listdir(xbmc.translatePath(path))
    images_dict = {}
    image_file = os.path.join(xbmc.translatePath(path), "images.json")
    if xbmcvfs.exists(image_file):
        f = xbmcvfs.File(image_file)
        try:
            images_dict = json.loads(f.read())
        except ValueError:
            kodiutils.log(kodiutils.get_string(32010), xbmc.LOGERROR)
        f.close()
    for _file in files:
        if _file.endswith(('.png', '.jpg', '.jpeg')):
            returned_dict = {
                "url": os.path.join(xbmc.translatePath(path), _file),
                "private": True
            }
            if images_dict:
                for image in images_dict:
                    if "image" in image.keys() and image["image"] == _file:
                        if "line1" in image.keys():
                            returned_dict["line1"] = image["line1"]
                        if "line2" in image.keys():
                            returned_dict["line2"] = image["line2"]
            yield returned_dict
Example #5
0
    def _get_new_xvrttoken(self, login_json, token_variant=None):
        """Get new X-VRT-Token from VRT NU website"""

        if token_variant == 'roaming':
            xvrttoken = self._get_roaming_xvrttoken()
        else:
            login_token = login_json.get('sessionInfo', {}).get('login_token')
            if not login_token:
                return None

            from json import dumps
            login_cookie = 'glt_{api_key}={token}'.format(api_key=self._API_KEY, token=login_token)
            payload = dict(
                uid=login_json.get('UID'),
                uidsig=login_json.get('UIDSignature'),
                ts=login_json.get('signatureTimestamp'),
                email=from_unicode(get_setting('username')),
            )
            data = dumps(payload).encode()
            headers = {'Content-Type': 'application/json', 'Cookie': login_cookie}
            log(2, 'URL post: {url}', url=unquote(self._TOKEN_GATEWAY_URL))
            req = Request(self._TOKEN_GATEWAY_URL, data=data, headers=headers)
            try:  # Python 3
                setcookie_header = urlopen(req).info().get('Set-Cookie')
            except AttributeError:  # Python 2
                setcookie_header = urlopen(req).info().getheader('Set-Cookie')
            xvrttoken = TokenResolver._create_token_dictionary(setcookie_header)

        if xvrttoken is None:
            return None
        self._set_cached_token(xvrttoken, token_variant)
        notification(message=localize(30952))  # Login succeeded.
        return xvrttoken.get('X-VRT-Token')
Example #6
0
    def update_watchlater(self, episode_id, title, watch_later=None):
        """Set program watchLater status and update local copy"""

        self.refresh_watchlater(ttl=5)

        # Update
        log(3,
            "[watchLater] Update {episode_id} watchLater status",
            episode_id=episode_id)

        # watchLater status is not changed, nothing to do
        if watch_later is not None and watch_later is self.is_watchlater(
                episode_id):
            return True

        # Update local watch_later cache
        if watch_later is True:
            self._watchlater[episode_id] = dict(title=title)
        else:
            del self._watchlater[episode_id]

        # Update cache
        from json import dumps
        update_cache(self.WATCHLATER_CACHE_FILE, dumps(self._watchlater))
        invalidate_caches('watchlater-*.json')

        # Update online
        self.set_watchlater_graphql(episode_id, title, watch_later)

        return True
Example #7
0
 def onPlayBackResumed(self):  # pylint: disable=invalid-name
     '''called when user resumes a paused file or a next playlist item is started '''
     suffix = 'after pausing' if self._paused else 'after playlist change'
     log(2, '[PlayerInfo] %d onPlayBackResumed %s' % (self._id, suffix))
     if not self._paused:
         self._info(dict(path=self._path, position=self._last_pos, total=self._total, event='playbackresumed'))
     self._paused = False
Example #8
0
    def playing_now(self, channel):
        ''' Return the EPG information for what is playing now '''
        now = datetime.now(dateutil.tz.tzlocal())
        epg = now
        # Daily EPG information shows information from 6AM until 6AM
        if epg.hour < 6:
            epg += timedelta(days=-1)
        # Try the cache if it is fresh
        schedule = get_cache('schedule.today.json', ttl=60 * 60)
        if not schedule:
            from json import load
            epg_url = epg.strftime(self.VRT_TVGUIDE)
            log(2, 'URL get: {url}', url=epg_url)
            schedule = load(urlopen(epg_url))
            update_cache('schedule.today.json', schedule)

        entry = find_entry(CHANNELS, 'name', channel)
        if not entry:
            return ''

        episodes = iter(schedule.get(entry.get('id'), []))

        while True:
            try:
                episode = next(episodes)
            except StopIteration:
                break
            start_date = dateutil.parser.parse(episode.get('startTime'))
            end_date = dateutil.parser.parse(episode.get('endTime'))
            if start_date <= now <= end_date:  # Now playing
                return episode.get('title')
        return ''
Example #9
0
    def _get_cached_token(self, token_name, token_variant=None):
        """Return a cached token"""
        path = self._get_token_path(token_name, token_variant)

        if not exists(path):
            return None

        with open_file(path) as fdesc:
            token = get_json_data(fdesc)

        if token is None:
            return None

        from datetime import datetime
        import dateutil.parser
        import dateutil.tz
        now = datetime.now(dateutil.tz.tzlocal())
        exp = dateutil.parser.parse(token.get('expirationDate'))
        if exp <= now:
            log(2, "Token expired, cached token '{path}' deleted", path=path)
            delete(path)
            return None

        log(3, "Got cached token '{path}'", path=path)
        return token.get(token_name)
Example #10
0
 def stream_position(self):
     ''' get latest stream position while playing '''
     while self.isPlaying() and not self._stop.is_set():
         self._last_pos = self.getTime()
         if self._stop.wait(timeout=0.5):
             break
     log(2, '[PlayerInfo] %d stream position loop exited' % self._id)
    def get_tvshows(self, category=None, channel=None, feature=None):
        ''' Get all TV shows for a given category, channel or feature, optionally filtered by favorites '''
        params = dict()

        if category:
            params['facets[categories]'] = category
            cache_file = 'category.%s.json' % category

        if channel:
            params['facets[programBrands]'] = channel
            cache_file = 'channel.%s.json' % channel

        if feature:
            params['facets[programTags.title]'] = feature
            cache_file = 'featured.%s.json' % feature

        # If no facet-selection is done, we return the 'All programs' listing
        if not category and not channel and not feature:
            params['facets[transcodingStatus]'] = 'AVAILABLE'  # Required for getting results in Suggests API
            cache_file = 'programs.json'
        tvshows = get_cache(cache_file, ttl=60 * 60)  # Try the cache if it is fresh
        if not tvshows:
            from json import load
            querystring = '&'.join('{}={}'.format(key, value) for key, value in list(params.items()))
            suggest_url = self._VRTNU_SUGGEST_URL + '?' + querystring
            log(2, 'URL get: {url}', url=unquote(suggest_url))
            tvshows = load(urlopen(suggest_url))
            update_cache(cache_file, tvshows)

        return tvshows
Example #12
0
    def _get_new_user_xvrttoken(self):
        """Get new 'user' X-VRT-Token from VRT NU website"""
        # Get login json
        login_json = self._get_login_json()

        if login_json.get('errorCode') != 0:
            return None

        payload = dict(
            UID=login_json.get('UID'),
            UIDSignature=login_json.get('UIDSignature'),
            signatureTimestamp=login_json.get('signatureTimestamp'),
            client_id='vrtnu-site',
            submit='submit',
        )
        data = urlencode(payload).encode()
        cookiejar = cookielib.CookieJar()
        opener = build_opener(HTTPCookieProcessor(cookiejar), ProxyHandler(self._proxies))
        log(2, 'URL get: {url}', url=unquote(self._USER_TOKEN_GATEWAY_URL))
        opener.open(self._USER_TOKEN_GATEWAY_URL)
        log(2, 'URL post: {url}', url=unquote(self._VRT_LOGIN_URL))
        opener.open(self._VRT_LOGIN_URL, data=data)
        xvrttoken = TokenResolver._create_token_dictionary(cookiejar)
        refreshtoken = TokenResolver._create_token_dictionary(cookiejar, cookie_name='vrtlogin-rt')
        if xvrttoken is None:
            return None

        self._set_cached_token(xvrttoken, token_variant='user')
        if refreshtoken is not None:
            self._set_cached_token(refreshtoken)
        return xvrttoken.get('X-VRT-Token')
    def __init__(self):
        """PlayerInfo initialisation"""
        self.resumepoints = ResumePoints()
        self.apihelper = ApiHelper(Favorites(), self.resumepoints)
        self.last_pos = None
        self.listen = False
        self.paused = False
        self.total = 100
        self.positionthread = None
        self.quit = Event()

        self.asset_str = None
        # FIXME On Kodi 17, use ListItem.Filenameandpath because Player.FilenameAndPath returns the stream manifest url and
        # this definitely breaks "Up Next" on Kodi 17, but this is not supported or available through the Kodi add-on repo anyway
        self.path_infolabel = 'ListItem.Filenameandpath' if kodi_version_major(
        ) < 18 else 'Player.FilenameAndPath'
        self.path = None
        self.title = None
        self.ep_id = None
        self.episode_id = None
        self.episode_title = None
        self.video_id = None
        from random import randint
        self.thread_id = randint(1, 10001)
        log(3, '[PlayerInfo {id}] Initialized', id=self.thread_id)
        super(PlayerInfo, self).__init__()
 def onPlayBackPaused(self):  # pylint: disable=invalid-name
     """Called when user pauses a playing file"""
     if not self.listen:
         return
     log(3, '[PlayerInfo {id}] Event onPlayBackPaused', id=self.thread_id)
     self.update_position()
     self.push_position(position=self.last_pos, total=self.total)
     self.paused = True
    def onPlayerExit(self):  # pylint: disable=invalid-name
        """Called when player exits"""
        log(3, '[PlayerInfo {id}] Event onPlayerExit', id=self.thread_id)
        self.positionthread = None
        self.push_position(position=self.last_pos, total=self.total)

        # Set property to let wait_for_resumepoints function know that update resume is done
        set_property('vrtnu_resumepoints', 'ready')
    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]
        log(2, 'URL get: {url}', url=unquote(master_hls_url))
        try:
            hls_playlist = to_unicode(urlopen(master_hls_url).read())
        except HTTPError as exc:
            if exc.code == 415:
                self._handle_bad_stream_error(protocol, exc.code, exc.reason)
                return None
            raise
        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)
Example #17
0
 def _get_new_playertoken(self, token_url, headers, token_variant=None):
     ''' Get new playertoken from VRT Token API '''
     from json import load
     log(2, 'URL post: {url}', url=unquote(token_url))
     req = Request(token_url, data=b'', headers=headers)
     playertoken = load(urlopen(req))
     if playertoken is not None:
         self._set_cached_token(playertoken, token_variant)
     return playertoken.get('vrtPlayerToken')
 def delete_online(self, asset_id):
     """Delete resumepoint online"""
     try:
         result = open_url('https://video-user-data.vrt.be/resume_points/{asset_id}'.format(asset_id=asset_id),
                           headers=self.resumepoint_headers(), method='DELETE', raise_errors='all')
         log(3, "[Resumepoints] '{asset_id}' online deleted: {code}", asset_id=asset_id, code=result.getcode())
     except HTTPError as exc:
         log_error("Failed to remove '{asset_id}' from resumepoints: {error}", asset_id=asset_id, error=exc)
         return False
     return True
Example #19
0
    def refresh_login(self):
        """Refresh login if necessary"""

        if self._credentials_changed() and has_credentials():
            log(2, 'Credentials have changed, cleaning up userdata')
            self.cleanup_userdata()

            # Refresh login
            log(2, 'Refresh login')
            self.login(refresh=True)
Example #20
0
def get_upload_playlist():
    api_endpoint = 'https://www.googleapis.com/youtube/v3/channels?part=contentDetails&id=%s&key=%s' % (CHANNEL_ID,YOUTUBE_API_KEY)
    try:
        resp = requests.get(api_endpoint).json()
    except ValueError:
        kodiutils.log(kodiutils.get_string(32004), xbmc.LOGERROR)
        return None
    if "items" in resp.keys():
        uploads_playlist = resp["items"][0]["contentDetails"]["relatedPlaylists"]["uploads"]
        return uploads_playlist
 def onPlayBackResumed(self):  # pylint: disable=invalid-name
     """Called when user resumes a paused file or a next playlist item is started"""
     if not self.listen:
         return
     suffix = 'after pausing' if self.paused else 'after playlist change'
     log(3,
         '[PlayerInfo {id}] Event onPlayBackResumed {suffix}',
         id=self.thread_id,
         suffix=suffix)
     self.paused = False
Example #22
0
 def send(self):
     """Decorator to send over a socket"""
     import json
     import socket
     log(2, "Sending data output to IPTV Manager using port {port}", port=self.port)
     sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
     sock.connect(('127.0.0.1', self.port))
     try:
         sock.sendall(json.dumps(func()).encode())  # pylint: disable=not-callable
     finally:
         sock.close()
Example #23
0
    def get_episode_items(self, date, channel):
        ''' Show episodes for a given date and channel '''
        now = datetime.now(dateutil.tz.tzlocal())
        epg = self.parse(date, now)
        epg_url = epg.strftime(self.VRT_TVGUIDE)

        self._favorites.refresh(ttl=60 * 60)

        cache_file = 'schedule.%s.json' % date
        if date in ('today', 'yesterday', 'tomorrow'):
            # Try the cache if it is fresh
            schedule = get_cache(cache_file, ttl=60 * 60)
            if not schedule:
                from json import load
                log(2, 'URL get: {url}', url=epg_url)
                schedule = load(urlopen(epg_url))
                update_cache(cache_file, schedule)
        else:
            from json import load
            log(2, 'URL get: {url}', url=epg_url)
            schedule = load(urlopen(epg_url))

        entry = find_entry(CHANNELS, 'name', channel)
        if entry:
            episodes = schedule.get(entry.get('id'), [])
        else:
            episodes = []
        episode_items = []
        for episode in episodes:

            label = self._metadata.get_label(episode)

            context_menu = []
            path = None
            if episode.get('url'):
                from statichelper import add_https_method, url_to_program
                video_url = add_https_method(episode.get('url'))
                path = url_for('play_url', video_url=video_url)
                program = url_to_program(episode.get('url'))
                context_menu, favorite_marker, watchlater_marker = self._metadata.get_context_menu(episode, program, cache_file)
                label += favorite_marker + watchlater_marker

            info_labels = self._metadata.get_info_labels(episode, date=date, channel=entry)
            info_labels['title'] = label

            episode_items.append(TitleItem(
                title=label,
                path=path,
                art_dict=self._metadata.get_art(episode),
                info_dict=info_labels,
                is_playable=True,
                context_menu=context_menu,
            ))
        return episode_items
Example #24
0
    def onSettingsChanged(self):  # pylint: disable=invalid-name
        """Handler for changes to settings"""

        log(1, 'Settings changed')
        TokenResolver().refresh_login()

        # Init watching activity again when settings change
        self.init_watching_activity()

        # Refresh container when settings change
        container_refresh()
Example #25
0
    def handle_info(self, info):
        ''' Handle information from PlayerInfo class '''
        log(2, 'Got VRT NU Player info: {info}', info=str(info))

        # Push resume position
        if info.get('position'):
            self.push_position(info)

        # Push up next episode info
        if info.get('program'):
            self.push_upnext(info)
Example #26
0
def get_upload_playlist():
    api_endpoint = 'https://www.googleapis.com/youtube/v3/channels?part=contentDetails&id=%s&key=%s' % (
        CHANNEL_ID, YOUTUBE_API_KEY)
    try:
        resp = requests.get(api_endpoint).json()
    except ValueError:
        kodiutils.log(kodiutils.get_string(32004), xbmc.LOGERROR)
        return None
    if "items" in resp.keys():
        uploads_playlist = resp["items"][0]["contentDetails"][
            "relatedPlaylists"]["uploads"]
        return uploads_playlist
Example #27
0
 def __init__(self, **kwargs):
     ''' PlayerInfo initialisation '''
     self._info = kwargs['info']
     self._path = None
     self._paused = False
     self._last_pos = None
     self._total = None
     self._stop = Event()
     from random import randint
     self._id = randint(1, 10001)
     log(2, '[PlayerInfo] %d initialized' % self._id)
     Player.__init__(self)
def get_live_videos():
    api_endpoint = 'https://www.googleapis.com/youtube/v3/search?eventType=live&part=snippet&channelId=%s&type=video&maxResults=50&key=%s' % (
        CHANNEL_ID, YOUTUBE_API_KEY)
    try:
        resp = requests.get(api_endpoint).json()
    except ValueError:
        kodiutils.log(kodiutils.get_string(32009), xbmc.LOGERROR)
        sys.exit(0)
    if "items" in resp.keys():
        for item in resp["items"]:
            yield {
                "label": item["snippet"]["title"],
                "video_id": item["id"]["videoId"]
            }
 def get_latest_episode(self, program):
     ''' Get the latest episode of a program '''
     api_data = self.get_episodes(program=program, variety='single')
     if len(api_data) != 1:
         return None
     episode = api_data[0]
     log(2, str(episode))
     video_item = TitleItem(
         title=self._metadata.get_label(episode),
         art_dict=self._metadata.get_art(episode),
         info_dict=self._metadata.get_info_labels(episode),
         prop_dict=self._metadata.get_properties(episode),
     )
     video = dict(listitem=video_item, video_id=episode.get('videoId'), publication_id=episode.get('publicationId'))
     return video
Example #30
0
 def _get_fresh_token(self, refresh_token, token_name, token_variant=None):
     """Refresh an expired X-VRT-Token, vrtlogin-at or vrtlogin-rt token"""
     refresh_url = self._TOKEN_GATEWAY_URL + '/refreshtoken'
     cookie_value = 'vrtlogin-rt=' + refresh_token
     headers = {'Cookie': cookie_value}
     cookiejar = cookielib.CookieJar()
     opener = build_opener(HTTPCookieProcessor(cookiejar), ProxyHandler(self._proxies))
     log(2, 'URL get: {url}', url=refresh_url)
     req = Request(refresh_url, headers=headers)
     opener.open(req)
     token = TokenResolver._create_token_dictionary(cookiejar, token_name)
     if token is None:
         return None
     self._set_cached_token(token, token_variant)
     return list(token.values())[0]
Example #31
0
def get_playlists():
    api_endpoint = 'https://www.googleapis.com/youtube/v3/playlists?part=snippet,contentDetails&channelId=%s&maxResults=50&key=%s' % (CHANNEL_ID,YOUTUBE_API_KEY)
    try:
        resp = requests.get(api_endpoint).json()
    except ValueError:
        kodiutils.log(kodiutils.get_string(32003), xbmc.LOGERROR)
    if "items" in resp.keys():
        for playlist in resp["items"]:
            liz = ListItem(playlist["snippet"]["title"])
            infolabels = {"plot": playlist["snippet"]["localized"]["description"]}
            liz.setInfo(type="video", infoLabels=infolabels)
            liz.setArt({"thumb": playlist["snippet"]["thumbnails"]["high"]["url"], "fanart": xbmcaddon.Addon().getAddonInfo("fanart")})
            liz.setProperty("type","playlist")
            liz.setProperty("playlist_id", playlist["id"])
            yield liz
    def onPlayBackSeek(self, time, seekOffset):  # pylint: disable=invalid-name
        """Called when user seeks to a time"""
        if not self.listen:
            return
        log(3,
            '[PlayerInfo {id}] Event onPlayBackSeek time={time} offset={offset}',
            id=self.thread_id,
            time=time,
            offset=seekOffset)
        self.last_pos = time // 1000

        # If we seek beyond the end, exit Player
        if self.last_pos >= self.total:
            self.quit.set()
            self.stop()
Example #33
0
def get_videos(name,playlist_id,token="",page_num=1):
    items_per_page = kodiutils.get_setting_as_int("items_per_page")
    url_api = 'https://www.googleapis.com/youtube/v3/playlistItems?part=id,snippet,contentDetails&maxResults=%s&playlistId=%s&key=%s' \
              % (str(items_per_page), playlist_id, YOUTUBE_API_KEY)
    if page_num != 1:
        url_api += "&pageToken=%s" % (token)

    try:
        resp = requests.get(url_api).json()
    except ValueError:
        kodiutils.log(kodiutils.get_string(32004), xbmc.LOGERROR)
        resp = None

    if resp:
        nextpagetoken = resp["nextPageToken"] if "nextPageToken" in resp.keys() else ""
        availablevideos = resp["pageInfo"]["totalResults"] if "pageInfo" in resp.keys() and "totalResults" in resp["pageInfo"].keys() else 1

        returnedVideos = resp["items"]
        totalpages = int(math.ceil((float(availablevideos) / items_per_page)))
        video_ids = []
        if returnedVideos:
            for video in returnedVideos:
                videoid = video["contentDetails"]["videoId"]
                video_ids.append(videoid)
            video_ids = ','.join(video_ids)
            url_api = 'https://www.googleapis.com/youtube/v3/videos?part=snippet,contentDetails&id=%s&key=%s' % (video_ids,YOUTUBE_API_KEY)
            try:
                resp = requests.get(url_api).json()
            except ValueError:
                kodiutils.log(kodiutils.get_string(32005), xbmc.LOGERROR)
                resp = None

            if resp:
                returnedVideos = resp["items"]

                for video in returnedVideos:
                    title = video["snippet"]["title"]
                    plot = video["snippet"]["description"]
                    aired = video["snippet"]["publishedAt"]
                    thumb = video["snippet"]["thumbnails"]["high"]["url"]
                    videoid = video["id"]
                    # process duration
                    duration_string = video["contentDetails"]["duration"]
                    duration = addonutils.return_duration_as_seconds(duration_string)
                    try:
                        aired = re.compile('(.+?)-(.+?)-(.+?)T').findall(aired)[0]
                        date = aired[2] + '.' + aired[1] + '.' + aired[0]
                        aired = aired[0] + '-' + aired[1] + '-' + aired[2]
                    except IndexError:
                        aired = ''
                        date = ''

                    infolabels = {'plot': plot.encode('utf-8'), 'aired': aired, 'date': date, 'tvshowtitle': TVSHOWTITLE,
                                  'title': title.encode('utf-8'), 'originaltitle': title.encode('utf-8'), 'status': STATUS,
                                  'cast': CAST, 'duration': duration}

                    # Video and audio info
                    video_info = {'codec': 'avc1', 'aspect': 1.78}
                    audio_info = {'codec': 'aac', 'language': 'en'}
                    if video["contentDetails"]["definition"].lower() == 'hd':
                        video_info['width'] = 1280
                        video_info['height'] = 720
                        audio_info['channels'] = 2
                    else:
                        video_info['width'] = 854
                        video_info['height'] = 480
                        audio_info['channels'] = 1
                    if xbmcaddon.Addon(id='plugin.video.youtube').getSetting('kodion.video.quality.ask') == 'false' and xbmcaddon.Addon(
                                    id='plugin.video.youtube').getSetting('kodion.video.quality') != '3' and xbmcaddon.Addon(
                                    id='plugin.video.youtube').getSetting('kodion.video.quality') != '4':
                        video_info['width'] = 854
                        video_info['height'] = 480
                        audio_info['channels'] = 1

                    yield build_video_item(title.encode('utf-8'), thumb, videoid, infolabels, video_info, audio_info)

    if totalpages > 1 and (page_num + 1) <= totalpages:
        nextpage = ListItem("[B]%s[/B] (%s/%s)" % (kodiutils.get_string(32008), str(page_num), str(totalpages)))
        nextpage.setProperty("type", "next")
        nextpage.setProperty("page", str(page_num+1))
        nextpage.setProperty("token", str(nextpagetoken))
        nextpage.setInfo(type="video",infoLabels={"plot": kodiutils.get_string(32002)})
        yield nextpage