Exemplo n.º 1
0
class RaiPlay(Plugin):
    url_re = re.compile(r"https?://(?:www\.)?raiplay\.it/dirette/(\w+)/?")
    stream_re = re.compile(r"data-video-url.*?=.*?\"([^\"]+)\"")
    stream_schema = validate.Schema(
        validate.all(
            validate.transform(stream_re.search),
            validate.any(None, validate.all(validate.get(1), validate.url()))))

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

    def _get_streams(self):
        http.headers.update({"User-Agent": useragents.FIREFOX})
        channel = self.url_re.match(self.url).group(1)
        self.logger.debug("Found channel: {0}", channel)
        stream_url = http.get(self.url, schema=self.stream_schema)
        if stream_url:
            try:
                return HLSStream.parse_variant_playlist(
                    self.session, stream_url)
            except Exception as e:
                if "Missing #EXTM3U header" in str(e):
                    raise PluginError(
                        "The streaming of this content is available in Italy only."
                    )
                raise e
Exemplo n.º 2
0
class CDNBG(Plugin):
    url_re = re.compile(
        r"""
        https?://(?:www\.)?(?:
            tv\.bnt\.bg/\w+(?:/\w+)?|
            bitelevision\.com/live|
            nova\.bg/live|
            kanal3\.bg/live|
            bgonair\.bg/tvonline|
            tvevropa\.com/na-zhivo|
            bloombergtv.bg/video
        )/?
    """, re.VERBOSE)
    iframe_re = re.compile(
        r"iframe .*?src=\"((?:https?:)?//(?:\w+\.)?cdn.bg/live[^\"]+)\"",
        re.DOTALL)
    sdata_re = re.compile(
        r"sdata\.src.*?=.*?(?P<q>[\"'])(?P<url>http.*?)(?P=q)")
    hls_file_re = re.compile(
        r"(src|file): (?P<q>[\"'])(?P<url>(https?:)?//.+?m3u8.*?)(?P=q)")
    hls_src_re = re.compile(r"video src=(?P<url>http[^ ]+m3u8[^ ]*)")

    stream_schema = validate.Schema(
        validate.any(
            validate.all(validate.transform(sdata_re.search),
                         validate.get("url")),
            validate.all(validate.transform(hls_file_re.search),
                         validate.get("url")),
            validate.all(validate.transform(hls_src_re.search),
                         validate.get("url")),
        ))

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

    def find_iframe(self, res):
        p = urlparse(self.url)
        for url in self.iframe_re.findall(res.text):
            if "googletagmanager" not in url:
                if url.startswith("//"):
                    return "{0}:{1}".format(p.scheme, url)
                else:
                    return url

    def _get_streams(self):
        http.headers = {"User-Agent": useragents.CHROME}
        res = http.get(self.url)
        iframe_url = self.find_iframe(res)

        if iframe_url:
            self.logger.debug("Found iframe: {0}", iframe_url)
            res = http.get(iframe_url, headers={"Referer": self.url})
            stream_url = update_scheme(self.url,
                                       self.stream_schema.validate(res.text))
            return HLSStream.parse_variant_playlist(
                self.session,
                stream_url,
                headers={"User-Agent": useragents.CHROME})
Exemplo n.º 3
0
class TV8(Plugin):
    """
    Support for the live stream on www.tv8.com.tr
    """
    url_re = re.compile(r"https?://www.tv8.com.tr/canli-yayin")

    player_config_re = re.compile(
        r"""
        configPlayer.source.media.push[ ]*\(
        [ ]*\{[ ]*'src':[ ]*"(.*?)",
        [ ]*type:[ ]*"application/x-mpegURL"[ ]*}[ ]*\);
    """, re.VERBOSE)
    player_config_schema = validate.Schema(
        validate.transform(player_config_re.search),
        validate.any(None, validate.all(validate.get(1), validate.url())))

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

    def _get_streams(self):
        res = http.get(self.url)
        stream_url = self.player_config_schema.validate(res.text)
        if stream_url:
            return HLSStream.parse_variant_playlist(self.session, stream_url)
Exemplo n.º 4
0
class Streamable(Plugin):
    url_re = re.compile(r"https?://(?:www\.)?streamable\.com/(.+)")
    meta_re = re.compile(r'''var\s*videoObject\s*=\s*({.*});''')
    config_schema = validate.Schema(
        validate.transform(meta_re.search),
        validate.any(
            None,
            validate.all(
                validate.get(1), validate.transform(parse_json), {
                    "files": {
                        validate.text: {
                            "url": validate.url(),
                            "width": int,
                            "height": int,
                            "bitrate": int
                        }
                    }
                })))

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

    def _get_streams(self):
        data = http.get(self.url, schema=self.config_schema)

        for info in data["files"].values():
            stream_url = update_scheme(self.url, info["url"])
            # pick the smaller of the two dimensions, for landscape v. portrait videos
            res = min(info["width"], info["height"])
            yield "{0}p".format(res), HTTPStream(self.session, stream_url)
