Ejemplo n.º 1
0
 def test_dict_optional_keys(self):
     assert validate({"a": 1, optional("b"): 2}, {"a": 1}) == {"a": 1}
     assert validate({
         "a": 1,
         optional("b"): 2
     }, {
         "a": 1,
         "b": 2
     }) == {
         "a": 1,
         "b": 2
     }
Ejemplo n.º 2
0
class Euronews(Plugin):
    _url_re = re.compile(r"http(?:s)?://(\w+)\.?euronews.com/(live|.*)")
    _re_vod = re.compile(
        r'<meta\s+property="og:video"\s+content="(http.*?)"\s*/>')
    _live_api_url = "http://{0}.euronews.com/api/watchlive.json"
    _live_schema = validate.Schema({u"url": validate.url()})
    _stream_api_schema = validate.Schema({
        u'status':
        u'ok',
        u'primary':
        validate.url(),
        validate.optional(u'backup'):
        validate.url()
    })

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

    def _get_vod_stream(self):
        """
        Find the VOD video url
        :return: video url
        """
        res = http.get(self.url)
        video_urls = self._re_vod.findall(res.text)
        if len(video_urls):
            return dict(vod=HTTPStream(self.session, video_urls[0]))

    def _get_live_streams(self, subdomain):
        """
        Get the live stream in a particular language
        :param subdomain:
        :return:
        """
        res = http.get(self._live_api_url.format(subdomain))
        live_res = http.json(res, schema=self._live_schema)
        api_res = http.get(live_res[u"url"])
        stream_data = http.json(api_res, schema=self._stream_api_schema)
        return HLSStream.parse_variant_playlist(self.session,
                                                stream_data[u'primary'])

    def _get_streams(self):
        """
        Find the streams for euronews
        :return:
        """
        match = self._url_re.match(self.url)
        subdomain, path = match.groups()

        if path == "live":
            return self._get_live_streams(subdomain)
        else:
            return self._get_vod_stream()
Ejemplo n.º 3
0
class Aftonbladet(Plugin):
    """Plugin for swedish news paper Aftonbladet's streaming service."""

    _url_re = re.compile(
        r"https?://tv\.aftonbladet\.se/[^/]+/[^/]+/(?P<id>\d+)")

    api_url = "https://svp.vg.no/svp/api/v1/ab/assets/{0}?appName=svp-player"

    _video_schema = validate.Schema({
        validate.optional("title"): validate.text,
        validate.optional("assetType"): validate.text,
        validate.optional("streamType"): validate.text,
        validate.optional("status"): validate.text,
        "streamUrls": {
            validate.optional("hls"): validate.any(validate.text, None),
            validate.optional("hds"): validate.any(validate.text, None),
            validate.optional("mp4"): validate.any(validate.text, None),
        },
    })

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

    def _get_streams(self):
        m_url = self._url_re.match(self.url)
        if not m_url:
            return

        video_id = m_url.group("id")

        headers = {"User-Agent": useragents.FIREFOX, "Referer": self.url}

        res = http.get(self.api_url.format(video_id), headers=headers)
        data = http.json(res, schema=self._video_schema)

        title = data.get("title")
        streamurls = data.get("streamUrls")

        if title:
            self.stream_title = title

        if streamurls:
            hls_url = streamurls.get("hls")
            if hls_url:
                streams = HLSStream.parse_variant_playlist(
                    self.session, hls_url, headers=headers).items()
                if not streams:
                    yield "live", HLSStream(self.session,
                                            hls_url,
                                            headers=headers)
                for s in streams:
                    yield s

            hds_url = streamurls.get("hds")
            if hds_url:
                for s in HDSStream.parse_manifest(self.session,
                                                  hds_url,
                                                  headers=headers).items():
                    yield s

            mp4_url = streamurls.get("mp4")
            if mp4_url:
                name = "live"
                yield name, HTTPStream(self.session, mp4_url, headers=headers)
