Пример #1
0
    def reload_playlist(self):
        if self.closed:
            return

        self.reader.buffer.wait_free()
        log.debug("Reloading playlist")
        res = self.session.http.get(self.stream.url,
                                    exception=StreamError,
                                    retries=self.playlist_reload_retries,
                                    **self.reader.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)
Пример #2
0
    def create_decryptor(self, key: Key, num: int) -> AES:
        if key.method != "AES-128":
            raise StreamError(f"Unable to decrypt cipher {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)
            formatter = Formatter({
                "url": lambda: key.uri,
                "scheme": lambda: p.scheme,
                "netloc": lambda: p.netloc,
                "path": lambda: p.path,
                "query": lambda: p.query,
            })
            key_uri = formatter.format(self.key_uri_override)
        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 self.num_to_iv(num)

        # Pad IV if needed
        iv = b"\x00" * (16 - len(iv)) + iv

        return AES.new(self.key_data, AES.MODE_CBC, iv)
Пример #3
0
def create_decryptor(self, key, sequence):
    if key.method != "AES-128":
        raise StreamError("Unable to decrypt cipher {0}", key.method)

    if not key.uri:
        raise StreamError("Missing URI to decryption key")

    if self.key_uri != key.uri:
        custom_uri = self.reader.stream.session.options.get("custom-uri")

        if custom_uri:
            uri = custom_uri
        else:
            uri = key.uri

        res = self.session.http.get(uri, exception=StreamError,
                                    retries=self.retries,
                                    **self.reader.request_params)

        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

    if _android_ssl:
        return enc(self.key_data, iv)
    elif _oscrypto:
        return AES(self.key_data, iv)
    else:
        return AES.new(self.key_data, AES.MODE_CBC, iv)
Пример #4
0
    def reload_playlist(self):
        if self.closed:  # pragma: no cover
            return

        self.reader.buffer.wait_free()

        log.debug("Reloading playlist")
        res = self._fetch_playlist()

        try:
            playlist = self._reload_playlist(res)
        except ValueError as err:
            raise StreamError(err)

        if playlist.is_master:
            raise StreamError(
                f"Attempted to play a variant playlist, use 'hls://{self.stream.url}' instead"
            )

        if playlist.iframes_only:
            raise StreamError(
                "Streams containing I-frames only are 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)
Пример #5
0
    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)
Пример #6
0
    def _create_video_clip(self, chunks, start_offset, stop_offset):
        playlist_duration = stop_offset - start_offset
        playlist_offset = 0
        playlist_streams = []
        playlist_tags = []

        for chunk in chunks:
            chunk_url = chunk["url"]
            chunk_length = chunk["length"]
            chunk_start = playlist_offset
            chunk_stop = chunk_start + chunk_length
            chunk_stream = HTTPStream(self.session, chunk_url)

            if chunk_start <= start_offset <= chunk_stop:
                try:
                    headers = extract_flv_header_tags(chunk_stream)
                except IOError as err:
                    raise StreamError("Error while parsing FLV: {0}", err)

                if not headers.metadata:
                    raise StreamError("Missing metadata tag in the first chunk")

                metadata = headers.metadata.data.value
                keyframes = metadata.get("keyframes")

                if not keyframes:
                    if chunk["upkeep"] == "fail":
                        raise StreamError("Unable to seek into muted chunk, try another timestamp")
                    else:
                        raise StreamError("Missing keyframes info in the first chunk")

                keyframe_offset = None
                keyframe_offsets = keyframes.get("filepositions")
                keyframe_times = [playlist_offset + t for t in keyframes.get("times")]
                for time, offset in zip(keyframe_times, keyframe_offsets):
                    if time > start_offset:
                        break

                    keyframe_offset = offset

                if keyframe_offset is None:
                    raise StreamError("Unable to find a keyframe to seek to "
                                      "in the first chunk")

                chunk_headers = dict(Range="bytes={0}-".format(int(keyframe_offset)))
                chunk_stream = HTTPStream(self.session, chunk_url,
                                          headers=chunk_headers)
                playlist_streams.append(chunk_stream)
                for tag in headers:
                    playlist_tags.append(tag)
            elif start_offset <= chunk_start < stop_offset:
                playlist_streams.append(chunk_stream)

            playlist_offset += chunk_length

        return FLVPlaylist(self.session, playlist_streams,
                           tags=playlist_tags, duration=playlist_duration)
Пример #7
0
    def _check_cmd(self):
        if not self.cmd:
            raise StreamError("`cmd' attribute not set")

        cmd = which(self.cmd)

        if not cmd:
            raise StreamError("Unable to find `{0}' command".format(self.cmd))

        return cmd
Пример #8
0
    def reload_playlist(self):
        if self.closed:
            return

        self.reader.buffer.wait_free()
        log.debug("Reloading playlist")

        if self.stream.channel:
            parsed = urlparse(self.stream.url)
            if self.stream._first_netloc is None:
                # save the first netloc
                self.stream._first_netloc = parsed.netloc
            # always use the first saved netloc
            new_stream_url = parsed._replace(
                netloc=self.stream._first_netloc).geturl()
        else:
            new_stream_url = self.stream.url

        try:
            res = self.session.http.get(new_stream_url,
                                        exception=StreamError,
                                        retries=self.playlist_reload_retries,
                                        **self.reader.request_params)
        except StreamError as err:
            if (hasattr(self.stream, "watch_timeout") and any(
                    x in str(err)
                    for x in ("403 Client Error", "502 Server Error"))):
                self.stream.watch_timeout = 0
                self.playlist_reload_time = 0
                log.debug(
                    f"Force reloading the channel playlist on error: {err}")
                return
            raise err

        try:
            playlist = hls_playlist.load(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)
        ]

        if sequences:
            self.process_sequences(playlist, sequences)