Exemplo n.º 5
0
class RadioNet(Plugin):
    _url_re = re.compile(r"https?://(\w+)\.radio\.(net|at|de|dk|es|fr|it|pl|pt|se)")
    _stream_data_re = re.compile(r'\bstation\s*:\s*(\{.+\}),?\s*')

    _stream_schema = validate.Schema(
        validate.transform(_stream_data_re.search),
        validate.any(
            None,
            validate.all(
                validate.get(1),
                validate.transform(parse_json),
                {
                    'stationType': validate.text,
                    'streamUrls': validate.all([{
                        'bitRate': int,
                        'streamUrl': validate.url()
                    }])
                },
            )
        )
    )

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

    def _get_streams(self):
        streams = http.get(self.url, schema=self._stream_schema)
        if streams is None:
            return

        # Ignore non-radio streams (podcasts...)
        if streams['stationType'] != 'radio_station':
            return

        stream_urls = []
        for stream in streams['streamUrls']:
            if stream['streamUrl'] in stream_urls:
                continue

            if stream['bitRate'] > 0:
                bitrate = '{}k'.format(stream['bitRate'])
            else:
                bitrate = 'live'
            yield bitrate, HTTPStream(self.session, stream['streamUrl'])
            stream_urls.append(stream['streamUrl'])
Exemplo n.º 6
0
class RaiPlay(Plugin):
    url_re = re.compile(r"https?://(?:www\.)?raiplay\.it/dirette/(\w+)/?")
    stream_re = re.compile(r"data-video-url.*?=.*?\"([^\"]+)\"")
    stream_schema = validate.Schema(
        validate.all(
            validate.transform(stream_re.search),
            validate.any(
                None,
                validate.all(validate.get(1), validate.url())
            )
        )
    )

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

    def _get_streams(self):
        channel = self.url_re.match(self.url).group(1)
        self.logger.debug("Found channel: {0}", channel)
        stream_url = http.get(self.url, schema=self.stream_schema)
        if stream_url:
            return HLSStream.parse_variant_playlist(self.session, stream_url)
Exemplo n.º 7
0
class ovvaTV(Plugin):
    url_re = re.compile(
        r"https?://(?:www\.)?ovva.tv/(?:ua/)?tvguide/.*?/online")
    iframe_re = re.compile(
        r"iframe .*?src=\"((?:https?:)?//(?:\w+\.)?ovva.tv/[^\"]+)\"",
        re.DOTALL)
    data_re = re.compile(r"ovva\(\'(.*?)\'\);")
    ovva_data_schema = validate.Schema({"url": validate.url()},
                                       validate.get("url"))
    ovva_redirect_schema = validate.Schema(
        validate.all(validate.transform(lambda x: x.split("=")),
                     ['302', validate.url()], validate.get(1)))

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

    def find_iframe(self, res):
        for url in self.iframe_re.findall(res.text):
            if url.startswith("//"):
                p = urlparse(self.url)
                return "{0}:{1}".format(p.scheme, url)
            else:
                return url

    def _get_streams(self):
        http.headers = {"User-Agent": useragents.ANDROID}
        res = http.get(self.url)
        iframe_url = self.find_iframe(res)

        if iframe_url:
            self.logger.debug("Found iframe: {0}", iframe_url)
            res = http.get(iframe_url, headers={"Referer": self.url})
            data = self.data_re.search(res.text)
            if data:
                try:
                    ovva_url = parse_json(b64decode(
                        data.group(1)).decode("utf8"),
                                          schema=self.ovva_data_schema)
                    stream_url = http.get(ovva_url,
                                          schema=self.ovva_redirect_schema)
                except PluginError as e:
                    self.logger.error("Could not find stream URL: {0}", e)
                else:
                    return HLSStream.parse_variant_playlist(
                        self.session, stream_url)
            else:
                self.logger.error("Could not find player data.")
Exemplo n.º 8
0
class LiveMe(Plugin):
    url_re = re.compile(r"https?://(www.)?liveme\.com/live\.html\?videoid=(\d+)")
    api_url = "https://live.ksmobile.net/live/queryinfo"
    api_schema = validate.Schema(validate.all({
        "status": "200",
        "data": {
            "video_info": {
                "videosource": validate.any('', validate.url()),
                "hlsvideosource": validate.any('', validate.url()),
            }
        }
    }, validate.get("data")))

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

    def _random_t(self, t):
        return "".join(random.choice("ABCDEFGHJKMNPQRSTWXYZabcdefhijkmnprstwxyz2345678") for _ in range(t))

    def _make_stream(self, url):
        if url and url.endswith("flv"):
            return HTTPStream(self.session, url)
        elif url and url.endswith("m3u8"):
            return HLSStream(self.session, url)

    def _get_streams(self):
        url_params = dict(parse_qsl(urlparse(self.url).query))
        video_id = url_params.get("videoid")

        if video_id:
            vali = '{0}l{1}m{2}'.format(self._random_t(4), self._random_t(4), self._random_t(5))
            data = {
                'userid': 1,
                'videoid': video_id,
                'area': '',
                'h5': 1,
                'vali': vali
            }
            self.logger.debug("Found Video ID: {0}".format(video_id))
            res = http.post(self.api_url, data=data)
            data = http.json(res, schema=self.api_schema)
            hls = self._make_stream(data["video_info"]["hlsvideosource"])
            video = self._make_stream(data["video_info"]["videosource"])
            if hls:
                yield "live", hls
            if video:
                yield "live", video