Ejemplo n.º 4
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)
Ejemplo n.º 5
0
_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": {
        validate.text: validate.text
    },
    "start_offset": int,
    "end_offset": int,
})
Ejemplo n.º 6
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(
Ejemplo n.º 7
0
class Dogan(Plugin):
    """
    Support for the live streams from Doğan Media Group channels
    """
    url_re = re.compile(
        r"""
        https?://(?:www.)?
        (?:teve2.com.tr/(?:canli-yayin|filmler/.*|programlar/.*)|
           kanald.com.tr/.*|
           cnnturk.com/canli-yayin|
           dreamtv.com.tr/canli-yayin|
           dreamturk.com.tr/canli)
    """, re.VERBOSE)
    playerctrl_re = re.compile(
        r'''<div[^>]*?ng-controller=(?P<quote>["'])(?:Live)?PlayerCtrl(?P=quote).*?>''',
        re.DOTALL)
    videoelement_re = re.compile(
        r'''<div[^>]*?id=(?P<quote>["'])video-element(?P=quote).*?>''',
        re.DOTALL)
    data_id_re = re.compile(
        r'''data-id=(?P<quote>["'])(?P<id>\w+)(?P=quote)''')
    content_id_re = re.compile(r'"content(?:I|i)d", "(\w+)"')
    content_api = "/actions/content/media/{id}"
    new_content_api = "/action/media/{id}"
    content_api_schema = validate.Schema({
        "Id": validate.text,
        "Media": {
            "Link": {
                "DefaultServiceUrl": validate.url(),
                validate.optional("ServiceUrl"):
                validate.any(validate.url(), ""),
                "SecurePath": validate.text,
            }
        }
    })

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

    def _get_content_id(self):
        res = http.get(self.url)
        # find the contentId
        content_id_m = self.content_id_re.search(res.text)
        if content_id_m:
            return content_id_m.group(1)

        # find the PlayerCtrl div
        player_ctrl_m = self.playerctrl_re.search(res.text)
        if player_ctrl_m:
            # extract the content id from the player control data
            player_ctrl_div = player_ctrl_m.group(0)
            content_id_m = self.data_id_re.search(player_ctrl_div)
            if content_id_m:
                return content_id_m.group("id")

        # find <div id="video-element"
        videoelement_m = self.videoelement_re.search(res.text)
        if videoelement_m:
            # extract the content id from the player control data
            videoelement_div = videoelement_m.group(0)
            content_id_m = self.data_id_re.search(videoelement_div)
            if content_id_m:
                return content_id_m.group("id")

    def _get_hls_url(self, content_id):
        # make the api url relative to the current domain
        if "cnnturk" in self.url or "teve2.com.tr" in self.url:
            self.logger.debug("Using new content API url")
            api_url = urljoin(self.url,
                              self.new_content_api.format(id=content_id))
        else:
            api_url = urljoin(self.url, self.content_api.format(id=content_id))

        apires = http.get(api_url)

        stream_data = http.json(apires, schema=self.content_api_schema)
        d = stream_data["Media"]["Link"]
        return urljoin((d["ServiceUrl"] or d["DefaultServiceUrl"]),
                       d["SecurePath"])

    def _get_streams(self):
        content_id = self._get_content_id()
        if content_id:
            self.logger.debug(u"Loading content: {}", content_id)
            hls_url = self._get_hls_url(content_id)
            return HLSStream.parse_variant_playlist(self.session, hls_url)
        else:
            self.logger.error(u"Could not find the contentId for this stream")
Ejemplo n.º 8
0
Archivo: vgtv.py Proyecto: thawtes/ipk
class VGTV(Plugin):
    """
        Plugin for VGTV, Norwegian newspaper VG Nett's streaming service.
        Plugin for swedish news paper Aftonbladet's streaming service.
    """

    _url_re = re.compile(r"""https?://(?:www\.)?
        (?P<host>
            tv\.aftonbladet\.se/abtv
            |
            (?:ap\.)?vgtv\.no
        )
        (?:/webtv(?:[^/]+)?)?
        /[^/]+/(?P<id>\d+)
        """, re.VERBOSE)

    appname_map = {
        "ap.vgtv.no": "aptv",
        "tv.aftonbladet.se/abtv": "abtv",
        "vgtv.no": "vgtv",
    }

    apiname_map = {
        "abtv": "ab",
        "aptv": "ap",
        "vgtv": "vgtv",
    }

    api_url = "https://svp.vg.no/svp/api/v1/{0}/assets/{1}?appName={2}-website"

    _video_schema = validate.Schema(
        {
            validate.optional("title"): validate.text,
            validate.optional("assetType"): validate.text,
            validate.optional("streamType"): validate.text,
            validate.optional("status"): validate.text,
            "streamUrls": {
                validate.optional("hls"): validate.any(validate.text, None),
                validate.optional("hds"): validate.any(validate.text, None),
                validate.optional("mp4"): validate.any(validate.text, None),
            },
        }
    )

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

    def _get_streams(self):
        m_url = self._url_re.match(self.url)
        if not m_url:
            return

        video_id = m_url.group("id")
        appname = self.appname_map[m_url.group("host")]
        apiname = self.apiname_map[appname]

        headers = {
            "User-Agent": useragents.FIREFOX,
            "Referer": self.url
        }

        res = http.get(self.api_url.format(apiname, video_id, appname), headers=headers)
        data = http.json(res, schema=self._video_schema)

        title = data.get("title")
        streamurls = data.get("streamUrls")

        if title:
            self.stream_title = title

        if streamurls:
            hls_url = streamurls.get("hls")
            if hls_url:
                self.logger.debug("HLS URL: {0}".format(hls_url))
                streams = HLSStream.parse_variant_playlist(self.session, hls_url, headers=headers).items()
                if not streams:
                    yield "live", HLSStream(self.session, hls_url, headers=headers)
                for s in streams:
                    yield s

            hds_url = streamurls.get("hds")
            if hds_url:
                self.logger.debug("HDS URL: {0}".format(hds_url))
                for s in HDSStream.parse_manifest(self.session, hds_url, headers=headers).items():
                    yield s

            mp4_url = streamurls.get("mp4")
            if mp4_url:
                self.logger.debug("MP4 URL: {0}".format(mp4_url))
                name = "live"
                yield name, HTTPStream(self.session, mp4_url, headers=headers)
Ejemplo n.º 9
0
class LiveEdu(Plugin):
    login_url = "https://www.liveedu.tv/accounts/login/"
    url_re = re.compile(r"https?://(?:\w+\.)?(?:livecoding|liveedu)\.tv/")
    config_re = re.compile(
        r"""\Wconfig.(?P<key>\w+)\s*=\s*(?P<q>['"])(?P<value>.*?)(?P=q);""")
    csrf_re = re.compile(r'''"csrfToken"\s*:\s*"(\w+)"''')
    api_schema = validate.Schema({
        "viewing_urls": {
            validate.optional("error"):
            validate.text,
            validate.optional("urls"): [{
                "src":
                validate.url(),
                "type":
                validate.text,
                validate.optional("res"):
                int,
                validate.optional("label"):
                validate.text,
            }]
        }
    })
    config_schema = validate.Schema({
        "selectedVideoHID": validate.text,
        "livestreamURL": validate.text,
        "videosURL": validate.text
    })

    options = PluginOptions({"email": None, "password": None})

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

    def login(self):
        """
        Attempt a login to LiveEdu.tv
        """
        email = self.get_option("email")
        password = self.get_option("password")

        if email and password:
            res = http.get(self.login_url)
            csrf_match = self.csrf_re.search(res.text)
            token = csrf_match and csrf_match.group(1)
            self.logger.debug("Attempting login as {0} (token={1})", email,
                              token)

            res = http.post(self.login_url,
                            data=dict(login=email,
                                      password=password,
                                      csrfmiddlewaretoken=token),
                            allow_redirects=False,
                            raise_for_status=False,
                            headers={"Referer": self.login_url})

            if res.status_code != 302:
                self.logger.error("Failed to login to LiveEdu account: {0}",
                                  email)

    def _get_streams(self):
        """
        Get the config object from the page source and call the
        API to get the list of streams
        :return:
        """
        # attempt a login
        self.login()

        res = http.get(self.url)
        # decode the config for the page
        matches = self.config_re.finditer(res.text)
        try:
            config = self.config_schema.validate(
                dict([m.group("key", "value") for m in matches]))
        except PluginError:
            return

        if config["selectedVideoHID"]:
            self.logger.debug("Found video hash ID: {0}",
                              config["selectedVideoHID"])
            api_url = urljoin(
                self.url,
                urljoin(config["videosURL"], config["selectedVideoHID"]))
        elif config["livestreamURL"]:
            self.logger.debug("Found live stream URL: {0}",
                              config["livestreamURL"])
            api_url = urljoin(self.url, config["livestreamURL"])
        else:
            return

        ares = http.get(api_url)
        data = http.json(ares, schema=self.api_schema)
        viewing_urls = data["viewing_urls"]

        if "error" in viewing_urls:
            self.logger.error("Failed to load streams: {0}",
                              viewing_urls["error"])
        else:
            for url in viewing_urls["urls"]:
                try:
                    label = "{0}p".format(url.get("res", url["label"]))
                except KeyError:
                    label = "live"

                if url["type"] == "rtmp/mp4" and RTMPStream.is_usable(
                        self.session):
                    params = {
                        "rtmp": url["src"],
                        "pageUrl": self.url,
                        "live": True,
                    }
                    yield label, RTMPStream(self.session, params)

                elif url["type"] == "application/x-mpegURL":
                    for s in HLSStream.parse_variant_playlist(
                            self.session, url["src"]).items():
                        yield s
Ejemplo n.º 10
0
    "vod": True,
    "last_update": "2017-05-03",
}