Пример #9
0
    def open(self):
        if self.is_usable(self.session):
            process = self.spawn(self.parameters, self.arguments)

            # Wait 0.5 seconds to see if program exited prematurely
            time.sleep(0.5)

            if not process.poll() is None:
                if hasattr(self.stderr, "name"):
                    raise StreamError(("Error while executing subprocess, "
                                       "error output logged to: {0}").format(self.stderr.name))
                else:
                    raise StreamError("Error while executing subprocess")

            return StreamProcessIO(self.session, process, process.stdout, timeout=self.timeout)
        else:
            raise StreamError("{0} is not installed or not supported on your system".format(os.path.basename(self.cmd)))
Пример #10
0
    def spawn(self,
              parameters=None,
              arguments=None,
              stderr=None,
              timeout=None,
              short_option_prefix="-",
              long_option_prefix="--"):
        """
        Spawn the process defined in `cmd`

        parameters is converted to options the short and long option prefixes
        if a list is given as the value, the parameter is repeated with each
        value

        If timeout is set the spawn will block until the process returns or
        the timeout expires.

        :param parameters: optional parameters
        :param arguments: positional arguments
        :param stderr: where to redirect stderr to
        :param timeout: timeout for short lived process
        :param long_option_prefix: option prefix, default -
        :param short_option_prefix: long option prefix, default --
        :return: spawned process
        """
        stderr = stderr or self.stderr
        cmd = self.bake(self._check_cmd(), parameters, arguments,
                        short_option_prefix, long_option_prefix)
        self.logger.debug("Spawning command: {0}",
                          subprocess.list2cmdline(cmd))

        try:
            process = subprocess.Popen(cmd,
                                       stderr=stderr,
                                       stdout=subprocess.PIPE)
        except (OSError, IOError) as err:
            raise StreamError("Failed to start process: {0} ({1})".format(
                self._check_cmd(), str(err)))

        if timeout:
            elapsed = 0
            while elapsed < timeout and not process.poll():
                time.sleep(0.25)
                elapsed += 0.25

            # kill after the timeout has expired and the process still hasn't ended
            if not process.poll():
                try:
                    self.logger.debug(
                        "Process timeout expired ({0}s), killing process".
                        format(timeout))
                    process.kill()
                except Exception:
                    pass

            process.wait()

        return process
Пример #11
0
    def open(self):
        if not CAN_DECRYPT:
            raise StreamError(
                "pyCrypto needs to be installed to decrypt this stream")

        reader = BeatStreamReader(self)
        reader.open()

        return reader
Пример #12
0
    def open(self):
        process = self.spawn(self.parameters, self.arguments)

        # Wait 0.5 seconds to see if program exited prematurely
        time.sleep(0.5)

        if not process.poll() is None:
            if hasattr(self.stderr, "name"):
                raise StreamError(
                    ("Error while executing subprocess, "
                     "error output logged to: {0}").format(self.stderr.name))
            else:
                raise StreamError("Error while executing subprocess")

        return StreamProcessIO(self.session,
                               process,
                               process.stdout,
                               timeout=self.timeout)
Пример #13
0
def pkcs7_decode(paddedData, keySize=16):
    '''
    Remove the PKCS#7 padding
    '''
    # Use ord + [-1:] to support both python 2 and 3
    val = ord(paddedData[-1:])
    if val > keySize:
        raise StreamError("Input is not padded or padding is corrupt, got padding size of {0}".format(val))

    return paddedData[:-val]