Exemplo n.º 9
0
class Turkuvaz(Plugin):
    """
    Plugin to support ATV/A2TV Live streams from www.atv.com.tr and www.a2tv.com.tr
    """

    _url_re = re.compile(
        r"""https?://(?:www.)?
                             (?:(atvavrupa).tv|
                                (atv|a2tv|ahaber|aspor|minikago|minikacocuk|anews).com.tr)
                                /webtv/(live-broadcast|canli-yayin)""",
        re.VERBOSE)
    _hls_url = "http://trkvz-live.ercdn.net/{channel}/{channel}.m3u8"
    _token_url = "http://videotoken.tmgrup.com.tr/webtv/secure"
    _token_schema = validate.Schema(
        validate.all({
            "Success": True,
            "Url": validate.url(),
        }, validate.get("Url")))

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

    def _get_streams(self):
        url_m = self._url_re.match(self.url)
        domain = url_m.group(1) or url_m.group(2)
        # remap the domain to channel
        channel = {
            "atv": "atvhd",
            "ahaber": "ahaberhd",
            "aspor": "asporhd",
            "anews": "anewshd",
            "minikacocuk": "minikagococuk"
        }.get(domain, domain)
        hls_url = self._hls_url.format(channel=channel)
        # get the secure HLS URL
        res = http.get(self._token_url,
                       params="url={0}".format(hls_url),
                       headers={
                           "Referer": self.url,
                           "User-Agent": useragents.CHROME
                       })

        secure_hls_url = http.json(res, schema=self._token_schema)

        self.logger.debug("Found HLS URL: {0}".format(secure_hls_url))
        return HLSStream.parse_variant_playlist(self.session, secure_hls_url)
Exemplo n.º 10
0
class ard_live(Plugin):
    swf_url = "http://live.daserste.de/lib/br-player/swf/main.swf"
    _url_re = re.compile(r"https?://(www.)?daserste.de/", re.I)
    _player_re = re.compile(r'''dataURL\s*:\s*(?P<q>['"])(?P<url>.*?)(?P=q)''')
    _player_url_schema = validate.Schema(
        validate.transform(_player_re.search),
        validate.any(None, validate.all(validate.get("url"), validate.text)))
    _livestream_schema = validate.Schema(
        validate.xml_findall(".//assets"),
        validate.filter(lambda x: x.attrib.get("type") != "subtitles"),
        validate.get(0), validate.xml_findall(".//asset"), [
            validate.union({
                "url": validate.xml_findtext("./fileName"),
                "bitrate": validate.xml_findtext("./bitrateVideo")
            })
        ])

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

    def _get_streams(self):
        data_url = http.get(self.url, schema=self._player_url_schema)
        if data_url:
            res = http.get(urljoin(self.url, data_url))
            stream_info = http.xml(res, schema=self._livestream_schema)

            for stream in stream_info:
                url = stream["url"]
                try:
                    if ".m3u8" in url:
                        for s in HLSStream.parse_variant_playlist(
                                self.session, url, name_key="bitrate").items():
                            yield s
                    elif ".f4m" in url:
                        for s in HDSStream.parse_manifest(
                                self.session,
                                url,
                                pvswf=self.swf_url,
                                is_akamai=True).items():
                            yield s
                    elif ".mp4" in url:
                        yield "{0}k".format(stream["bitrate"]), HTTPStream(
                            self.session, url)
                except IOError as err:
                    self.logger.warning("Error parsing stream: {0}", err)
Exemplo n.º 11
0
class Cam4(Plugin):
    _url_re = re.compile(r'https?://([a-z]+\.)?cam4.com/.+')
    _video_data_re = re.compile(
        r"flashData: (?P<flash_data>{.*}), hlsUrl: '(?P<hls_url>.+?)'")

    _flash_data_schema = validate.Schema(
        validate.all(
            validate.transform(parse_json),
            validate.Schema({
                'playerUrl':
                validate.url(),
                'flashVars':
                validate.Schema({
                    'videoPlayUrl': validate.text,
                    'videoAppUrl': validate.url(scheme='rtmp')
                })
            })))

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

    def _get_streams(self):
        res = http.get(self.url, headers={'User-Agent': useragents.ANDROID})
        match = self._video_data_re.search(res.text)
        if match is None:
            return

        hls_streams = HLSStream.parse_variant_playlist(
            self.session,
            match.group('hls_url'),
            headers={'Referer': self.url})
        for s in hls_streams.items():
            yield s

        rtmp_video = self._flash_data_schema.validate(
            match.group('flash_data'))
        rtmp_stream = RTMPStream(
            self.session, {
                'rtmp': rtmp_video['flashVars']['videoAppUrl'],
                'playpath': rtmp_video['flashVars']['videoPlayUrl'],
                'swfUrl': rtmp_video['playerUrl']
            })
        yield 'live', rtmp_stream