MEDIA_URL = "http://www.ardmediathek.de/play/media/{0}"
SWF_URL = "http://www.ardmediathek.de/ard/static/player/base/flash/PluginFlash.swf"
HDCORE_PARAMETER = "?hdcore=3.3.0"
QUALITY_MAP = {"auto": "auto", 3: "544p", 2: "360p", 1: "288p", 0: "144p"}

_url_re = re.compile(
    r"http(s)?://(?:(\w+\.)?ardmediathek.de/tv|mediathek.daserste.de/)")
_media_id_re = re.compile(r"/play/(?:media|config)/(\d+)")
_media_schema = validate.Schema({
    "_mediaArray": [{
        "_mediaStreamArray": [{
            validate.optional("_server"):
            validate.text,
            "_stream":
            validate.any(validate.text, [validate.text]),
            "_quality":
            validate.any(int, validate.text)
        }]
    }]
})
_smil_schema = validate.Schema(
    validate.union({
        "base":
        validate.all(validate.xml_find("head/meta"), validate.get("base"),
                     validate.url(scheme="http")),
        "cdn":
        validate.all(validate.xml_find("head/meta"), validate.get("cdn")),
Ejemplo n.º 11
0
class OKru(Plugin):
    """Livecli Plugin for ok.ru"""

    _data_re = re.compile(
        r"""data-options=(?P<q>["'])(?P<data>{[^"']+})(?P=q)""")
    _url_re = re.compile(r"""https?://(?:www\.)?ok\.ru/""")

    _metadata_schema = validate.Schema(
        validate.transform(parse_json),
        validate.any(
            {
                "videos":
                validate.any([], [{
                    "name": validate.text,
                    "url": validate.text,
                }]),
                validate.optional("hlsManifestUrl"):
                validate.text,
                validate.optional("hlsMasterPlaylistUrl"):
                validate.text,
                validate.optional("liveDashManifestUrl"):
                validate.text,
                validate.optional("rtmpUrl"):
                validate.text,
            }, None))

    _data_schema = validate.Schema(
        validate.all(
            validate.transform(_data_re.search), validate.get("data"),
            validate.transform(unescape), validate.transform(parse_json),
            validate.get("flashvars"),
            validate.any({"metadata": _metadata_schema},
                         {"metadataUrl": validate.transform(unquote)}, None)))

    QUALITY_WEIGHTS = {
        "full": 1080,
        "1080": 1080,
        "hd": 720,
        "720": 720,
        "sd": 480,
        "480": 480,
        "360": 360,
        "low": 360,
        "lowest": 240,
        "mobile": 144,
    }

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

    @classmethod
    def stream_weight(cls, key):
        weight = cls.QUALITY_WEIGHTS.get(key)
        if weight:
            return weight, "okru"

        return Plugin.stream_weight(key)

    def _get_streams(self):
        headers = {"User-Agent": useragents.FIREFOX, "Referer": self.url}
        data = http.get(self.url, headers=headers, schema=self._data_schema)
        metadata = data.get("metadata")
        metadata_url = data.get("metadataUrl")
        if metadata_url:
            metadata = http.post(metadata_url,
                                 headers=headers,
                                 schema=self._metadata_schema)

        if metadata:
            list_hls = [
                metadata.get("hlsManifestUrl"),
                metadata.get("hlsMasterPlaylistUrl"),
            ]
            for hls_url in list_hls:
                if hls_url is not None:
                    for s in HLSStream.parse_variant_playlist(
                            self.session, hls_url, headers=headers).items():
                        yield s

            if metadata.get("videos"):
                for http_stream in metadata.get("videos"):
                    http_name = http_stream["name"]
                    http_url = http_stream["url"]
                    yield http_name, HTTPStream(self.session,
                                                http_url,
                                                headers=headers)

            if metadata.get("rtmpUrl"):
                yield "live", RTMPStream(
                    self.session, params={"rtmp": metadata.get("rtmpUrl")})
Ejemplo n.º 12
0
_room_id_re = re.compile(r'"roomId":(?P<room_id>\d+),')
_room_id_alt_re = re.compile(
    r'content="showroom:///room\?room_id=(?P<room_id>\d+)"')
_room_id_lookup_failure_log = 'Failed to find room_id for {0} using {1} regex'

_api_status_url = 'https://www.showroom-live.com/room/is_live?room_id={room_id}'
_api_stream_url = 'https://www.showroom-live.com/api/live/streaming_url?room_id={room_id}'

_api_stream_schema = validate.Schema(
    validate.any(
        {
            "streaming_url_list":
            validate.all([{
                "url": validate.text,
                validate.optional("stream_name"): validate.text,
                "id": int,
                "label": validate.text,
                "is_default": int,
                "type": validate.text,
                "quality": int,
            }])
        }, {}))

# the "low latency" streams are rtmp, the others are hls
_rtmp_quality_lookup = {
    "オリジナル画質": "high",
    "オリジナル画質(低遅延)": "high",
    "original spec(low latency)": "high",
    "original spec": "high",
    "低画質": "low",
Ejemplo n.º 13
0
    http(s)?://(\w+\.)?
    dailymotion.com
    (?:
        (/embed)?/(video|live)
        /(?P<media_id>[^_?/]+)
    |
        /(?P<channel_name>[A-Za-z0-9-_]+)
    )
""", re.VERBOSE)
chromecast_re = re.compile(r'''stream_chromecast_url"\s*:\s*(?P<url>".*?")''')

_media_inner_schema = validate.Schema([{
    "layerList": [{
        "name":
        validate.text,
        validate.optional("sequenceList"): [{
            "layerList":
            validate.all([{
                "name": validate.text,
                validate.optional("param"): dict
            }],
                         validate.filter(lambda l: l["name"] in
                                         ("video", "reporting", "message")))
        }]
    }]
}])
_media_schema = validate.Schema(
    validate.any(
        _media_inner_schema,
        validate.all({"sequence": _media_inner_schema},
                     validate.get("sequence"))))
Ejemplo n.º 14
0
class OlympicChannel(Plugin):
    _url_re = re.compile(
        r"http(?:s)?://(\w+)\.?olympicchannel.com/../(?P<type>tv|playback)/(livestream-.\d|.*)/"
    )
    _live_api_url = "https://www.olympicchannel.com{0}api/v2/metadata/{1}"
    _stream_get_url = "https://www.olympicchannel.com/en/proxy/viewings/"
    _stream_api_schema = validate.Schema({
        u'status':
        u'ok',
        u'primary':
        validate.url(),
        validate.optional(u'backup'):
        validate.url()
    })

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

    def _get_vod_streams(self):
        page = http.get(self.url)
        asset = re.search(r'asse_.{32}', str(page._content)).group(0)
        post_data = '{"asset_url":"/api/assets/%s/"}' % asset
        stream_data = http.json(
            http.post(self._stream_get_url,
                      data=post_data))['objects'][0]['level3']['streaming_url']
        return HLSStream.parse_variant_playlist(self.session, stream_data)

    def _get_live_streams(self, lang, path):
        """
        Get the live stream in a particular language
        :param lang:
        :param path:
        :return:
        """
        res = http.get(self._live_api_url.format(lang, path))
        live_res = http.json(res)['default']['uid']
        post_data = '{"channel_url":"/api/channels/%s/"}' % live_res
        try:
            stream_data = http.json(
                http.post(self._stream_get_url, data=post_data))['stream_url']
        except BaseException:
            stream_data = http.json(
                http.post(self._stream_get_url, data=post_data))['channel_url']
        return HLSStream.parse_variant_playlist(self.session, stream_data)

    def _get_streams(self):
        """
        Find the streams for OlympicChannel
        :return:
        """
        match = self._url_re.match(self.url)
        type_of_stream = match.group('type')
        lang = re.search(r"/../", self.url).group(0)

        if type_of_stream == 'tv':
            path = re.search(r"tv/.*-\d/$", self.url).group(0)

            return self._get_live_streams(lang, path)
        elif type_of_stream == 'playback':
            path = re.search(r"/playback/.*/$", self.url).group(0)
            return self._get_vod_streams()
Ejemplo n.º 15
0
_flashvar_re = re.compile(r"""(['"])(.*?)\1\s*:\s*(['"])(.*?)\3""")
_clientlibs_re = re.compile(r"""<script.*?src=(['"])(.*?/clientlibs_anime_watch.*?\.js)\1""")

_schema = validate.Schema(
    validate.union({
        "flashvars": validate.all(
            validate.transform(_flashvars_re.search),
            validate.get(1),
            validate.transform(_flashvar_re.findall),
            validate.map(lambda v: (v[1], v[3])),
            validate.transform(dict),
            {
                "s": validate.text,
                "country": validate.text,
                "init": validate.text,
                validate.optional("ss_id"): validate.text,
                validate.optional("mv_id"): validate.text,
                validate.optional("device_cd"): validate.text,
                validate.optional("ss1_prm"): validate.text,
                validate.optional("ss2_prm"): validate.text,
                validate.optional("ss3_prm"): validate.text
            }
        ),
        "clientlibs": validate.all(
            validate.transform(_clientlibs_re.search),
            validate.get(2),
            validate.text
        )
    })
)
Ejemplo n.º 16
0
class AdultSwim(Plugin):
    API_URL = "http://www.adultswim.com/videos/api/v2/videos/{id}?fields=stream"
    vod_api = "http://www.adultswim.com/videos/api/v0/assets"

    url_re = re.compile(
        r"""https?://(?:www\.)?adultswim\.com/videos
            (?:/(streams))?
            (?:/([^/]+))?
            (?:/([^/]+))?
            """, re.VERBOSE)
    _stream_data_re = re.compile(r"(?:__)?AS_INITIAL_DATA(?:__)? = (\{.*?});",
                                 re.M | re.DOTALL)

    live_schema = validate.Schema({
        u"streams": {
            validate.text: {
                u"stream":
                validate.text,
                validate.optional(u"isLive"):
                bool,
                u"archiveEpisodes": [{
                    u"id": validate.text,
                    u"slug": validate.text,
                }]
            }
        }
    })
    vod_id_schema = validate.Schema(
        {u"show": {
            u"sluggedVideo": {
                u"id": validate.text
            }
        }}, validate.transform(lambda x: x["show"]["sluggedVideo"]["id"]))
    _api_schema = validate.Schema({
        u'status': u'ok',
        u'data': {
            u'stream': {
                u'assets': [{
                    u'url': validate.url()
                }]
            }
        }
    })
    _vod_api_schema = validate.Schema(
        validate.all(validate.xml_findall(".//files/file"), [
            validate.xml_element,
            validate.transform(lambda v: {
                "bitrate": v.attrib.get("bitrate"),
                "url": v.text
            })
        ]))

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

    def _make_hls_hds_stream(self, func, stream, *args, **kwargs):
        return func(self.session, stream["url"], *args, **kwargs)

    def _get_show_streams(self,
                          stream_data,
                          show,
                          episode,
                          platform="desktop"):
        video_id = parse_json(stream_data.group(1), schema=self.vod_id_schema)
        res = http.get(self.vod_api,
                       params={
                           "platform": platform,
                           "id": video_id
                       })

        # create a unique list of the stream manifest URLs
        streams = []
        urldups = []
        for stream in parse_xml(res.text, schema=self._vod_api_schema):
            if stream["url"] not in urldups:
                streams.append(stream)
                urldups.append(stream["url"])

        mapper = StreamMapper(lambda fmt, strm: strm["url"].endswith(fmt))
        mapper.map(".m3u8", self._make_hls_hds_stream,
                   HLSStream.parse_variant_playlist)
        mapper.map(".f4m",
                   self._make_hls_hds_stream,
                   HDSStream.parse_manifest,
                   is_akamai=True)
        mapper.map(
            ".mp4", lambda s:
            (s["bitrate"] + "k", HTTPStream(self.session, s["url"])))

        for q, s in mapper(streams):
            yield q, s

    def _get_live_stream(self, stream_data, show, episode=None):
        # parse the stream info as json
        stream_info = parse_json(stream_data.group(1), schema=self.live_schema)
        # get the stream ID
        stream_id = None
        show_info = stream_info[u"streams"][show]

        if episode:
            self.logger.debug("Loading replay of episode: {0}/{1}", show,
                              episode)
            for epi in show_info[u"archiveEpisodes"]:
                if epi[u"slug"] == episode:
                    stream_id = epi[u"id"]
        elif show_info.get("isLive") or not len(show_info[u"archiveEpisodes"]):
            self.logger.debug("Loading LIVE streams for: {0}", show)
            stream_id = show_info[u"stream"]
        else:  # off-air
            if len(show_info[u"archiveEpisodes"]):
                epi = show_info[u"archiveEpisodes"][0]
                self.logger.debug("Loading replay of episode: {0}/{1}", show,
                                  epi[u"slug"])
                stream_id = epi[u"id"]
            else:
                self.logger.error("This stream is currently offline")
                return

        if stream_id:
            api_url = self.API_URL.format(id=stream_id)

            res = http.get(api_url,
                           headers={"User-Agent": useragents.SAFARI_8})
            stream_data = http.json(res, schema=self._api_schema)

            mapper = StreamMapper(lambda fmt, surl: surl.endswith(fmt))
            mapper.map(".m3u8", HLSStream.parse_variant_playlist, self.session)
            mapper.map(".f4m", HDSStream.parse_manifest, self.session)

            stream_urls = [
                asset[u"url"]
                for asset in stream_data[u'data'][u'stream'][u'assets']
            ]
            for q, s in mapper(stream_urls):
                yield q, s

        else:
            self.logger.error(
                "Couldn't find the stream ID for this stream: {0}".format(
                    show))

    def _get_streams(self):
        # get the page
        url_match = self.url_re.match(self.url)
        live_stream, show_name, episode_name = url_match.groups()
        if live_stream:
            show_name = show_name or "live-stream"

        res = http.get(self.url, headers={"User-Agent": useragents.SAFARI_8})
        # find the big blob of stream info in the page
        stream_data = self._stream_data_re.search(res.text)

        if stream_data:
            if live_stream:
                streams = self._get_live_stream(stream_data, show_name,
                                                episode_name)
            else:
                self.logger.debug("Loading VOD streams for: {0}/{1}",
                                  show_name, episode_name)
                streams = self._get_show_streams(stream_data, show_name,
                                                 episode_name)

            # De-dup the streams, some of the mobile streams overlap the desktop streams
            dups = set()
            for q, s in streams:
                if hasattr(s, "args") and "url" in s.args:
                    if s.args["url"] not in dups:
                        yield q, s
                        dups.add(s.args["url"])
                else:
                    yield q, s

        else:
            self.logger.error(
                "Couldn't find the stream data for this stream: {0}".format(
                    show_name))
Ejemplo n.º 17
0
    validate.any(
        None, {
            "status":
            int,
            "media": [{
                "duration":
                validate.any(float, int),
                "offset":
                validate.any(float, int),
                "id":
                int,
                "parts": [{
                    "duration": validate.any(float, int),
                    "id": int,
                    "offset": validate.any(float, int),
                    validate.optional("recording"): int,
                    validate.optional("start"): validate.any(float, int)
                }]
            }]
        }))

Chunk = namedtuple("Chunk", "recording quality sequence extension")


class BeatFLVTagConcat(FLVTagConcat):
    def __init__(self, *args, **kwargs):
        FLVTagConcat.__init__(self, *args, **kwargs)

    def decrypt_data(self, key, iv, data):
        decryptor = crypto_AES.new(key, crypto_AES.MODE_CBC, iv)
        return decryptor.decrypt(data)
Ejemplo n.º 18
0
QUALITYS = ["original", "hd", "sd"]

QUALITY_WEIGHTS = {
    "original": 1080,
    "hd": 720,
    "sd": 480
}

_url_re = re.compile(r"http(s)?://(?P<cdn>\w+\.)?afreeca(tv)?\.com/(?P<username>\w+)(/\d+)?")

_channel_schema = validate.Schema(
    {
        "CHANNEL": {
            "RESULT": validate.transform(int),
            validate.optional("BPWD"): validate.text,
            validate.optional("BNO"): validate.text,
            validate.optional("RMD"): validate.text,
            validate.optional("AID"): validate.text,
            validate.optional("CDN"): validate.text
        }
    },
    validate.get("CHANNEL")
)

_stream_schema = validate.Schema(
    {
        validate.optional("view_url"): validate.url(
            scheme=validate.any("rtmp", "http")
        ),
        "stream_status": validate.text
Ejemplo n.º 19
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
Ejemplo n.º 20
0
_plu_schema = validate.Schema({
    "playLines": [{
        "urls": [{
            "securityUrl":
            validate.url(scheme=validate.any("rtmp", "http")),
            "resolution":
            validate.text,
            "ext":
            validate.text
        }]
    }]
})

_qq_schema = validate.Schema(
    {validate.optional("playurl"): validate.url(scheme="http")},
    validate.get("playurl"))

STREAM_WEIGHTS = {"middle": 540, "source": 1080}


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

    @classmethod
    def stream_weight(cls, stream):
        if stream in STREAM_WEIGHTS:
            return STREAM_WEIGHTS[stream], "tga"
Ejemplo n.º 21
0
class TV8cat(Plugin):
    url_re = re.compile(r"https?://(?:www\.)?tv8\.cat/directe/?")
    live_iframe = "http://www.8tv.cat/wp-content/themes/8tv/_/inc/_live_html.php"
    iframe_re = re.compile(r'iframe .*?src="((?:https?)?//[^"]*?)"')
    account_id_re = re.compile(r"accountId:\"(\d+?)\"")
    policy_key_re = re.compile(r"policyKey:\"(.+?)\"")
    britecove = "https://edge.api.brightcove.com/playback/v1/accounts/{account_id}/videos/{video_id}"
    britecove_schema = validate.Schema({
        "sources": [{
            "height": int,
            validate.optional("src"): validate.url(),
            validate.optional("app_name"): validate.url(scheme="rtmp"),
            validate.optional("stream_name"): validate.text
        }]
    })

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

    def _find_iframe(self, res):
        iframe = self.iframe_re.search(res.text)
        url = iframe and iframe.group(1)
        if url and url.startswith("//"):
            p = urlparse(self.url)
            url = "{0}:{1}".format(p.scheme, url)
        return url

    def _britecove_params(self, url):
        res = http.get(url,
                       headers={
                           "User-Agent": useragents.FIREFOX,
                           "Referer": self.url
                       })
        acc = self.account_id_re.search(res.text)
        pk = self.policy_key_re.search(res.text)

        query = dict(parse_qsl(urlparse(url).query))
        return {
            "video_id": query.get("videoId"),
            "account_id": acc and acc.group(1),
            "policy_key": pk and pk.group(1),
        }

    def _get_stream_data(self, **params):
        api_url = self.britecove.format(**params)
        res = http.get(api_url,
                       headers={
                           "Accept":
                           "application/json;pk={policy_key}".format(**params)
                       })
        return parse_json(res.text, schema=self.britecove_schema)

    def _get_streams(self):
        res = http.get(self.live_iframe)
        britecove_url = self._find_iframe(res)

        if britecove_url:
            self.logger.debug("Found britecove embed url: {0}", britecove_url)
            params = self._britecove_params(britecove_url)
            self.logger.debug("Got britecode params: {0}", params)
            stream_info = self._get_stream_data(**params)
            for source in stream_info.get("sources"):
                if source.get("src"):
                    for s in HLSStream.parse_variant_playlist(
                            self.session, source.get("src")).items():
                        yield s
                else:
                    q = "{0}p".format(source.get("height"))
                    s = RTMPStream(
                        self.session, {
                            "rtmp": source.get("app_name"),
                            "playpath": source.get("stream_name")
                        })
                    yield q, s
Ejemplo n.º 22
0
from livecli.plugin.api import validate
from livecli.plugin.api.utils import parse_json

__all__ = ["parse_playlist"]

_playlist_re = re.compile(r"\(?\{.*playlist: (\[.*\]),.*?\}\)?;", re.DOTALL)
_js_to_json = partial(re.compile(r"(\w+):\s").sub, r'"\1":')

_playlist_schema = validate.Schema(
    validate.transform(_playlist_re.search),
    validate.any(
        None,
        validate.all(
            validate.get(1),
            validate.transform(_js_to_json),
            validate.transform(parse_json),
            [{
                "sources": [{
                    "file": validate.text,
                    validate.optional("label"): validate.text
                }]
            }]
        )
    )
)


def parse_playlist(res):
    """Attempts to parse a JWPlayer playlist in a HTTP response body."""
    return _playlist_schema.validate(res.text)
Ejemplo n.º 23
0
            int(ts[-6:-5] + "1"))


_url_re = re.compile(
    r"""
    http(s)?://(\w+\.)?crunchyroll\.
    (?:
        com|de|es|fr|co.jp
    )
    (?:/[^/&?]+)?
    /[^/&?]+-(?P<media_id>\d+)
""", re.VERBOSE)

_api_schema = validate.Schema({
    "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")),
Ejemplo n.º 24
0
class TVPlayer(Plugin):
    context_url = "http://tvplayer.com/watch/context"
    api_url = "http://api.tvplayer.com/api/v2/stream/live"
    login_url = "https://tvplayer.com/account/login"
    update_url = "https://tvplayer.com/account/update-detail"
    dummy_postcode = "SE1 9LT"  # location of ITV HQ in London

    url_re = re.compile(
        r"https?://(?:www.)?tvplayer.com/(:?watch/?|watch/(.+)?)")
    stream_attrs_re = re.compile(
        r'data-(resource|token|channel-id)\s*=\s*"(.*?)"', re.S)
    data_id_re = re.compile(r'data-id\s*=\s*"(.*?)"', re.S)
    login_token_re = re.compile(r'input.*?name="token".*?value="(\w+)"')
    stream_schema = validate.Schema(
        {
            "tvplayer":
            validate.Schema({
                "status":
                u'200 OK',
                "response":
                validate.Schema({
                    "stream":
                    validate.url(scheme=validate.any("http", "https")),
                    validate.optional("drmToken"):
                    validate.any(None, validate.text)
                })
            })
        }, validate.get("tvplayer"), validate.get("response"))
    context_schema = validate.Schema({
        "validate": validate.text,
        validate.optional("token"): validate.text,
        "platform": {
            "key": validate.text
        }
    })
    options = PluginOptions({"email": None, "password": None})

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

    def __init__(self, url):
        super(TVPlayer, self).__init__(url)
        http.headers.update({"User-Agent": useragents.CHROME})

    def authenticate(self, username, password):
        res = http.get(self.login_url)
        match = self.login_token_re.search(res.text)
        token = match and match.group(1)
        res2 = http.post(self.login_url,
                         data=dict(email=username,
                                   password=password,
                                   token=token),
                         allow_redirects=False)
        # there is a 302 redirect on a successful login
        return res2.status_code == 302

    def _get_stream_data(self, resource, channel_id, token, service=1):
        # Get the context info (validation token and platform)
        self.logger.debug(
            "Getting stream information for resource={0}".format(resource))
        context_res = http.get(self.context_url,
                               params={
                                   "resource": resource,
                                   "gen": token
                               })
        context_data = http.json(context_res, schema=self.context_schema)
        self.logger.debug("Context data: {0}", str(context_data))

        # get the stream urls
        res = http.post(self.api_url,
                        data=dict(service=service,
                                  id=channel_id,
                                  validate=context_data["validate"],
                                  token=context_data.get("token"),
                                  platform=context_data["platform"]["key"]),
                        raise_for_status=False)

        return http.json(res, schema=self.stream_schema)

    def _get_stream_attrs(self, page):
        stream_attrs = dict(
            (k.replace("-", "_"), v.strip('"'))
            for k, v in self.stream_attrs_re.findall(page.text))

        if not stream_attrs.get("channel_id"):
            m = self.data_id_re.search(page.text)
            stream_attrs["channel_id"] = m and m.group(1)

        self.logger.debug("Got stream attributes: {0}", str(stream_attrs))
        valid = True
        for a in ("channel_id", "resource", "token"):
            if a not in stream_attrs:
                self.logger.debug("Missing '{0}' from stream attributes", a)
                valid = False

        return stream_attrs if valid else {}

    def _get_streams(self):
        if self.get_option("email") and self.get_option("password"):
            if not self.authenticate(self.get_option("email"),
                                     self.get_option("password")):
                self.logger.warning("Failed to login as {0}".format(
                    self.get_option("email")))

        # find the list of channels from the html in the page
        self.url = self.url.replace("https", "http")  # https redirects to http
        res = http.get(self.url)

        if "enter your postcode" in res.text:
            self.logger.info(
                "Setting your postcode to: {0}. "
                "This can be changed in the settings on tvplayer.com",
                self.dummy_postcode)
            res = http.post(self.update_url,
                            data=dict(postcode=self.dummy_postcode),
                            params=dict(return_url=self.url))

        stream_attrs = self._get_stream_attrs(res)
        if stream_attrs:
            stream_data = self._get_stream_data(**stream_attrs)

            if stream_data:
                if stream_data.get("drmToken"):
                    self.logger.error(
                        "This stream is protected by DRM can cannot be played")
                    return
                else:
                    return HLSStream.parse_variant_playlist(
                        self.session, stream_data["stream"])
        else:
            if "need to login" in res.text:
                self.logger.error(
                    "You need to login using --tvplayer-email/--tvplayer-password to view this stream"
                )
Ejemplo n.º 25
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"))
Ejemplo n.º 26
0
    r"http(s)?://(\w+\.)?weeb.tv/(channel|online)/(?P<channel>[^/&?]+)")
_schema = validate.Schema(
    dict, validate.map(lambda k, v: (PARAMS_KEY_MAP.get(k, k), v)),
    validate.any(
        {
            "status":
            validate.transform(int),
            "rtmp":
            validate.url(scheme="rtmp"),
            "playpath":
            validate.text,
            "multibitrate":
            validate.all(validate.transform(int), validate.transform(bool)),
            "block_type":
            validate.transform(int),
            validate.optional("token"):
            validate.text,
            validate.optional("block_time"):
            validate.text,
            validate.optional("reconnect_time"):
            validate.text,
        },
        {
            "status": validate.transform(int),
        },
    ))


class Weeb(Plugin):
    @classmethod
    def can_handle_url(self, url):
Ejemplo n.º 27
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)),
    }]),
