Пример #1
0
class WebTV(Plugin):
    _url_re = re.compile(r"http(?:s)?://(\w+)\.web.tv/?")
    _sources_re = re.compile(r'"sources": (\[.*?\]),', re.DOTALL)
    _sources_schema = validate.Schema([
        {
            "src": validate.any(
                validate.contains("m3u8"),
                validate.all(
                    validate.text,
                    validate.transform(lambda x: WebTV.decrypt_stream_url(x)),
                    validate.contains("m3u8")
                )
            ),
            "type": validate.text,
            "label": validate.text
        }
    ])

    @classmethod
    def can_handle_url(cls, url):
        return cls._url_re.match(url) is not None

    @staticmethod
    def decrypt_stream_url(encoded_url):
        data = base64.b64decode(encoded_url)
        cipher_text = binascii.unhexlify(data[96:])

        decryptor = AES.new(binascii.unhexlify(data[32:96]),
                            AES.MODE_CBC,
                            binascii.unhexlify(data[:32]))

        return unpad_pkcs5(decryptor.decrypt(cipher_text)).decode("utf8")

    def _get_streams(self):
        """
        Find the streams for web.tv
        :return:
        """
        headers = {}
        res = self.session.http.get(self.url, headers=headers)
        headers["Referer"] = self.url

        sources = self._sources_re.findall(res.text)
        if len(sources):
            sdata = parse_json(sources[0], schema=self._sources_schema)
            for source in sdata:
                log.debug(f"Found stream of type: {source['type']}")
                if source["type"] == "application/vnd.apple.mpegurl":
                    url = update_scheme(self.url, source["src"])

                    try:
                        # try to parse the stream as a variant playlist
                        variant = HLSStream.parse_variant_playlist(self.session, url, headers=headers)
                        if variant:
                            yield from variant.items()
                        else:
                            # and if that fails, try it as a plain HLS stream
                            yield 'live', HLSStream(self.session, url, headers=headers)
                    except IOError:
                        log.warning("Could not open the stream, perhaps the channel is offline")
Пример #2
0
 def test_failure_schema(self):
     with pytest.raises(validate.ValidationError) as cm:
         validate.validate(validate.contains("invalid"), 1)
     assert_validationerror(
         cm.value, """
         ValidationError(type):
           Type of 1 should be str, but is int
     """)
Пример #3
0
 def test_failure(self):
     with pytest.raises(validate.ValidationError) as cm:
         validate.validate(validate.contains("invalid"), "foo bar baz")
     assert_validationerror(
         cm.value, """
         ValidationError(contains):
           'foo bar baz' does not contain 'invalid'
     """)
Пример #4
0
class OlympicChannel(Plugin):
    _url_re = re.compile(
        r"https?://(\w+\.)olympicchannel.com/../(?P<type>live|video|original-series|films)/?(?:\w?|[-\w]+)"
    )
    _tokenizationApiDomainUrl = """"tokenizationApiDomainUrl" content="/OcsTokenization/api/v1/tokenizedUrl">"""
    _live_api_path = "/OcsTokenization/api/v1/tokenizedUrl?url={url}&domain={netloc}&_ts={time}"

    _api_schema = validate.Schema(validate.text,
                                  validate.transform(lambda v: json.loads(v)),
                                  validate.url())
    _video_url_re = re.compile(
        r""""video_url"\scontent\s*=\s*"(?P<value>[^"]+)""")
    _video_url_schema = validate.Schema(
        validate.contains(_tokenizationApiDomainUrl),
        validate.transform(_video_url_re.search),
        validate.any(None, validate.get("value")), validate.url())

    @classmethod
    def can_handle_url(cls, url):
        return cls._url_re.match(url)

    def _get_vod_streams(self):
        stream_url = self.session.http.get(self.url,
                                           schema=self._video_url_schema)
        return HLSStream.parse_variant_playlist(self.session, stream_url)

    def _get_live_streams(self):
        video_url = self.session.http.get(self.url,
                                          schema=self._video_url_schema)
        parsed = urlparse(video_url)
        api_url = urljoin(
            self.url,
            self._live_api_path.format(url=video_url,
                                       netloc="{0}://{1}".format(
                                           parsed.scheme, parsed.netloc),
                                       time=int(time())))
        stream_url = self.session.http.get(api_url, schema=self._api_schema)
        return HLSStream.parse_variant_playlist(self.session, stream_url)

    def _get_streams(self):
        match = self._url_re.match(self.url)
        type_of_stream = match.group('type')

        if type_of_stream == 'live':
            return self._get_live_streams()
        elif type_of_stream in ('video', 'original-series', 'films'):
            return self._get_vod_streams()