Exemplo n.º 12
0
class TVRPlus(Plugin):
    url_re = re.compile(r"https?://(?:www\.)tvrplus.ro/live-")
    hls_file_re = re.compile(
        r"""src:\s?(?P<q>["'])(?P<url>http.+?m3u8.*?)(?P=q)""")

    stream_schema = validate.Schema(
        validate.all(validate.transform(hls_file_re.search),
                     validate.any(None, validate.get("url"))), )

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

    def _get_streams(self):
        stream_url = self.stream_schema.validate(http.get(self.url).text)
        if stream_url:
            headers = {"Referer": self.url}
            return HLSStream.parse_variant_playlist(self.session,
                                                    stream_url,
                                                    headers=headers)
Exemplo n.º 13
0
class TVRBy(Plugin):
    url_re = re.compile(r"""https?://(?:www\.)?tvr.by/televidenie/belarus""")
    file_re = re.compile(
        r"""(?P<q1>["']?)file(?P=q1)\s*:\s*(?P<q2>["'])(?P<url>(?:http.+?m3u8.*?|rtmp://.*?))(?P=q2)"""
    )

    stream_schema = validate.Schema(
        validate.all(validate.transform(file_re.finditer),
                     validate.transform(list), [validate.get("url")]), )

    def __init__(self, url):
        # ensure the URL ends with a /
        if not url.endswith("/"):
            url += "/"
        super(TVRBy, self).__init__(url)

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

    def _get_streams(self):
        res = http.get(self.url)
        stream_urls = self.stream_schema.validate(res.text)
        self.logger.debug("Found {0} stream URL{1}", len(stream_urls),
                          "" if len(stream_urls) == 1 else "s")

        for stream_url in stream_urls:
            if "m3u8" in stream_url:
                for _, s in HLSStream.parse_variant_playlist(
                        self.session, stream_url).items():
                    yield "live", s
            if stream_url.startswith("rtmp://"):
                a = stream_url.split("///")
                s = RTMPStream(
                    self.session, {
                        "rtmp": a[0],
                        "playpath": "live",
                        "swfVfy": "http://www.tvr.by/plugines/uppod/uppod.swf",
                        "pageUrl": self.url
                    })
                yield "live", s
Exemplo n.º 14
0
class INE(Plugin):
    url_re = re.compile(r"""https://streaming.ine.com/play\#?/
            ([0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12})/?
            (.*?)""", re.VERBOSE)
    play_url = "https://streaming.ine.com/play/{vid}/watch"
    js_re = re.compile(r'''script type="text/javascript" src="(https://content.jwplatform.com/players/.*?)"''')
    jwplayer_re = re.compile(r'''jwConfig\s*=\s*(\{.*\});''', re.DOTALL)
    setup_schema = validate.Schema(
        validate.transform(jwplayer_re.search),
        validate.any(
            None,
            validate.all(
                validate.get(1),
                validate.transform(json.loads),
                {"playlist": [
                    {"sources": [{"file": validate.text,
                                  "type": validate.text}]}
                ]}
            )
        )
    )

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

    def _get_streams(self):
        vid = self.url_re.match(self.url).group(1)
        self.logger.debug("Found video ID: {0}", vid)

        page = http.get(self.play_url.format(vid=vid))
        js_url_m = self.js_re.search(page.text)
        if js_url_m:
            js_url = js_url_m.group(1)
            self.logger.debug("Loading player JS: {0}", js_url)

            res = http.get(js_url)
            data = self.setup_schema.validate(res.text)
            for source in data["playlist"][0]["sources"]:
                if source["type"] == "hls":
                    return HLSStream.parse_variant_playlist(self.session, "https:" + source["file"])
Exemplo n.º 15
0
class CinerGroup(Plugin):
    """
    Support for the live stream on www.showtv.com.tr
    """
    url_re = re.compile(
        r"""https?://(?:www.)?
        (?:
            showtv.com.tr/canli-yayin(/showtv)?|
            haberturk.com/canliyayin|
            showmax.com.tr/canliyayin|
            showturk.com.tr/canli-yayin/showturk|
            bloomberght.com/tv|
            haberturk.tv/canliyayin
        )/?""", re.VERBOSE)
    stream_re = re.compile(
        r"""div .*? data-ht=(?P<quote>["'])(?P<data>.*?)(?P=quote)""",
        re.DOTALL)
    stream_data_schema = validate.Schema(
        validate.transform(stream_re.search),
        validate.any(
            None,
            validate.all(
                validate.get("data"), validate.transform(unquote),
                validate.transform(lambda x: x.replace("&quot;", '"')),
                validate.transform(json.loads),
                {"ht_stream_m3u8": validate.url()},
                validate.get("ht_stream_m3u8"))))

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

    def _get_streams(self):
        res = http.get(self.url)
        stream_url = self.stream_data_schema.validate(res.text)
        if stream_url:
            return HLSStream.parse_variant_playlist(self.session, stream_url)