Пример #14
0
    def open(self):
        if self.session.options.get("rtmp-proxy"):
            if not self._supports_param("socks"):
                raise StreamError("Installed rtmpdump does not support --socks argument")

            self.parameters["socks"] = self.session.options.get("rtmp-proxy")

        if "jtv" in self.parameters and not self._supports_param("jtv"):
            raise StreamError("Installed rtmpdump does not support --jtv argument")

        if "weeb" in self.parameters and not self._supports_param("weeb"):
            raise StreamError("Installed rtmpdump does not support --weeb argument")

        if self.redirect:
            self._check_redirect()

        self.parameters["flv"] = "-"

        return StreamProcess.open(self)
Пример #15
0
    def handshake(self, fd):
        try:
            self.flv = FLV(fd)
        except FLVError as err:
            raise StreamError(str(err))

        self.buffer.write(self.flv.header.serialize())
        log.debug("Attempting to handshake")

        for i, tag in enumerate(self.flv):
            if i == 10:
                raise StreamError(
                    "No OnEdge metadata in FLV after 10 tags, probably not a AkamaiHD stream"
                )

            self.process_tag(tag, exception=StreamError)

            if self.completed_handshake:
                log.debug("Handshake successful")
                break
Пример #16
0
    def create_decryptor(self, key, sequence):
        if key.method != "AES-128":
            raise StreamError("Unable to decrypt cipher {0}", key.method)

        if not key.uri:
            raise StreamError("Missing URI to decryption key")

        if self.key_uri != key.uri:
            res = self.session.http.get(key.uri, exception=StreamError,
                                        retries=self.retries,
                                        **self.reader.request_params)
            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)
Пример #17
0
 def url(self):
     # If the watch timeout has passed then refresh the playlist from the API
     if int(time.time()) >= self.watch_timeout:
         for stream in self._get_stream_data():
             if stream["quality"] == self.quality:
                 self.watch_timeout = int(time.time()) + stream["watch-timeout"]
                 self._url = stream["url"]
                 return self._url
         raise StreamError("cannot refresh FilmOn HLS Stream playlist")
     else:
         return self._url
Пример #18
0
    def _generate_session_token(self, data64):
        swfdata = base64.decodestring(bytes(data64, "ascii"))
        md5 = hashlib.md5()
        md5.update(swfdata)
        hash = md5.hexdigest()

        if hash in self.TokenGenerators:
            generator = self.TokenGenerators[hash](self)

            return generator.generate()
        else:
            raise StreamError(
                ("No token generator available for hash '{0}'").format(hash))
Пример #19
0
    def cached(self, sequence: Sequence.num, byterange: ByteRange) -> Tuple[int, int]:
        if byterange.offset is not None:
            bytes_start = byterange.offset
        elif self.offset is not None and self.sequence == sequence - 1:
            bytes_start = self.offset
        else:
            raise StreamError("Missing BYTERANGE offset")

        bytes_end = self._calc_end(bytes_start, byterange.range)

        self.sequence = sequence
        self.offset = bytes_end + 1

        return bytes_start, bytes_end
Пример #20
0
    def _supports_param(self, param, timeout=5.0):
        try:
            rtmpdump = self.spawn(dict(help=True), timeout=timeout, stderr=subprocess.PIPE)
        except StreamError as err:
            raise StreamError("Error while checking rtmpdump compatibility: {0}".format(err.message))

        for line in rtmpdump.stderr.readlines():
            m = re.match(r"^--(\w+)", str(line, "ascii"))

            if not m:
                continue

            if m.group(1) == param:
                return True

        return False
Пример #21
0
    def generate(self):
        if not self.stream.swf:
            raise StreamError("A SWF URL is required to create session token")

        res = self.stream.session.http.get(self.stream.swf,
                                           exception=StreamError)
        data = swfdecompress(res.content)

        md5 = hashlib.md5()
        md5.update(data)

        data = bytes(self.stream.sessionid, "ascii") + md5.digest()
        sig = hmac.new(b"foo", data, hashlib.sha1)
        b64 = base64.encodestring(sig.digest())
        token = str(b64, "ascii").replace("\n", "")

        return token
Пример #22
0
    def fetch_module_info(self):
        self.logger.debug("Fetching module info")
        conn = create_ums_connection("channel",
                                     self.stream.channel_id,
                                     self.stream.page_url,
                                     self.stream.password,
                                     exception=StreamError)

        try:
            result = conn.process_packets(invoked_method="moduleInfo",
                                          timeout=10)
        except (IOError, librtmp.RTMPError) as err:
            raise StreamError("Failed to get module info: {0}".format(err))
        finally:
            conn.close()

        result = _module_info_schema.validate(result)
        return _channel_schema.validate(result, "module info")
