def create_decryptor(self, key, sequence): if key.method != "AES-128": raise StreamError("Unable to decrypt cipher {0}", key.method) if not self.key_uri_override and not key.uri: raise StreamError("Missing URI to decryption key") if self.key_uri_override: p = urlparse(key.uri) key_uri = LazyFormatter.format( self.key_uri_override, url=key.uri, scheme=p.scheme, netloc=p.netloc, path=p.path, query=p.query, ) else: key_uri = key.uri if self.key_uri != key_uri: res = self.session.http.get(key_uri, exception=StreamError, retries=self.retries, **self.reader.request_params) res.encoding = "binary/octet-stream" self.key_data = res.content self.key_uri = key_uri iv = key.iv or num_to_iv(sequence) # Pad IV if needed iv = b"\x00" * (16 - len(iv)) + iv return AES.new(self.key_data, AES.MODE_CBC, iv)
def test_format_lazy_title_default(self): plugin = self._get_fake_plugin() plugin.get_title.return_value = None res = LazyFormatter.format("{title}", title=lambda: plugin.get_title() or "default_title") self.assertEqual("default_title", res) plugin.get_title.assert_called() plugin.get_author.assert_not_called() plugin.get_game.assert_not_called()
def test_format_lazy_title_default(self): plugin = self._get_fake_plugin() plugin.get_title.return_value = None res = LazyFormatter.format( "{title}", title=lambda: plugin.get_title() or "default_title") self.assertEqual("default_title", res) plugin.get_title.assert_called() plugin.get_author.assert_not_called() plugin.get_game.assert_not_called()
def create_title(plugin=None): if args.title and plugin: title = LazyFormatter.format( maybe_encode(args.title), title=lambda: plugin.get_title() or DEFAULT_STREAM_METADATA["title"], author=lambda: plugin.get_author() or DEFAULT_STREAM_METADATA["author"], category=lambda: plugin.get_category() or DEFAULT_STREAM_METADATA["category"], game=lambda: plugin.get_category() or DEFAULT_STREAM_METADATA["game"] ) else: title = args.url return title
def test_format_lazy_title_author_game(self): plugin = self._get_fake_plugin() res = LazyFormatter.format("{title} - {author} - {game}", title=plugin.get_title, author=plugin.get_author, game=plugin.get_game) self.assertEqual("title - author - game", res) plugin.get_title.assert_called() plugin.get_author.assert_called() plugin.get_game.assert_called()
def test_format_lazy_title(self): plugin = self._get_fake_plugin() res = LazyFormatter.format("{title}", title=plugin.get_title, author=plugin.get_author, game=plugin.get_game, url=plugin.url) self.assertEqual("title", res) plugin.get_title.assert_called() plugin.get_author.assert_not_called() plugin.get_game.assert_not_called()
def test_format_fmt_prop(self): self.assertEqual("test", LazyFormatter.format("{fmt}", fmt="test"))
def test_format_lazy_title_not_callable(self): res = LazyFormatter.format("{title}", title="title") self.assertEqual("title", res)
def create_request_params(self, sequence): # felix add update headers cookies request_params = dict(self.reader.request_params) headers = request_params.pop("headers", {}) cookies = request_params.pop("cookies", {}) if self.token_uri_override: p = urlparse(self.token_uri_override) key_uri = LazyFormatter.format( self.token_uri_override, url=self.token_uri_override, scheme=p.scheme, netloc=p.netloc, path=p.path, query=p.query, ) try: token = self.session.cache.get(key_uri) if not token: res = self.session.http.get( key_uri, exception=StreamError, retries=self.playlist_reload_retries, **self.reader.request_params) token = self.session.http.json(res) self.session.cache.set( key_uri, token, expires=self.session.options.get('hls-token-period')) log.debug( f"create_request_params save to cache {key_uri} {token}" ) else: log.debug( f"create_request_params load from cache {key_uri} {token}" ) except BaseException as e: log.warning(e) token = {} log.debug(f"create_request_params token {token}") token_headers = token.pop("headers", {}) token_cookies = token.pop("cookies", {}) headers.update(token_headers) cookies.update(token_cookies) if sequence.segment.byterange: bytes_start = self.byterange_offsets[sequence.segment.uri] if sequence.segment.byterange.offset is not None: bytes_start = sequence.segment.byterange.offset bytes_len = max(sequence.segment.byterange.range - 1, 0) bytes_end = bytes_start + bytes_len headers["Range"] = "bytes={0}-{1}".format(bytes_start, bytes_end) self.byterange_offsets[sequence.segment.uri] = bytes_end + 1 request_params["headers"] = headers if cookies: cookiejar = cookiejar_from_dict(cookies) request_params["cookies"] = cookiejar return request_params
def reload_playlist(self): if self.closed: return self.reader.buffer.wait_free() log.debug("Reloading playlist") # felix add update headers cookies ''' add option to self.session.options.options then update self.session.http.headers before access self.stream.url eg: headers.update(session.headers) ''' request_params = dict(self.reader.request_params) headers = request_params.pop("headers", {}) cookies = request_params.pop("cookies", {}) if self.token_uri_override: p = urlparse(self.token_uri_override) key_uri = LazyFormatter.format( self.token_uri_override, url=self.token_uri_override, scheme=p.scheme, netloc=p.netloc, path=p.path, query=p.query, ) try: token = self.session.cache.get(key_uri) if not token: res = self.session.http.get( key_uri, exception=StreamError, retries=self.playlist_reload_retries, **self.reader.request_params) token = self.session.http.json(res) self.session.cache.set( key_uri, token, expires=self.session.options.get('hls-token-period')) log.debug( f"reload_playlist save to cache {key_uri} {token}") else: log.debug( f"reload_playlist load from cache {key_uri} {token}") except BaseException as e: log.warning(e) token = {} log.debug(f"reload_playlist {token}") token_headers = token.pop("headers", {}) token_cookies = token.pop("cookies", {}) headers.update(token_headers) cookies.update(token_cookies) request_params["headers"] = headers if cookies: cookiejar = cookiejar_from_dict(cookies) request_params["cookies"] = cookiejar res = self.session.http.get(self.stream.url, exception=StreamError, retries=self.playlist_reload_retries, **request_params) try: playlist = self._reload_playlist(res.text, res.url) except ValueError as err: raise StreamError(err) if playlist.is_master: raise StreamError("Attempted to play a variant playlist, use " "'hls://{0}' instead".format(self.stream.url)) if playlist.iframes_only: raise StreamError( "Streams containing I-frames only is not playable") media_sequence = playlist.media_sequence or 0 sequences = [ Sequence(media_sequence + i, s) for i, s in enumerate(playlist.segments) ] self.playlist_reload_time = self._playlist_reload_time( playlist, sequences) if sequences: self.process_sequences(playlist, sequences)