Exemplo n.º 16
0
class PowerApp(Plugin):
    url_re = re.compile(r"https?://(?:www.)?powerapp.com.tr/tv/(\w+)")
    api_url = "http://api.powergroup.com.tr/Channels/{0}/?appRef=iPowerWeb&apiVersion=11"
    api_schema = validate.Schema(
        validate.all(
            {
                "errorCode": 0,
                "response": {
                    "channel_stream_url": validate.url()
                }
            }, validate.get("response")))

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

    def _get_streams(self):
        channel = self.url_re.match(self.url).group(1)

        res = http.get(self.api_url.format(channel))
        data = http.json(res, schema=self.api_schema)

        return HLSStream.parse_variant_playlist(self.session,
                                                data["channel_stream_url"])
Exemplo n.º 17
0
class ovvaTV(Plugin):
    url_re = re.compile(r"https?://(?:www\.)?1plus1\.video/tvguide/embed/[^/]")
    data_re = re.compile(r"""ovva-player["'],["'](.*?)["']\)};""")
    next_date_re = re.compile(
        r"""<div\sclass=["']o-message-timer['"]\sdata-timer=["'](\d+)["']""")
    ovva_data_schema = validate.Schema({"balancer": validate.url()},
                                       validate.get("balancer"))
    ovva_redirect_schema = validate.Schema(
        validate.all(validate.transform(lambda x: x.split("=")),
                     ['302', validate.url()], validate.get(1)))

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

    def _get_streams(self):
        res = http.get(self.url)
        data = self.data_re.search(res.text)
        next_date = self.next_date_re.search(res.text)
        if data:
            try:
                ovva_url = parse_json(b64decode(data.group(1)).decode("utf8"),
                                      schema=self.ovva_data_schema)
                stream_url = http.get(ovva_url,
                                      schema=self.ovva_redirect_schema)
            except PluginError as e:
                self.logger.error("Could not find stream URL: {0}", e)
            else:
                return HLSStream.parse_variant_playlist(
                    self.session, stream_url)
        elif next_date:
            self.logger.info("The broadcast will be available at {0}".format(
                datetime.fromtimestamp(int(
                    next_date.group(1))).strftime('%Y-%m-%d %H:%M:%S')))
        else:
            self.logger.error("Could not find player data.")
Exemplo n.º 18
0
}

BALANCER_URL = "http://www.mips.tv:1935/loadbalancer"
PLAYER_URL = "http://mips.tv/embedplayer/{0}/1/500/400"
SWF_URL = "http://mips.tv/content/scripts/eplayer.swf"

_url_re = re.compile(r"http(s)?://(\w+.)?mips.tv/(?P<channel>[^/&?]+)")
_flashvars_re = re.compile(r"'FlashVars', '([^']+)'")
_rtmp_re = re.compile(r"redirect=(.+)")

_schema = validate.Schema(
    validate.transform(_flashvars_re.search),
    validate.any(
        None,
        validate.all(validate.get(1), validate.transform(parse_query), {
            "id": validate.transform(int),
            validate.optional("s"): validate.text
        })))
_rtmp_schema = validate.Schema(
    validate.transform(_rtmp_re.search),
    validate.get(1),
)


class Mips(Plugin):
    @classmethod
    def can_handle_url(self, url):
        return _url_re.match(url)

    @Plugin.broken()
    def _get_streams(self):
        match = _url_re.match(self.url)