Пример #23
0
    def open(self):
        self.guid = cache_bust_string(12)
        self.islive = None
        self.sessionid = None
        self.flv = None

        self.buffer = Buffer()
        self.completed_handshake = False

        url = self.StreamURLFormat.format(host=self.host,
                                          streamname=self.streamname)
        params = self._create_params(seek=self.seek)

        log.debug(f"Opening host={self.host} streamname={self.streamname}")

        try:
            res = self.session.http.get(url, stream=True, params=params)
            self.fd = StreamIOIterWrapper(res.iter_content(8192))
        except Exception as err:
            raise StreamError(str(err))

        self.handshake(self.fd)

        return self
Пример #24
0
    def test_stream_failure_no_output_open(self, mock_console: Mock,
                                           mock_log: Mock):
        output = Mock()
        stream = Mock(__str__=lambda _: "fake-stream",
                      open=Mock(side_effect=StreamError("failure")))
        formatter = Formatter({})

        with patch("streamlink_cli.main.output", Mock()), \
             patch("streamlink_cli.main.create_output", return_value=output):
            output_stream(stream, formatter)

        self.assertEqual(mock_log.error.call_args_list, [
            call(
                "Try 1/2: Could not open stream fake-stream (Could not open stream: failure)"
            ),
            call(
                "Try 2/2: Could not open stream fake-stream (Could not open stream: failure)"
            ),
        ])
        self.assertEqual(mock_console.exit.call_args_list, [
            call("Could not open stream fake-stream, tried 2 times, exiting")
        ])
        self.assertFalse(output.open.called,
                         "Does not open the output on stream error")