Пример #5
0
class CeskatelevizeAPI2(object):
    _player_api = 'https://playlist.ceskatelevize.cz/'
    _url_re = re.compile(r'http(s)?://([^.]*.)?ceskatelevize.cz')
    _playlist_info_re = re.compile(
        r'{\s*"type":\s*"([a-z]+)",\s*"id":\s*"(\w+)"')
    _playlist_schema = validate.Schema({
        "CODE": validate.contains("OK"),
        "RESULT": {
            "playlist": [{
                "streamUrls": {
                    "main": validate.url(),
                }
            }]
        }
    })
    _ctcomp_re = re.compile(
        r'data-ctcomp="Video"\sdata-video-id="(?P<val1>[^"]*)"\sdata-ctcomp-data="(?P<val2>[^"]+)">'
    )
    _ctcomp_schema = validate.Schema(
        validate.text, validate.transform(_ctcomp_re.findall),
        validate.transform(
            lambda vl: [{
                "video-id": v[0],
                "ctcomp-data": json.loads(html_unescape(v[1]))
            } for v in vl]))
    _playlist_info_schema = validate.Schema({
        "type":
        validate.text,
        "id":
        validate.any(validate.text, int),
        "key":
        validate.text,
        "date":
        validate.text,
        "requestSource":
        validate.text,
        "drm":
        int,
        validate.optional("canBePlay"):
        int,
        validate.optional("assetId"):
        validate.text,
        "quality":
        validate.text,
        validate.optional("region"):
        int
    })

    def __init__(self, session, url, res=None):
        self.session = session
        self.url = url
        self.response = res

    def _get_streams(self):
        if self.response is None:
            infos = self.session.http.get(self.url, schema=self._ctcomp_schema)
        else:
            infos = self.session.http.json(self.response,
                                           schema=self._ctcomp_schema)
        if not infos:
            # playlist infos not found
            raise PluginError('Cannot find playlist infos!')

        vod_prio = len(infos) == 2
        for info in infos:
            try:
                pl = info['ctcomp-data']['source']['playlist'][0]
            except KeyError:
                raise PluginError('Cannot find playlist info!')

            pl = self._playlist_info_schema.validate(pl)
            if vod_prio and pl['type'] != 'VOD':
                continue

            log.trace('{0!r}'.format(info))
            if pl['type'] == 'LIVE':
                data = {
                    "contentType":
                    "live",
                    "items": [{
                        "id": pl["id"],
                        "assetId": pl["assetId"],
                        "key": pl["key"],
                        "playerType": "dash",
                        "date": pl["date"],
                        "requestSource": pl["requestSource"],
                        "drm": pl["drm"],
                        "quality": pl["quality"],
                    }]
                }
            elif pl['type'] == 'VOD':
                data = {
                    "contentType":
                    "vod",
                    "items": [{
                        "id": pl["id"],
                        "key": pl["key"],
                        "playerType": "dash",
                        "date": pl["date"],
                        "requestSource": pl["requestSource"],
                        "drm": pl["drm"],
                        "canBePlay": pl["canBePlay"],
                        "quality": pl["quality"],
                        "region": pl["region"]
                    }]
                }

        headers = {
            "Content-Type": "application/x-www-form-urlencoded; charset=UTF-8",
        }

        data = json.dumps(data)
        response = self.session.http.post(self._player_api,
                                          data="data={}".format(quote(data)),
                                          headers=headers)
        json_data = self.session.http.json(response,
                                           schema=self._playlist_schema)
        log.trace('{0!r}'.format(json_data))
        playlist = json_data['RESULT']['playlist'][0]['streamUrls']['main']
        for s in DASHStream.parse_manifest(self.session, playlist).items():
            yield s