Exemplo n.º 19
0
class Rtve(Plugin):
    secret_key = base64.b64decode("eWVMJmRhRDM=")
    content_id_re = re.compile(r'data-id\s*=\s*"(\d+)"')
    url_re = re.compile(
        r"""
        https?://(?:www\.)?rtve\.es/(?:directo|noticias|television|deportes|alacarta|drmn)/.*?/?
    """, re.VERBOSE)
    cdn_schema = validate.Schema(
        validate.transform(partial(parse_xml, invalid_char_entities=True)),
        validate.xml_findall(".//preset"), [
            validate.union({
                "quality":
                validate.all(validate.getattr("attrib"), validate.get("type")),
                "urls":
                validate.all(validate.xml_findall(".//url"),
                             [validate.getattr("text")])
            })
        ])
    subtitles_api = "http://www.rtve.es/api/videos/{id}/subtitulos.json"
    subtitles_schema = validate.Schema(
        {"page": {
            "items": [{
                "src": validate.url(),
                "lang": validate.text
            }]
        }}, validate.get("page"), validate.get("items"))
    video_api = "http://www.rtve.es/api/videos/{id}.json"
    video_schema = validate.Schema(
        {
            "page": {
                "items": [{
                    "qualities": [{
                        "preset": validate.text,
                        "height": int
                    }]
                }]
            }
        }, validate.get("page"), validate.get("items"), validate.get(0))
    options = PluginOptions({"mux_subtitles": False})

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

    def __init__(self, url):
        Plugin.__init__(self, url)
        self.zclient = ZTNRClient(self.secret_key)
        http.headers = {"User-Agent": useragents.SAFARI_8}

    def _get_content_id(self):
        res = http.get(self.url)
        m = self.content_id_re.search(res.text)
        return m and int(m.group(1))

    def _get_subtitles(self, content_id):
        res = http.get(self.subtitles_api.format(id=content_id))
        return http.json(res, schema=self.subtitles_schema)

    def _get_quality_map(self, content_id):
        res = http.get(self.video_api.format(id=content_id))
        data = http.json(res, schema=self.video_schema)
        qmap = {}
        for item in data["qualities"]:
            qname = {
                "MED": "Media",
                "HIGH": "Alta",
                "ORIGINAL": "Original"
            }.get(item["preset"], item["preset"])
            qmap[qname] = u"{0}p".format(item["height"])
        return qmap

    def _get_streams(self):
        streams = []
        content_id = self._get_content_id()
        if content_id:
            self.logger.debug("Found content with id: {0}", content_id)
            stream_data = self.zclient.get_cdn_list(content_id,
                                                    schema=self.cdn_schema)
            quality_map = None

            for stream in stream_data:
                for url in stream["urls"]:
                    if url.endswith("m3u8"):
                        try:
                            streams.extend(
                                HLSStream.parse_variant_playlist(
                                    self.session, url).items())
                        except (IOError, OSError):
                            self.logger.debug("Failed to load m3u8 url: {0}",
                                              url)
                    elif ((url.endswith("mp4") or url.endswith("mov")
                           or url.endswith("avi"))
                          and http.head(
                              url, raise_for_status=False).status_code == 200):
                        if quality_map is None:  # only make the request when it is necessary
                            quality_map = self._get_quality_map(content_id)
                        # rename the HTTP sources to match the HLS sources
                        quality = quality_map.get(stream["quality"],
                                                  stream["quality"])
                        streams.append((quality, HTTPStream(self.session,
                                                            url)))

            subtitles = None
            if self.get_option("mux_subtitles"):
                subtitles = self._get_subtitles(content_id)
            if subtitles:
                substreams = {}
                for i, subtitle in enumerate(subtitles):
                    substreams[subtitle["lang"]] = HTTPStream(
                        self.session, subtitle["src"])

                for q, s in streams:
                    yield q, MuxedStream(self.session, s, subtitles=substreams)
            else:
                for s in streams:
                    yield s
Exemplo n.º 20
0
def parse_fmt_list(formatsmap):
    formats = {}
    if not formatsmap:
        return formats

    for format in formatsmap.split(","):
        s = format.split("/")
        (w, h) = s[1].split("x")
        formats[int(s[0])] = "{0}p".format(h)

    return formats