Ejemplo n.º 28
0
    "notes": "",
    "live": True,
    "vod": False,
    "last_update": "2016-11-21",
}

_url_re = re.compile(r"http(s)?://(www\.)?livestream.com/")
_stream_config_schema = validate.Schema({
    "event": {
        "stream_info": validate.any({
            "is_live": bool,
            "qualities": [{
                "bitrate": int,
                "height": int
            }],
            validate.optional("play_url"): validate.url(scheme="http"),
            validate.optional("m3u8_url"): validate.url(
                scheme="http",
                path=validate.endswith(".m3u8")
            ),
        }, None)
    },
    validate.optional("playerUri"): validate.text,
    validate.optional("viewerPlusSwfUrl"): validate.url(scheme="http"),
    validate.optional("lsPlayerSwfUrl"): validate.text,
    validate.optional("hdPlayerSwfUrl"): validate.text
})
_smil_schema = validate.Schema(validate.union({
    "http_base": validate.all(
        validate.xml_find("{http://www.w3.org/2001/SMIL20/Language}head/"
                          "{http://www.w3.org/2001/SMIL20/Language}meta"
Ejemplo n.º 29
0
__livecli_docs__ = {
    "domains": [
        "camsoda.com",
    ],
    "geo_blocked": [],
    "notes": "",
    "live": True,
    "vod": False,
    "last_update": "2017-11-18",
}

_url_re = re.compile(r"http(s)?://(www\.)?camsoda\.com/(?P<username>[^\"\']+)")

_api_user_schema = validate.Schema({
    "status": validate.any(int, validate.text),
    validate.optional("user"): {
        "online": validate.any(int, validate.text),
        "chatstatus": validate.text,
    }
})

_api_video_schema = validate.Schema({
    "token": validate.text,
    "app": validate.text,
    "edge_servers": [validate.text],
    "stream_name": validate.text
})


class Camsoda(Plugin):
    API_URL_USER = "******"
Ejemplo n.º 30
0
    ],
    "geo_blocked": [],
    "notes": "",
    "live": True,
    "vod": True,
    "last_update": "2014-06-22",
}

API_CLIENT_NAME = "Bambuser AS2"
API_CONTEXT = "b_broadcastpage"
API_KEY = "005f64509e19a868399060af746a00aa"
API_URL_VIDEO = "http://player-c.api.bambuser.com/getVideo.json"

_url_re = re.compile(r"http(s)?://(\w+.)?bambuser.com/v/(?P<video_id>\d+)")
_video_schema = validate.Schema({
    validate.optional("error"): validate.text,
    validate.optional("result"): {
        "id": validate.text,
        "size": validate.text,
        "url": validate.url(scheme=validate.any("rtmp", "http"))
    }
})


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

    def _get_streams(self):
        match = _url_re.match(self.url)