Пример #6
0
class LivespottingTV(Plugin):
    _url_re = re.compile(
        r"""
        (?:
            https?://livespotting\.tv/
            (?:locations\?id=)?
            (?:[^/].+/)?
        )(\w+)
    """, re.VERBOSE)
    _player_re = re.compile(
        r"player_id:\s*'(\w+)',\s*livesource_id:\s*'(\w+)'")

    _URL_PLAYER_CONFIG = "https://player.livespotting.com/v1/config/{player_id}.json"
    _URL_PLAYER_SHOWROOM = "https://player.livespotting.com/v2/livesource/{livesource_id}?type=showroom"

    _playlist_schema = validate.Schema({
        "id": validate.text,
        "playlist": validate.url(scheme="http"),
        "playlist_mode": validate.text,
        "weather_live_enable": bool,
    })
    _sources_schema = validate.Schema([{
        validate.optional("mediaid"):
        validate.text,
        validate.optional("title"):
        validate.text,
        validate.optional("livestream"):
        validate.all(validate.url(scheme="http"), validate.contains(".m3u8")),
        "sources": [{
            "file":
            validate.all(validate.url(scheme="http"),
                         validate.contains(".m3u8"))
        }],
    }])
    _livesource_schema = validate.Schema({
        "id":
        validate.text,
        "source":
        validate.all(validate.url(scheme="http"), validate.contains(".m3u8")),
    })

    @classmethod
    def can_handle_url(cls, url):
        return cls._url_re.match(url) is not None

    def _get_streams(self):
        source_id = self._url_re.search(self.url).group(1)
        res = self.session.http.get(self.url)
        m = self._player_re.search(res.text)
        if m:
            _player_id, _source_id = m.groups()
            if _source_id == source_id:
                config_url = self._URL_PLAYER_CONFIG.format(
                    player_id=_player_id)
                log.debug("config_url: {0}".format(config_url))
                res = self.session.http.get(config_url)
                res = self.session.http.json(res, schema=self._playlist_schema)
                log.debug("playlist_mode: {0}".format(res["playlist_mode"]))
                log.debug("weather_live_enable: {0}".format(
                    res["weather_live_enable"]))
                if res["playlist_mode"] == "showroom":
                    playlist_url = self._URL_PLAYER_SHOWROOM.format(
                        livesource_id=_source_id)
                    _schema = self._livesource_schema
                else:
                    playlist_url = res["playlist"]
                    _schema = self._sources_schema

                log.debug("playlist_url: {0}".format(playlist_url))
                res = self.session.http.get(playlist_url)
                res = self.session.http.json(res, schema=_schema)
                log.trace("sources: {0!r}".format(res))
                for source in res if isinstance(res, list) else [res]:
                    _id = source.get("mediaid") or _source_id
                    if _id == _source_id:
                        title = source.get("title", "N/A")
                        log.debug("title: {0}".format(title))
                        if source.get("livestream"):
                            for s in HLSStream.parse_variant_playlist(
                                    self.session,
                                    source["livestream"]).items():
                                yield s
                        else:
                            log.debug(
                                "No 'livestream' source found, trying alt. sources"
                            )
                            sources = source.get("sources") or [{
                                "file":
                                source["source"]
                            }]
                            for file in sources:
                                for s in HLSStream.parse_variant_playlist(
                                        self.session, file["file"]).items():
                                    yield s
Пример #7
0
 def test_success(self):
     assert validate.validate(validate.contains("bar"), "foo bar baz")