Пример #25
0
def create_decryptor(self, key, sequence):
    #self.logger.debug('key.method, key.uri: %s, %s'%(key.method, key.uri))

    if key.method != "AES-128":
        raise StreamError("Unable to decrypt cipher {0}", key.method)

    if not key.uri:
        raise StreamError("Missing URI to decryption key")

    if self.key_uri != key.uri:
        zoom_key = self.reader.stream.session.options.get("zoom-key")
        zuom_key = self.reader.stream.session.options.get("zuom-key")
        livecam_key = self.reader.stream.session.options.get("livecam-key")
        saw_key = self.reader.stream.session.options.get("saw-key")
        your_key = self.reader.stream.session.options.get("your-key")
        mama_key = self.reader.stream.session.options.get("mama-key")
        if zoom_key:
            uri = 'http://www.zoomtv.me/k.php?q='+base64.urlsafe_b64encode(zoom_key+base64.urlsafe_b64encode(key.uri))
        elif zuom_key:
            uri = 'http://www.zuom.xyz/k.php?q='+base64.urlsafe_b64encode(zuom_key+base64.urlsafe_b64encode(key.uri))
        elif livecam_key:           
            h = urlparse.urlparse(urllib.unquote(livecam_key)).netloc
            q = urlparse.urlparse(urllib.unquote(livecam_key)).query            
            uri = 'http://%s/kaes?q='%h+base64.urlsafe_b64encode(q+base64.b64encode(key.uri))
        elif saw_key:
            if 'foxsportsgo' in key.uri:
                _tmp = key.uri.split('/')
                uri = urljoin(saw_key,'/m/fream?p='+_tmp[-4]+'&k='+_tmp[-1])
            elif 'nlsk.neulion' in key.uri:
                _tmp = key.uri.split('?')
                uri = urljoin(saw_key,'/m/stream?'+_tmp[-1])
            elif 'nlsk' in key.uri:
                _tmp = key.uri.split('?')
                uri = 'http://bile.level303.club/m/stream?'+_tmp[-1]
            elif 'nhl.com' in key.uri:
                _tmp = key.uri.split('/')
                uri = urljoin(saw_key,'/m/streams?ci='+_tmp[-3]+'&k='+_tmp[-1])
            else:
                uri = key.uri
        elif mama_key:
           if 'nlsk' in key.uri:
                _tmp = key.uri.split('&url=')
                uri = 'http://mamahd.in/nba?url=' + _tmp[-1]
        elif your_key:
            if 'mlb.com' in key.uri:
                _tmp = key.uri.split('?')
                uri = urljoin(your_key,'/mlb/get_key/'+_tmp[-1])
            elif 'espn3/auth' in key.uri:
                _tmp = key.uri.split('?')
                uri = urljoin(your_key,'/ncaa/get_key/'+_tmp[-1])
            elif 'nhl.com' in key.uri:
                _tmp = key.uri.split('nhl.com/')
                uri = urljoin(your_key,'/nhl/get_key/'+_tmp[-1])
            else:
                uri = key.uri
        else:
            uri = key.uri

        res = self.session.http.get(uri, exception=StreamError,
                                    retries=self.retries,
                                    **self.reader.request_params)

        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

    if _android_ssl:
        return enc(self.key_data, iv)
    elif _oscrypto:
        return AES(self.key_data, iv)
    else:
        return AES.new(self.key_data, AES.MODE_CBC, iv)
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")

    key_uri = self.key_uri_override if self.key_uri_override else key.uri

    if self.key_uri != key_uri:
        zoom_key = self.reader.stream.session.options.get("zoom-key")
        zuom_key = self.reader.stream.session.options.get("zuom-key")
        livecam_key = self.reader.stream.session.options.get("livecam-key")
        saw_key = self.reader.stream.session.options.get("saw-key")
        your_key = self.reader.stream.session.options.get("your-key")
        mama_key = self.reader.stream.session.options.get("mama-key")
        #custom_uri = self.reader.stream.session.options.get("custom-uri")

        if zoom_key:
            uri = 'http://www.zoomtv.me/k.php?q=' + base64.urlsafe_b64encode(
                zoom_key + base64.urlsafe_b64encode(key_uri))
        elif zuom_key:
            uri = 'http://www.zuom.xyz/k.php?q=' + base64.urlsafe_b64encode(
                zuom_key + base64.urlsafe_b64encode(key_uri))
        elif livecam_key:
            h = urlparse.urlparse(urllib.unquote(livecam_key)).netloc
            q = urlparse.urlparse(urllib.unquote(livecam_key)).query
            uri = 'https://%s/kaesv2?sqa=' % h + base64.urlsafe_b64encode(
                q + base64.b64encode(key_uri))
        elif saw_key:
            if 'foxsportsgo' in key_uri:
                _tmp = key_uri.split('/')
                uri = urljoin(saw_key,
                              '/m/fream?p=' + _tmp[-4] + '&k=' + _tmp[-1])
            elif 'nlsk.neulion' in key_uri:
                _tmp = key_uri.split('?')
                uri = urljoin(saw_key, '/m/stream?' + _tmp[-1])
            elif 'nlsk' in key_uri:
                _tmp = key_uri.split('?')
                uri = 'http://bile.level303.club/m/stream?' + _tmp[-1]
            elif 'nhl.com' in key_uri:
                _tmp = key_uri.split('/')
                uri = urljoin(saw_key,
                              '/m/streams?ci=' + _tmp[-3] + '&k=' + _tmp[-1])
            else:
                uri = key_uri
        elif mama_key:
            if 'nlsk' in key_uri:
                _tmp = key_uri.split('&url=')
                uri = 'http://mamahd.in/nba?url=' + _tmp[-1]
        elif your_key:
            if re.search(
                    r'playback\.svcs\.mlb\.com|mlb-ws-mf\.media\.mlb\.com|mf\.svc\.nhl\.com',
                    key_uri, re.IGNORECASE) != None:
                _ip = your_key.split('?')[1]
                uri = re.sub(
                    r'playback\.svcs\.mlb\.com|mlb-ws-mf\.media\.mlb\.com|mf\.svc\.nhl\.com',
                    _ip, key_uri, re.IGNORECASE)
            elif 'mlb.com' in key_uri:
                _tmp = key_uri.split('?')
                uri = urljoin(your_key, '/mlb/get_key/' + _tmp[-1])
            elif 'espn3/auth' in key_uri:
                _tmp = key_uri.split('?')
                uri = urljoin(your_key, '/ncaa/get_key/' + _tmp[-1])
            elif 'nhl.com' in key_uri:
                _tmp = key_uri.split('nhl.com/')
                uri = urljoin(your_key, '/nhl/get_key/' + _tmp[-1])
            else:
                uri = key_uri
        #elif custom_uri:
        #uri = custom_uri

        else:
            uri = key_uri

        #xbmc.log('[StreamLink_Proxy] using key uri %s'%str(uri))

        res = self.session.http.get(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

    if _android_ssl:
        return enc(self.key_data, iv)
    elif _oscrypto:
        return AES(self.key_data, iv)
    else:
        return AES.new(self.key_data, AES.MODE_CBC, iv)
Пример #27
0
    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)
Пример #28
0
    def uncached(self, byterange: ByteRange) -> Tuple[int, int]:
        bytes_start = byterange.offset
        if bytes_start is None:
            raise StreamError("Missing BYTERANGE offset")

        return bytes_start, self._calc_end(bytes_start, byterange.range)