_config_schema = validate.Schema({
    validate.optional("fmt_list"):
    validate.all(validate.text, validate.transform(parse_fmt_list)),
    validate.optional("url_encoded_fmt_stream_map"):
    validate.all(validate.text, validate.transform(parse_stream_map), [{
        "itag":
        validate.all(validate.text, validate.transform(int)),
        "quality":
        validate.text,
        "url":
        validate.url(scheme="http"),
        validate.optional("s"):
        validate.text,
        validate.optional("stereo3d"):
        validate.all(validate.text, validate.transform(int),
                     validate.transform(bool)),
    }]),
    validate.optional("adaptive_fmts"):
Exemplo n.º 21
0
        /
        (?P<clip_name>[\w]+)
    )?
""", re.VERBOSE)

_access_token_schema = validate.Schema(
    {
        "token": validate.text,
        "sig": validate.text
    }, validate.union((validate.get("sig"), validate.get("token"))))
_token_schema = validate.Schema(
    {
        "chansub": {
            "restricted_bitrates":
            validate.all([validate.text],
                         validate.filter(lambda n: not re.match(
                             r"(.+_)?archives|live|chunked", n)))
        }
    }, validate.get("chansub"))
_user_schema = validate.Schema(
    {validate.optional("display_name"): validate.text},
    validate.get("display_name"))
_video_schema = validate.Schema({
    "chunks": {
        validate.text: [{
            "length": int,
            "url": validate.any(None, validate.url(scheme="http")),
            "upkeep": validate.any("pass", "fail", None)
        }]
    },
    "restrictions": {
Exemplo n.º 22
0
class Looch(Plugin):
    url_re = re.compile(
        r"https?://(?:www\.)?looch\.tv/channel/(?P<name>[^/]+)(/videos/(?P<video_id>\d+))?"
    )

    api_base = "https://api.looch.tv"
    channel_api = api_base + "/channels/{name}"
    video_api = api_base + "/videos/{id}"

    playback_schema = validate.Schema({"weight": int, "uri": validate.url()})
    data_schema = validate.Schema({
        "type": validate.text,
        "attributes": {
            validate.optional("playback"): [playback_schema],
            validate.optional("resolution"): {
                "width": int,
                "height": int
            }
        }
    })
    channel_schema = validate.Schema(
        validate.transform(parse_json), {
            "included":
            validate.all(
                [data_schema],
                validate.filter(lambda x: x["type"] == "active_streams"),
                validate.map(lambda x: x["attributes"].get("playback")),
                validate.transform(lambda x: list(itertools.chain(*x)))),
        }, validate.get("included"))
    video_schema = validate.Schema(validate.transform(parse_json),
                                   {"data": data_schema}, validate.get("data"),
                                   validate.get("attributes"))

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

    def _get_live_stream(self, channel):
        url = self.channel_api.format(name=channel)
        self.logger.debug("Channel API call: {0}", url)
        data = http.get(url, schema=self.channel_schema)
        self.logger.debug("Got {0} channel playback items", len(data))
        for playback in data:
            for s in HLSStream.parse_variant_playlist(self.session,
                                                      playback["uri"]).items():
                yield s

    def _get_video_stream(self, video_id):
        url = self.video_api.format(id=video_id)
        self.logger.debug("Video API call: {0}", url)
        data = http.get(url, schema=self.video_schema)
        self.logger.debug("Got video {0} playback items",
                          len(data["playback"]))
        res = data["resolution"]["height"]
        for playback in data["playback"]:
            yield "{0}p".format(res), HTTPStream(self.session, playback["uri"])

    def _get_streams(self):
        match = self.url_re.match(self.url)
        self.logger.debug("Matched URL: name={name}, video_id={video_id}",
                          **match.groupdict())

        if match.group("video_id"):
            return self._get_video_stream(match.group("video_id"))
        elif match.group("name"):
            return self._get_live_stream(match.group("name"))
Exemplo n.º 23
0
    "error": bool,
    validate.optional("code"): validate.text,
    validate.optional("message"): validate.text,
    validate.optional("data"): object,
})
_media_schema = validate.Schema(
    {
        "stream_data":
        validate.any(
            None, {
                "streams":
                validate.all([{
                    "quality":
                    validate.any(validate.text, None),
                    "url":
                    validate.url(scheme="http",
                                 path=validate.endswith(".m3u8")),
                    validate.optional("video_encode_id"):
                    validate.text
                }])
            })
    }, validate.get("stream_data"))
_login_schema = validate.Schema({
    "auth":
    validate.text,
    "expires":
    validate.all(validate.text, validate.transform(parse_timestamp)),
    "user": {
        "username": validate.any(validate.text, None),
        "email": validate.text
    }
Exemplo n.º 24
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([{
        u"src":
        validate.any(
            validate.contains("m3u8"),
            validate.all(
                validate.text,
                validate.transform(lambda x: WebTV.decrypt_stream_url(x)),
                validate.contains("m3u8"))),
        u"type":
        validate.text,
        u"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 = crypto_AES.new(binascii.unhexlify(data[32:96]),
                                   crypto_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 = 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:
                self.logger.debug("Found stream of type: {}", source[u'type'])
                if source[u'type'] == u"application/vnd.apple.mpegurl":
                    url = update_scheme(self.url, source[u"src"])

                    try:
                        # try to parse the stream as a variant playlist
                        variant = HLSStream.parse_variant_playlist(
                            self.session, url, headers=headers)
                        if variant:
                            for q, s in variant.items():
                                yield q, s
                        else:
                            # and if that fails, try it as a plain HLS stream
                            yield 'live', HLSStream(self.session,
                                                    url,
                                                    headers=headers)
                    except IOError:
                        self.logger.warning(
                            "Could not open the stream, perhaps the channel is offline"
                        )
Exemplo n.º 25
0
    ],
    "geo_blocked": [],
    "notes": "",
    "live": True,
    "vod": True,
    "last_update": "2017-02-09",
}

_url_re = re.compile(r"https?://(?:www\.)?openrec.tv/(live|movie)/")
_playlist_url_re = re.compile(r"data-(source)?file=\"(?P<url>[^\"]+)\"")
_movie_data_re = re.compile(r'''<script type="application/ld\+json">(.*?)</script>''', re.DOTALL | re.M)
_live_schema = validate.Schema(
    validate.transform(_playlist_url_re.findall),
    [
        validate.union({
            "isSource": validate.all(validate.get(0), validate.transform(lambda s: s == "source")),
            "url": validate.all(validate.get(1), validate.url(scheme="http",
                                                              path=validate.endswith(".m3u8")))
        })
    ]
)
_movie_schema = validate.Schema(
    validate.transform(_movie_data_re.search),
    validate.any(
        None,
        validate.all(
            validate.get(1),
            validate.transform(parse_json),
            validate.get("contentUrl")
        )
    )
Exemplo n.º 26
0
 def test_list(self):
     assert validate([1, 0], [1, 0, 1, 1]) == [1, 0, 1, 1]
     assert validate([1, 0], []) == []
     assert validate(all([0, 1], lambda l: len(l) > 2),
                     [0, 1, 0]) == [0, 1, 0]
Exemplo n.º 27
0
    def test_all(self):
        assert validate(all(int, lambda n: 0 < n < 5), 3) == 3

        assert validate(all(transform(int), lambda n: 0 < n < 5), 3.33) == 3
Exemplo n.º 28
0
    "vod": True,
    "last_update": "2017-03-26",
}

_url_re = re.compile(
    r"""
    https?://(\w+\.)?aliez.\w+/
    (?:live/[^/]+|video/\d+/[^/]+)
""", re.VERBOSE)
_file_re = re.compile(r"\"?file\"?:\s+['\"]([^'\"]+)['\"]")
_swf_url_re = re.compile(r"swfobject.embedSWF\(\"([^\"]+)\",")

_schema = validate.Schema(
    validate.union({
        "urls":
        validate.all(validate.transform(_file_re.findall),
                     validate.map(unquote), [validate.url()]),
        "swf":
        validate.all(
            validate.transform(_swf_url_re.search),
            validate.any(
                None,
                validate.all(
                    validate.get(1),
                    validate.url(scheme="http",
                                 path=validate.endswith("swf")))))
    }))


class Aliez(Plugin):
    @classmethod
    def can_handle_url(self, url):
Exemplo n.º 29
0
class IDF1(Plugin):
    DACAST_API_URL = 'https://json.dacast.com/b/{}/{}/{}'
    DACAST_TOKEN_URL = 'https://services.dacast.com/token/i/b/{}/{}/{}'

    _url_re = re.compile(
        r'http://www\.idf1\.fr/(videos/[^/]+/[^/]+\.html|live\b)')
    _video_id_re = re.compile(
        r"dacast\('(?P<broadcaster_id>\d+)_(?P<video_type>[a-z]+)_(?P<video_id>\d+)', 'replay_content', data\);"
    )
    _video_id_alt_re = re.compile(
        r'<script src="//player.dacast.com/js/player.js" id="(?P<broadcaster_id>\d+)_(?P<video_type>[cf])_(?P<video_id>\d+)"'
    )
    _player_url = 'http://ssl.p.jwpcdn.com/player/v/7.12.6/jwplayer.flash.swf'

    _api_schema = validate.Schema(
        validate.transform(parse_json), {
            validate.optional('html5'): validate.all([
                {
                    'src': validate.url()
                },
            ], ),
            'hls': validate.url(),
            'hds': validate.url()
        },
        validate.transform(
            lambda x: [update_scheme(IDF1.DACAST_API_URL, x['hls']), x['hds']
                       ] + [y['src'] for y in x.get('html5', [])]))

    _token_schema = validate.Schema(validate.transform(parse_json),
                                    {'token': validate.text},
                                    validate.get('token'))

    _user_agent = useragents.IE_11

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

    def _get_streams(self):
        res = http.get(self.url)
        match = self._video_id_re.search(
            res.text) or self._video_id_alt_re.search(res.text)
        if match is None:
            return
        broadcaster_id = match.group('broadcaster_id')
        video_type = match.group('video_type')
        video_id = match.group('video_id')

        videos = http.get(self.DACAST_API_URL.format(broadcaster_id,
                                                     video_type, video_id),
                          schema=self._api_schema)
        token = http.get(self.DACAST_TOKEN_URL.format(broadcaster_id,
                                                      video_type, video_id),
                         schema=self._token_schema)
        parsed = []

        for video_url in videos:
            video_url += token

            # Ignore duplicate video URLs
            if video_url in parsed:
                continue
            parsed.append(video_url)

            # Ignore HDS streams (broken)
            if '.m3u8' in video_url:
                for s in HLSStream.parse_variant_playlist(
                        self.session, video_url).items():
                    yield s
Exemplo n.º 30
0
HUAJIAO_URL = "http://www.huajiao.com/l/{}"
LAPI_URL = "http://g2.live.360.cn/liveplay?stype=flv&channel={}&bid=huajiao&sn={}&sid={}&_rate=xd&ts={}&r={}&_ostype=flash&_delay=0&_sign=null&_ver=13"

_url_re = re.compile(
    r"""
        http(s)?://(www\.)?huajiao.com
        /l/(?P<channel>[^/]+)
""", re.VERBOSE)

_feed_json_re = re.compile(r'^\s*var\s*feed\s*=\s*(?P<feed>{.*})\s*;',
                           re.MULTILINE)

_feed_json_schema = validate.Schema(
    validate.all(
        validate.transform(_feed_json_re.search),
        validate.any(
            None,
            validate.all(validate.get('feed'),
                         validate.transform(json.loads)))))


class Huajiao(Plugin):
    @classmethod
    def can_handle_url(self, url):
        return _url_re.match(url)

    def _get_streams(self):
        match = _url_re.match(self.url)
        channel = match.group("channel")

        http.headers.update({"User-Agent": USER_AGENT})
        http.verify = False