Exemple #1
0
    def _get_rtmp_streams(self, swfurl):
        if not RTMPStream.is_usable(self.session):
            raise NoStreamsError(self.url)

        self.logger.debug("Fetching RTMP stream info")

        res = http.get(swfurl)
        swf = swfdecompress(res.content)
        match = re.search("customURL[^h]+(https://.*?)\\\\", swf)

        if not match:
            raise NoStreamsError(self.url)

        res = http.get(match.group(1))
        rtmp, playpath = rtmpparse(res.text)

        params = {
            "rtmp": rtmp,
            "pageUrl": self.url,
            "playpath": playpath,
            "live": True
        }

        match = re.search("file[^h]+(https?://.*?.swf)", swf)
        if match:
            params["swfUrl"] = match.group(1)

        return RTMPStream(self.session, params)
Exemple #2
0
    def _get_live_streams(self):
        stream_id = _id_map[self.channel_path]

        if stream_id == "ruv":
            qualities_rtmp = ["720p", "480p", "360p", "240p"]

            for i, quality in enumerate(qualities_rtmp):
                yield quality, RTMPStream(
                    self.session, {
                        "rtmp": RTMP_LIVE_URL.format(stream_id, i + 1),
                        "pageUrl": self.url,
                        "live": True
                    })

            qualities_hls = ["240p", "360p", "480p", "720p"]
            for i, quality_hls in enumerate(qualities_hls):
                yield quality_hls, HLSStream(self.session,
                                             HLS_RUV_LIVE_URL.format(i + 1))

        else:
            yield "audio", RTMPStream(
                self.session, {
                    "rtmp": RTMP_LIVE_URL.format(stream_id, 1),
                    "pageUrl": self.url,
                    "live": True
                })

            yield "audio", HLSStream(self.session,
                                     HLS_RADIO_LIVE_URL.format(stream_id))
Exemple #3
0
    def _get_rtmp_streams(self):
        def clean_tag(tag):
            if tag[0] == "_":
                return tag[1:]
            else:
                return tag

        chansub = self._authenticate()

        url = self.StreamInfoURL.format(self.channelname)
        params = dict(b_id="true", group="", private_code="null",
                      p=int(random.random() * 999999),
                      channel_subscription=chansub, type="any")

        self.logger.debug("Fetching stream info")
        res = urlget(url, params=params)
        data = res.text

        # fix invalid xml
        data = re.sub("<(\d+)", "<_\g<1>", data)
        data = re.sub("</(\d+)", "</_\g<1>", data)

        streams = {}

        try:
            dom = xml.dom.minidom.parseString(data)
        except Exception as err:
            raise PluginError(("Unable to parse config XML: {0})").format(err))

        nodes = dom.getElementsByTagName("nodes")[0]

        if len(nodes.childNodes) == 0:
            return streams

        swfurl = urlresolve(self.SWFURL)

        for node in nodes.childNodes:
            info = {}
            for child in node.childNodes:
                info[child.tagName] = self._get_node_text(child)

            if not ("connect" in info and "play" in info):
                continue

            stream = RTMPStream(self.session, {
                "rtmp": ("{0}/{1}").format(info["connect"], info["play"]),
                "swfVfy": swfurl,
                "live": True
            })

            sname = clean_tag(node.tagName)

            if "token" in info:
                stream.params["jtv"] = info["token"]
            else:
                self.logger.warning("No token found for stream {0}, this stream may fail to play", sname)

            streams[sname] = stream

        return streams
Exemple #4
0
    def _get_streams(self):
        channelid = urlparse(
            self.url).path.rstrip("/").rpartition("/")[-1].lower()

        self.logger.debug("Fetching stream info")
        headers = {"Referer": self.url}
        options = dict(id=channelid)
        res = urlget(self.StreamInfoURL, headers=headers, params=options)
        json = res_json(res, "stream info JSON")

        if not isinstance(json, dict):
            raise PluginError("Invalid JSON response")

        if not ("rtmp" in json and "streamname" in json):
            raise NoStreamsError(self.url)

        if not RTMPStream.is_usable(self.session):
            raise PluginError(
                "rtmpdump is not usable and required by Owncast plugin")

        rtmp = json["rtmp"]
        playpath = json["streamname"]

        streams = {}
        streams["live"] = RTMPStream(
            self.session, {
                "rtmp": rtmp,
                "pageUrl": self.url,
                "swfUrl": self.SWFURL,
                "playpath": playpath,
                "live": True
            })

        return streams
    def _get_rtmp_streams(self):
        chansub = self._authenticate()

        url = self.StreamInfoURL.format(self.channelname)
        params = dict(
            b_id="true",
            group="",
            private_code="null",
            p=int(random.random() * 999999),
            channel_subscription=chansub,
            type="any",
        )

        self.logger.debug("Fetching stream info")
        res = urlget(url, params=params)
        json = res_json(res, "stream info JSON")

        if not isinstance(json, list):
            raise PluginError("Invalid JSON response")

        if len(json) == 0:
            raise NoStreamsError(self.url)

        streams = {}
        swfurl, swfhash, swfsize = self._verify_swf()

        for info in json:
            if not ("connect" in info and "play" in info and "type" in info):

                continue

            stream = RTMPStream(
                self.session,
                {
                    "rtmp": ("{0}/{1}").format(info["connect"], info["play"]),
                    "swfUrl": swfurl,
                    "swfhash": swfhash,
                    "swfsize": swfsize,
                    "live": True,
                },
            )

            if "display" in info:
                sname = info["display"]
            else:
                sname = info["type"]

            if "token" in info:
                stream.params["jtv"] = info["token"]
            else:
                self.logger.warning("No token found for stream {0}, this stream may fail to play", sname)

            streams[sname] = stream

        return streams
Exemple #6
0
    def _get_rtmp_streams(self):
        chansub = self._authenticate()

        url = self.StreamInfoURL.format(self.channelname)
        params = dict(b_id="true",
                      group="",
                      private_code="null",
                      p=int(random.random() * 999999),
                      channel_subscription=chansub,
                      type="any")

        self.logger.debug("Fetching stream info")
        res = urlget(url, params=params)
        json = res_json(res, "stream info JSON")

        if not isinstance(json, list):
            raise PluginError("Invalid JSON response")

        if len(json) == 0:
            raise NoStreamsError(self.url)

        streams = {}
        swfurl, swfhash, swfsize = self._verify_swf()

        for info in json:
            if not ("connect" in info and "play" in info and "type" in info):

                continue

            stream = RTMPStream(
                self.session, {
                    "rtmp": ("{0}/{1}").format(info["connect"], info["play"]),
                    "swfUrl": swfurl,
                    "swfhash": swfhash,
                    "swfsize": swfsize,
                    "live": True
                })

            if "display" in info:
                sname = info["display"]
            else:
                sname = info["type"]

            if "token" in info:
                stream.params["jtv"] = info["token"]
            else:
                self.logger.warning(
                    "No token found for stream {0}, this stream may fail to play",
                    sname)

            streams[sname] = stream

        return streams
Exemple #7
0
    def _get_streams(self):
        self.logger.debug("Fetching stream info")
        res = urlget(self.url)

        match = re.search("var current_channel = (.*);", res.text)
        if match:
            json = parse_json(match.group(1))
        else:
            raise NoStreamsError(self.url)

        if not isinstance(json, dict):
            raise PluginError("Invalid JSON response")
        elif not "streams" in json:
            raise NoStreamsError(self.url)

        if not RTMPStream.is_usable(self.session):
            raise PluginError(
                "rtmpdump is not usable and required by Filmon plugin")

        match = re.search("var flash_config = (.*);", res.text)
        if match:
            config = parse_json(match.group(1))
            if "streamer" in config:
                self.SWFURL = urljoin(self.SWFURL, config["streamer"])

        streams = {}

        for stream in json["streams"]:
            if not ("url" in stream and "name" in stream):
                continue

            parsed = urlparse(stream["url"])

            if not parsed.scheme.startswith("rtmp"):
                continue

            if parsed.query:
                app = "{0}?{1}".format(parsed.path[1:], parsed.query)
            else:
                app = parsed.path[1:]

            name = stream["quality"]
            streams[name] = RTMPStream(
                self.session, {
                    "rtmp": stream["url"],
                    "pageUrl": self.url,
                    "swfUrl": self.SWFURL,
                    "playpath": stream["name"],
                    "app": app,
                    "live": True
                })

        return streams
    def _get_streaminfo(self, channelname):
        def clean_tag(tag):
            if tag[0] == "_":
                return tag[1:]
            else:
                return tag

        metadata = self._get_metadata(channelname)
        randomp = int(random.random() * 999999)

        if "chansub_guid" in metadata:
            url = self.StreamInfoURLSub.format(channelname, randomp, metadata["chansub_guid"])
        else:
            url = self.StreamInfoURL.format(channelname, randomp)

        data = urlget(url)

        # fix invalid xml
        data = re.sub(b"<(\d+)", b"<_\g<1>", data)
        data = re.sub(b"</(\d+)", b"</_\g<1>", data)

        streams = {}

        try:
            dom = xml.dom.minidom.parseString(data)
        except Exception as err:
            raise PluginError(("Unable to parse config XML: {0})").format(err))

        nodes = dom.getElementsByTagName("nodes")[0]

        swfhash, swfsize = swfverify(self.SWFURL)

        for node in nodes.childNodes:
            info = {}
            for child in node.childNodes:
                info[child.tagName] = self._get_node_text(child)

            stream = RTMPStream({
                "rtmp": ("{0}/{1}").format(info["connect"], info["play"]),
                "swfUrl": self.SWFURL,
                "swfhash": swfhash,
                "swfsize": swfsize,
                "live": 1
            })

            if "token" in info:
                stream.params["jtv"] = info["token"]

            sname = clean_tag(node.tagName)
            streams[sname] = stream

        return streams
Exemple #9
0
    def _get_streams(self):
        country_code = urlparse(self.url).netloc.split(".")[0]

        self.logger.debug("Fetching stream info")
        res = urlget(self.APIURL)
        json = res_json(res)

        if not isinstance(json, dict):
            raise PluginError("Invalid JSON response")
        elif not ("primary" in json or "secondary" in json):
            raise PluginError("Invalid JSON response")

        if not RTMPStream.is_usable(self.session):
            raise PluginError(
                "rtmpdump is not usable and required by Euronews plugin")

        streams = {}

        self.logger.debug("Euronews Countries:{0}",
                          " ".join(json["primary"].keys()))

        if not (country_code in json["primary"]
                or country_code in json["secondary"]):
            res = urlget(self.GEOIPURL)
            geo = res_json(res)
            if isinstance(json, dict) and "country_code" in geo:
                country_code = geo["country_code"].lower()
                if not (country_code in json["primary"]
                        or country_code in json["secondary"]):
                    country_code = "en"
            else:
                country_code = "en"

        for site in ("primary", "secondary"):
            for quality in json[site][country_code]["rtmp_flash"]:
                stream = json[site][country_code]["rtmp_flash"][quality]
                name = quality + "k"
                if site == "secondary":
                    name += "_alt"
                streams[name] = RTMPStream(
                    self.session, {
                        "rtmp": stream["server"],
                        "playpath": stream["name"],
                        "swfUrl": self.SWFURL,
                        "live": True
                    })

        if len(streams) == 0:
            raise NoStreamsError(self.url)

        return streams
Exemple #10
0
    def _parse_live(self, json):
        streams = {}
        app = json["ingest"]["name"]
        playpath = json["name_seo"]
        i = 0
        id = self._choose_server(json)

        for server in json["server"]:
            name = server["server"]["name"]
            height = str(json["current_video_height"])+"p"

            if id != i:
                height+="_alt_"+name

            streams[height] = RTMPStream(self.session, {
                "rtmp": "rtmp://"+server["server"]["hostname"],
                "app": app,
                "playpath": playpath,
                "pageUrl": self.url,
                "swfUrl": self.SWFURL,
                "live": True
            })
            i += 1


        return streams
Exemple #11
0
    def _get_streams(self):
        self.channelname = self._get_channel_name(self.url)

        if not self.channelname:
            raise NoStreamsError(self.url)

        streams = {}

        if RTMPStream.is_usable(self.session):
            try:
                rtmpstreams = self._get_rtmp_streams()
                streams.update(rtmpstreams)
            except PluginError as err:
                self.logger.error("Error when fetching RTMP stream info: {0}", str(err))
        else:
            self.logger.warning("rtmpdump is not usable, only HLS streams will be available")

        try:
            hlsstreams = self._get_hls_streams()

            for name, stream in hlsstreams.items():
                if name in streams:
                    streams[name] = [streams[name], stream]
                else:
                    streams[name] = stream

        except PluginError as err:
            self.logger.error("Error when fetching HLS stream info: {0}", str(err))

        return streams
Exemple #12
0
    def _get_streams(self):
        self.logger.debug("Fetching stream info")
        res = urlget(self.url, params=dict(output="json"))

        if res.json is None:
            raise PluginError("No JSON data in stream info")

        streams = {}
        video = verifyjson(res.json, "video")
        videos = verifyjson(video, "videoReferences")

        for video in videos:
            if not ("url" in video and "playerType" in video):
                continue

            if video["playerType"] == "flash":
                if video["url"].startswith("rtmp"):
                    stream = RTMPStream(
                        self.session, {
                            "rtmp": video["url"],
                            "pageUrl": self.PageURL,
                            "swfVfy": self.SWFURL,
                            "live": True
                        })
                    streams[str(video["bitrate"]) + "k"] = stream
            elif video["playerType"] == "ios":
                try:
                    hlsstreams = HLSStream.parse_variant_playlist(
                        self.session, video["url"])
                    streams.update(hlsstreams)
                except IOError as err:
                    self.logger.warning("Failed to get variant playlist: {0}",
                                        err)

        return streams
Exemple #13
0
    def _get_sarpurinn_streams(self):
        res = http.get(self.url)
        match = _rtmp_url_re.search(res.text)

        if not match:
            yield

        token = match.group("id")
        status = match.group("status")
        extension = match.group("ext")
        date = match.group("date")
        if not date:
            date = ""

        if extension == "mp3":
            key = "audio"
        else:
            key = "576p"

            # HLS on Sarpurinn is currently only available on videos
            yield key, HLSStream(
                self.session,
                HLS_SARPURINN_URL.format(status, date, token, extension))

        yield key, RTMPStream(
            self.session, {
                "rtmp": RTMP_SARPURINN_URL.format(status, date, token,
                                                  extension),
                "pageUrl": self.url,
                "live": True
            })
    def _get_streams(self):
        res = http.get(self.StreamURL, data={"from": "ongamenet"})

        match = re.search("var stream = \"(.+?)\";", res.text)
        if not match:
            raise NoStreamsError(self.url)

        stream = match.group(1)

        match = re.search("var server = \"(.+?)\";", res.text)
        if not match:
            raise NoStreamsError(self.url)

        server = match.group(1)

        streams = {}
        streams["live"] = RTMPStream(
            self.session, {
                "rtmp": server,
                "playpath": stream,
                "swfUrl": self.SWFURL,
                "pageUrl": self.PageURL,
                "live": True,
            })

        return streams
Exemple #15
0
    def _get_live_streams(self, params, swf_url):
        for key, quality in QUALITY_MAP.items():
            key_url = "{0}URL".format(key)
            url = params.get(key_url)

            if not url:
                continue

            try:
                res = http.get(url, exception=IOError)
            except IOError:
                continue

            if quality == "hds":
                streams = HDSStream.parse_manifest(self.session, res.url)
                for name, stream in streams.items():
                    if key == "source":
                        name += "+"

                    yield name, stream
            elif res.text.startswith("rtmp"):
                match = _rtmp_re.match(res.text)
                if not match:
                    continue

                stream = RTMPStream(
                    self.session, {
                        "rtmp": match.group("host"),
                        "app": match.group("app"),
                        "playpath": match.group("playpath"),
                        "swfVfy": swf_url,
                        "live": True
                    })

                yield quality, stream
    def _get_streams(self):
        self.logger.debug("Fetching stream info")
        res = http.get(self.url)

        match = re.search("\"User_channelid\".+?value=\"(.+?)\"", res.text)
        if not match:
            raise NoStreamsError(self.url)

        headers = {"Referer": self.url}

        res = http.get(self.PlayerURL.format(match.group(1)), headers=headers)

        match = re.search("stream:\s+'(rtmp://.+?)'", res.text)
        if not match:
            raise NoStreamsError(self.url)

        rtmp = match.group(1)
        streams = {}
        streams["live"] = RTMPStream(self.session, {
            "rtmp": rtmp,
            "pageUrl": self.url,
            "swfVfy": self.SWFURL,
            "live": True
        })

        return streams
Exemple #17
0
    def _get_streams(self):
        info = http.get(self.url, schema=_schema)
        if not info:
            return

        headers = {"Referer": self.url}
        res = http.get(info["token_url"], headers=headers)
        token = http.json(res, schema=_token_schema)

        parsed = urlparse(info["rtmp_url"])
        if parsed.query:
            app = "{0}?{1}".format(parsed.path[1:], parsed.query)
        else:
            app = parsed.path[1:]

        params = {
            "rtmp": info["rtmp_url"],
            "app": app,
            "pageUrl": self.url,
            "swfVfy": info["swf_url"],
            "playpath": info["rtmp_playpath"],
            "token": token,
            "live": True
        }

        stream = RTMPStream(self.session, params)
        return dict(live=stream)
    def _get_live_streams(self):
        streams = defaultdict(list)

        if RTMPStream.is_usable(self.session):
            try:
                for name, stream in self._get_desktop_streams().items():
                    streams[name].append(stream)

            except PluginError as err:
                self.logger.error("Error when fetching desktop streams: {0}",
                                  err)
            except NoStreamsError:
                pass
        else:
            self.logger.warning("rtmpdump is not usable, "
                                "only mobile streams may be available")

        try:
            for name, stream in self._get_mobile_streams().items():
                # Justin.tv streams have a iphone prefix, so let's
                # strip it to keep it consistent with Twitch.
                name = name.replace("iphone", "")
                streams[name].append(stream)

        except PluginError as err:
            self.logger.error("Error when fetching mobile streams: {0}",
                              err)
        except NoStreamsError:
            pass

        return streams
Exemple #19
0
    def _get_streams(self):
        self.logger.debug("Fetching stream info")
        res = urlget(self.url)

        match = re.search(
            "flashplayer: \"(.+.swf)\".+streamer: \"(.+)\".+file: \"(.+).flv\"",
            res.text, re.DOTALL)
        if not match:
            raise NoStreamsError(self.url)

        rtmp = match.group(2)
        playpath = match.group(3)
        swfurl = match.group(1)

        streams = {}
        streams["live"] = RTMPStream(self.session, {
            "rtmp": rtmp,
            "pageUrl": self.url,
            "swfVfy": swfurl,
            "playpath": playpath,
            "live": True
        },
                                     redirect=True)

        return streams
Exemple #20
0
    def _get_streams(self):
        if not RTMPStream.is_usable(self.session):
            raise PluginError("rtmpdump is not usable and required by Filmon plugin")

        self.logger.debug("Fetching stream info")
        self.rsession = requests.session()
        res = urlget(self.url, session=self.rsession)

        match = re.search("movie_id=(\d+)", res.text)
        if match:
            return self._get_vod_stream(match.group(1))

        match = re.search("/channels/(\d+)/extra_big_logo.png", res.text)
        if not match:
            return

        channel_id = match.group(1)
        streams = {}
        for quality in ("low", "high"):
            try:
                streams[quality] = self._get_stream(channel_id, quality)
            except NoStreamsError:
                pass

        return streams
Exemple #21
0
    def _get_vod_stream(self, movie_id):
        res = http.get(VODINFO_URL.format(movie_id), headers=AJAX_HEADERS)
        json = http.json(res)
        json = json and json.get("data")
        json = json and json.get("streams")

        if not json:
            raise NoStreamsError(self.url)

        streams = {}
        for quality in ("low", "high"):
            stream = json.get(quality)
            if not stream:
                continue

            rtmp = stream.get("url")
            app = self._get_rtmp_app(rtmp)
            if not app:
                continue

            playpath = stream.get("name")
            if ".mp4" in playpath:
                playpath = "mp4:" + playpath

            streams[quality] = RTMPStream(
                self.session, {
                    "rtmp": rtmp,
                    "pageUrl": self.url,
                    "swfUrl": SWF_URL,
                    "playpath": playpath,
                    "app": app,
                })

        return streams
Exemple #22
0
    def _get_stream(self, channel_id, quality):
        params = dict(channel_id=channel_id, quality=quality)
        res = http.post(CHINFO_URL, data=params, headers=AJAX_HEADERS)
        json = http.json(res)

        if not json:
            raise NoStreamsError(self.url)

        rtmp = json.get("serverURL")
        playpath = json.get("streamName")
        if not (rtmp and playpath):
            raise NoStreamsError(self.url)

        app = self._get_rtmp_app(rtmp)
        if not app:
            raise NoStreamsError(self.url)

        return RTMPStream(
            self.session, {
                "rtmp": rtmp,
                "pageUrl": self.url,
                "swfUrl": SWF_URL,
                "playpath": playpath,
                "app": app,
                "live": True
            })
Exemple #23
0
    def _get_streams(self):
        if not RTMPStream.is_usable(self.session):
            raise PluginError(
                "rtmpdump is not usable and required by Filmon plugin")

        self.logger.debug("Fetching stream info")
        res = http.get(self.url)

        match = re.search("movie_id=(\d+)", res.text)
        if match:
            return self._get_vod_stream(match.group(1))

        match = re.search("/channels/(\d+)/extra_big_logo.png", res.text)
        if not match:
            return

        channel_id = match.group(1)
        streams = {}
        for quality in ("low", "high"):
            try:
                streams[quality] = self._get_stream(channel_id, quality)
            except NoStreamsError:
                pass

        return streams
Exemple #24
0
    def _get_streams(self):
        res = http.get(self.url, schema=_schema)
        if not res:
            return
        owner = res["vars"]["owner"]
        token = res["vars"].get("token", "null")
        swf_url = res["swf"]

        # Check if the stream is online
        res = http.get(CHANNEL_DETAILS_URI.format(owner, token))
        channel_details = http.json(res, schema=_channel_details_schema)
        if not channel_details["channel"]["live"]:
            return

        stream_ip = http.get(REDIRECT_SERVICE_URI.format(owner)).text

        streams = {}
        streams["live"] = RTMPStream(
            self.session, {
                "rtmp":
                RTMP_URL.format(stream_ip, channel_details["channel"]["slug"]),
                "pageUrl":
                self.url,
                "swfUrl":
                urljoin(self.url, swf_url),
                "live":
                True
            })
        return streams
Exemple #25
0
    def _get_streams(self):
        channelname = urlparse(
            self.url).path.rstrip("/").rpartition("/")[-1].lower()

        self.logger.debug("Fetching stream info")

        headers = {"Referer": self.url}

        res = urlget(self.PlayerURL.format(channelname), headers=headers)
        match = re.search("'FlashVars', '(id=\d+)&", res.text)
        if not match:
            raise NoStreamsError(self.url)

        channelname += "?" + match.group(1)
        res = urlget(self.BalancerURL, headers=headers)

        match = re.search("redirect=(.+)", res.text)
        if not match:
            raise PluginError(
                "Error retrieving RTMP address from loadbalancer")

        rtmp = match.group(1)
        streams = {}
        streams["live"] = RTMPStream(
            self.session, {
                "rtmp": "rtmp://{0}/live/{1}".format(rtmp, channelname),
                "pageUrl": self.url,
                "swfVfy": self.SWFURL,
                "conn": "S:OK",
                "live": True
            })

        return streams
Exemple #26
0
    def _get_streams(self):
        channelid = urlparse(self.url).path.rstrip("/").rpartition("/")[-1].lower()

        self.logger.debug("Fetching stream info")
        headers = {"Referer": self.url}
        options = dict(id=channelid)
        res = urlget(self.StreamInfoURL, headers=headers, params=options)
        json = res_json(res, "stream info JSON")

        if not isinstance(json, dict):
            raise PluginError("Invalid JSON response")

        if not ("rtmp" in json and "streamname" in json):
            raise NoStreamsError(self.url)

        if not RTMPStream.is_usable(self.session):
            raise PluginError("rtmpdump is not usable and required by Owncast plugin")

        rtmp = json["rtmp"]
        playpath = json["streamname"]

        streams = {}
        streams["live"] = RTMPStream(
            self.session, {"rtmp": rtmp, "pageUrl": self.url, "swfUrl": self.SWFURL, "playpath": playpath, "live": True}
        )

        return streams
Exemple #27
0
    def _get_rtmp_streams(self, channelname):
        options = dict(l="info",
                       a="xmlClipPath",
                       clip_id=channelname,
                       rid=time())
        res = urlget(self.APIURL, params=options)

        dom = res_xml(res)
        rtmpurl = dom.getElementsByTagName("url")
        rtmp = None

        if len(rtmpurl) > 0:
            rtmp = get_node_text(rtmpurl[0])
        else:
            raise PluginError(
                ("No RTMP Streams found on URL {0}").format(self.url))

        rtmplist = {}
        rtmplist["live"] = RTMPStream(self.session, {
            "rtmp": rtmp,
            "swfVfy": self.SWFURL,
            "live": True
        })

        return rtmplist
Exemple #28
0
    def _create_rtmp_stream(self, cdn, stream_name):
        parsed = urlparse(cdn)
        options = dict(rtmp=cdn, app=parsed.path[1:],
                       playpath=stream_name, pageUrl=self.url,
                       swfUrl=SWF_URL, live=True)

        return RTMPStream(self.session, options)
    def _get_streams(self):
        if not RTMPStream.is_usable(self.session):
            self.logger.warning("rtmpdump is not usable, only HDS streams will be available")

        self.logger.debug("Fetching stream info")
        match = re.search("/\w*/(live|video)*/(\d+)", self.url)
        if not match:
            return

        stream_id = match.group(2)
        res = http.get(API_URL, params=dict(ak="web", id=stream_id))
        root = parse_xml(res.text.encode("utf8"))

        streams = {}
        for formitaet in root.iter('formitaet'):
            url = formitaet.find('url').text
            quality = formitaet.find('quality').text

            if formitaet.get('basetype') == "h264_aac_f4f_http_f4m_http":
                hds_streams = HDSStream.parse_manifest(self.session, url)
                streams.update(hds_streams)
            elif formitaet.get('basetype') == 'h264_aac_mp4_rtmp_zdfmeta_http':
                streams[quality] = RTMPStream(self.session, {
                    "rtmp": self._get_stream(url),
                    "pageUrl": self.url,
                })

        return streams
    def _get_live_streams(self, *args, **kwargs):
        streams = defaultdict(list)

        if RTMPStream.is_usable(self.session):
            try:
                for name, stream in self._get_desktop_streams(*args, **kwargs).items():
                    streams[name].append(stream)

            except PluginError as err:
                self.logger.error("Error when fetching desktop streams: {0}",
                                  err)
            except NoStreamsError:
                pass
        else:
            self.logger.warning("rtmpdump is required to access the desktop "
                                "streams, but it could not be found")

        try:
            for name, stream in self._get_mobile_streams(*args, **kwargs).items():
                # Justin.tv streams have a iphone prefix, so let's
                # strip it to keep it consistent with Twitch.
                name = name.replace("iphone", "")
                streams[name].append(stream)

        except PluginError as err:
            self.logger.error("Error when fetching mobile streams: {0}",
                              err)
        except NoStreamsError:
            pass

        return streams
Exemple #31
0
    def _get_streams(self):
        self.channelname = self._get_channel_name(self.url)

        if not self.channelname:
            raise NoStreamsError(self.url)

        streams = {}

        if RTMPStream.is_usable(self.session):
            try:
                rtmpstreams = self._get_rtmp_streams()
                streams.update(rtmpstreams)
            except PluginError as err:
                self.logger.error("Error when fetching RTMP stream info: {0}", str(err))
        else:
            self.logger.warning("rtmpdump is not usable, only HLS streams will be available")

        try:
            hlsstreams = self._get_hls_streams()
            if len(streams) > 0:
                hlssuffix = "_hls"
            else:
                hlssuffix = ""

            for name, stream in hlsstreams.items():
                streams[name + hlssuffix] = stream
        except PluginError as err:
            self.logger.error("Error when fetching HLS stream info: {0}", str(err))

        return streams
Exemple #32
0
    def _get_streams(self, type):
        self.channelname = self._get_channel_name(self.url)

        if not self.channelname:
            raise NoStreamsError(self.url)

        streams = {}
        
        if type in (None, StreamType.RTMP):
            if RTMPStream.is_usable(self.session):
                try:
                    rtmpstreams = self._get_rtmp_streams()
                    streams.update(rtmpstreams)
                except PluginError as err:
                    self.logger.error("Error when fetching RTMP stream info: {0}", str(err))
            else:
                self.logger.warning("rtmpdump is not usable, only HLS streams will be available")

        if type in (None, StreamType.HLS):
            try:
                hlsstreams = self._get_hls_streams()
                if len(streams) > 0:
                    hlssuffix = "_hls"
                else:
                    hlssuffix = ""

                for name, stream in hlsstreams.items():
                    streams[name + hlssuffix] = stream
            except PluginError as err:
                self.logger.error("Error when fetching HLS stream info: {0}", str(err))

        return streams
Exemple #33
0
 def _create_stream(self, cdn, streamname):
     url = "{0}/{1}".format(cdn, streamname)
     options = dict(rtmp=url,
                    pageUrl=self.url,
                    swfUrl=self.SWFURL,
                    live=True)
     return RTMPStream(self.session, options)
Exemple #34
0
    def _get_rtmp_streams(self, swfurl):
        if not RTMPStream.is_usable(self.session):
            raise NoStreamsError(self.url)

        self.logger.debug("Fetching RTMP stream info")

        res = http.get(swfurl)
        swf = swfdecompress(res.content)
        match = re.search("customURL[^h]+(https://.*?)\\\\", swf)

        if not match:
            raise NoStreamsError(self.url)

        res = http.get(match.group(1))
        rtmp, playpath = rtmpparse(res.text)

        params = {
            "rtmp": rtmp,
            "pageUrl": self.url,
            "playpath": playpath,
            "live": True
        }

        match = re.search("file[^h]+(https?://.*?.swf)", swf)
        if match:
            params["swfUrl"] = match.group(1)

        return RTMPStream(self.session, params)
Exemple #35
0
    def _get_streams(self):
        self.logger.debug("Fetching stream info")
        res = urlget(self.url)

        match = re.search(
            "flashplayer: \"(.+.swf)\".+streamer: \"(.+)\".+file: \"(.+).flv\"",
            res.text, re.DOTALL)
        if not match:
            raise NoStreamsError(self.url)

        params = {
            "rtmp": match.group(2),
            "pageUrl": self.url,
            "swfVfy": match.group(1),
            "playpath": match.group(3),
            "live": True
        }

        match = re.search("(http(s)?://.+/server.php\?id=\d+)", res.text)
        if match:
            token_url = match.group(1)
            res = res_json(urlget(token_url, headers=dict(Referer=self.url)))
            token = res.get("token")
            if token:
                params["token"] = token

        streams = {}
        streams["live"] = RTMPStream(self.session, params)

        return streams
Exemple #36
0
    def _create_stream(self, stream, is_live):
        stream_name = "{0}p".format(stream["height"])
        stream_type = stream["mediaType"]
        stream_url = stream["url"]

        if stream_type in ("hls", "mp4"):
            if urlparse(stream_url).path.endswith("m3u8"):
                try:
                    streams = HLSStream.parse_variant_playlist(
                        self.session, stream_url)

                    # TODO: Replace with "yield from" when dropping Python 2.
                    for stream in streams.items():
                        yield stream
                except IOError as err:
                    self.logger.error("Failed to extract HLS streams: {0}",
                                      err)
            else:
                yield stream_name, HTTPStream(self.session, stream_url)

        elif stream_type == "rtmp":
            params = {
                "rtmp": stream["streamer"],
                "playpath": stream["url"],
                "swfVfy": SWF_URL,
                "pageUrl": self.url,
            }

            if is_live:
                params["live"] = True
            else:
                params["playpath"] = "mp4:{0}".format(params["playpath"])

            stream = RTMPStream(self.session, params)
            yield stream_name, stream
Exemple #37
0
    def _get_streams(self):
        match = re.search("/v/(\d+)", self.url)
        if not match:
            return

        vid = match.group(1)
        params = dict(client_name="Bambuser AS2",
                      context="b_broadcastpage",
                      raw_user_input=1,
                      api_key="005f64509e19a868399060af746a00aa",
                      vid=vid,
                      r=random.random())

        self.logger.debug("Fetching stream info")
        res = http.get(PLAYER_URL, params=params)
        json = http.json(res)

        error = json and json.get("errorCode")
        if error:
            error = error and json.get("error")
            self.logger.error(error)
            return

        json = verifyjson(json, "result")
        playpath = verifyjson(json, "id")
        url = verifyjson(json, "url")
        (width, height) = verifyjson(json, "size").split("x")
        name = "{0}p".format(height)

        parsed = urlparse(url)
        streams = {}

        if parsed.scheme.startswith("rtmp"):
            if not RTMPStream.is_usable(self.session):
                raise PluginError(
                    "rtmpdump is not usable and required by Bambuser plugin")
            streams[name] = RTMPStream(
                self.session, {
                    "rtmp": url,
                    "playpath": playpath,
                    "pageUrl": self.url,
                    "live": True
                })
        elif parsed.scheme == "http":
            streams[name] = HTTPStream(self.session, url)

        return streams
Exemple #38
0
    def _get_streams(self):
        params = parse_qsd(urlparse(self.url).query)
        if not 'watch' in params:
            raise NoStreamsError(self.url)
        channel = params['watch']

        if not RTMPStream.is_usable(self.session):
            raise PluginError(
                "rtmpdump is not usable but required by Picarto plugin")

        streams = {}
        streams["live"] = RTMPStream(
            self.session, {
                "rtmp": "rtmp://199.189.86.17/dsapp/{0}.flv".format(channel),
                "pageUrl": self.url,
                "live": True
            })
        return streams
Exemple #39
0
    def _get_rtmp_streams(self, text):
        match = re.search("streamer=(rtmp://.+?)&", text)
        if not match:
            raise PluginError(
                ("No RTMP streamer found on URL {0}").format(self.url))

        rtmp = match.group(1)

        match = re.search("<meta content=\"(http://.+?\.swf)\?", text)
        if not match:
            self.logger.warning(
                "Failed to get player SWF URL location on URL {0}", self.url)
        else:
            self.SWFURL = match.group(1)
            self.logger.debug("Found player SWF URL location {0}", self.SWFURL)

        match = re.search("<meta content=\"(.+)\" name=\"item-id\" />", text)
        if not match:
            raise PluginError(
                ("Missing channel item-id on URL {0}").format(self.url))

        res = http.get(self.APIURL.format(match.group(1), time()),
                       params=dict(output="json"))
        json = http.json(res)

        if not isinstance(json, list):
            raise PluginError("Invalid JSON response")

        rtmplist = {}

        for jdata in json:
            if "stream_name" not in jdata or "type" not in jdata:
                continue

            if "rtmp" not in jdata["type"]:
                continue

            playpath = jdata["stream_name"]

            if "token" in jdata and jdata["token"]:
                playpath += jdata["token"]

            if len(json) == 1:
                stream_name = "live"
            else:
                stream_name = jdata["stream_name"]

            rtmplist[stream_name] = RTMPStream(
                self.session, {
                    "rtmp": rtmp,
                    "pageUrl": self.url,
                    "swfVfy": self.SWFURL,
                    "playpath": playpath,
                    "live": True
                })

        return rtmplist
Exemple #40
0
 def _create_rtmp_stream(self, rtmp, playpath, live):
     return RTMPStream(
         self.session, {
             "rtmp": rtmp,
             "playpath": playpath,
             "pageUrl": self.url,
             "swfVfy": SWF_URL,
             "live": live
         })
Exemple #41
0
    def _get_streams(self):
        self.logger.debug("Fetching stream info")
        res = urlget(self.url)

        match = re.search("var current_channel = (.*);", res.text)
        if match:
            json = parse_json(match.group(1))
        else:
            raise NoStreamsError(self.url)

        if not isinstance(json, dict):
            raise PluginError("Invalid JSON response")
        elif not "streams" in json:
            raise NoStreamsError(self.url)

        if not RTMPStream.is_usable(self.session):
            raise PluginError("rtmpdump is not usable and required by Filmon plugin")

        match = re.search("var flash_config = (.*);", res.text)
        if match:
            config = parse_json(match.group(1))
            if "streamer" in config:
                self.SWFURL = urljoin(self.SWFURL, config["streamer"])

        streams = {}

        for stream in json["streams"]:
            if not ("url" in stream and "name" in stream):
                continue

            parsed = urlparse(stream["url"])

            if not parsed.scheme.startswith("rtmp"):
                continue

            if parsed.query:
                app = "{0}?{1}".format(parsed.path[1:], parsed.query)
            else:
                app = parsed.path[1:]

            name = stream["quality"]
            streams[name] = RTMPStream(self.session, {
                "rtmp": stream["url"],
                "pageUrl": self.url,
                "swfUrl": self.SWFURL,
                "playpath": stream["name"],
                "app": app,
                "live": True
            })

        return streams
Exemple #42
0
    def _get_streams_from_rtmp(self):
        password = self.options.get("password")
        module_info = self._get_module_info("channel", self.channel_id,
                                            password)
        if not module_info:
            raise NoStreamsError(self.url)

        providers = module_info.get("stream")
        if providers == "offline":
            raise NoStreamsError(self.url)
        elif not isinstance(providers, list):
            raise PluginError("Invalid stream info: {0}".format(providers))

        streams = {}
        for provider in filter(valid_provider, providers):
            provider_url = provider.get("url")
            provider_name = provider.get("name")
            provider_streams = provider.get("streams")

            for stream_index, stream_info in enumerate(provider_streams):
                stream = None
                stream_height = int(stream_info.get("height", 0))
                stream_name = stream_info.get("description")

                if not stream_name:
                    if stream_height:
                        if not stream_info.get("isTranscoded"):
                            stream_name = "{0}p+".format(stream_height)
                        else:
                            stream_name = "{0}p".format(stream_height)
                    else:
                        stream_name = "live"

                if stream_name in streams:
                    provider_name_clean = provider_name.replace("uhs_", "")
                    stream_name += "_alt_{0}".format(provider_name_clean)

                if provider_name.startswith("uhs_"):
                    stream = UHSStream(self.session, self.channel_id,
                                       self.url, provider_name,
                                       stream_index, password)
                elif (provider_url.startswith("rtmp") and
                      RTMPStream.is_usable(self.session)):
                        playpath = stream_info.get("streamName")
                        stream = self._create_rtmp_stream(provider_url,
                                                          playpath)

                if stream:
                    streams[stream_name] = stream

        return streams
    def _get_streams(self):
        # If email option given, try to login
        if self.options.get("email"):
            res = http.get(self.LOGINPAGEURL)
            match = re.search('<meta content="([^"]+)" name="csrf-token"', res.text)
            if not match:
                raise PluginError("Missing CSRF Token: " + self.LOGINPAGEURL)
            csrf_token = match.group(1)

            email = self.options.get("email")
            password = self.options.get("password")

            res = http.post(
                self.LOGINPOSTURL,
                data={
                    "authenticity_token": csrf_token,
                    "channel_id": "",
                    "commit": "Login",
                    "plan_id": "",
                    "session[email]": email,
                    "session[password]": password,
                    "utf8": "\xE2\x9C\x93",  # Check Mark Character
                },
            )

            self.logger.debug("Login account info: {0}", res.text)
            result = http.json(res)
            if result.get("email", "no-mail") != email:
                raise PluginError("Invalid account")

        res = http.get(self.url)

        streams = {}

        if RTMPStream.is_usable(self.session):
            try:
                rtmpstreams = self._get_rtmp_streams(res.text)
                streams.update(rtmpstreams)
            except PluginError as err:
                self.logger.error("Error when fetching RTMP stream info: {0}", str(err))
        else:
            self.logger.warning("rtmpdump is not usable, only HLS streams will be available")

        try:
            hlsstreams = self._get_hls_streams(res.text)
            streams.update(hlsstreams)
        except PluginError as err:
            self.logger.error("Error when fetching HLS stream info: {0}", str(err))

        return streams
Exemple #44
0
 def _get_streams(self):
     params = parse_qsd(urlparse(self.url).query)
     if not 'watch' in params:
         raise NoStreamsError(self.url)
     channel = params['watch']
     
     if not RTMPStream.is_usable(self.session):
         raise PluginError("rtmpdump is not usable but required by Picarto plugin")
     
     streams = {}
     streams["live"] = RTMPStream(self.session, {
         "rtmp": "rtmp://199.189.86.17/dsapp/{0}.flv".format(channel),
         "pageUrl": self.url,
         "live": True
     })
     return streams
Exemple #45
0
    def _get_streams(self):
        country_code = urlparse(self.url).netloc.split(".")[0]

        self.logger.debug("Fetching stream info")
        res = http.get(self.APIURL)
        json = http.json(res)

        if not isinstance(json, dict):
            raise PluginError("Invalid JSON response")
        elif not ("primary" in json or "secondary" in json):
            raise PluginError("Invalid JSON response")

        if not RTMPStream.is_usable(self.session):
            raise PluginError("rtmpdump is not usable and required by Euronews plugin")

        streams = {}

        self.logger.debug("Euronews Countries:{0}", " ".join(json["primary"].keys()))

        if not (country_code in json["primary"] or country_code in json["secondary"]):
            res = http.get(self.GEOIPURL)
            geo = http.json(res)
            if isinstance(json, dict) and "country_code" in geo:
                country_code = geo["country_code"].lower()
                if not (country_code in json["primary"] or country_code in json["secondary"]):
                    country_code = "en"
            else:
                country_code = "en"

        for site in ("primary", "secondary"):
            for quality in json[site][country_code]["rtmp_flash"]:
                stream = json[site][country_code]["rtmp_flash"][quality]
                name = quality + "k"
                if site == "secondary":
                    name += "_alt"
                streams[name] = RTMPStream(self.session, {
                    "rtmp": stream["server"],
                    "playpath" : stream["name"],
                    "swfUrl": self.SWFURL,
                    "live": True
                })

        if len(streams) == 0:
            raise NoStreamsError(self.url)

        return streams
Exemple #46
0
    def _get_streams_from_amf(self):
        if not RTMPStream.is_usable(self.session):
            raise NoStreamsError(self.url)

        res = urlget(AMF_URL.format(self.channel_id))

        try:
            packet = AMFPacket.deserialize(BytesIO(res.content))
        except (IOError, AMFError) as err:
            raise PluginError("Failed to parse AMF packet: {0}".format(err))

        for message in packet.messages:
            if message.target_uri == "/1/onResult":
                result = message.value
                break
        else:
            raise PluginError("No result found in AMF packet")

        streams = {}
        stream_name = result.get("streamName")
        if stream_name:
            cdn = result.get("cdnUrl") or result.get("fmsUrl")
            if cdn:
                stream = self._create_rtmp_stream(cdn, stream_name)

                if "videoCodec" in result and result["videoCodec"]["height"] > 0:
                    stream_name = "{0}p".format(int(result["videoCodec"]["height"]))
                else:
                    stream_name = "live"

                streams[stream_name] = stream
            else:
                self.logger.warning("Missing cdnUrl and fmsUrl from result")

        stream_versions = result.get("streamVersions")
        if stream_versions:
            for version, info in stream_versions.items():
                stream_version_cdn = info.get("streamVersionCdn", {})

                for name, cdn in filter(valid_cdn, stream_version_cdn.items()):
                    stream = self._create_rtmp_stream(cdn["cdnStreamUrl"],
                                                      cdn["cdnStreamName"])
                    stream_name = "live_alt_{0}".format(name)
                    streams[stream_name] = stream

        return streams
Exemple #47
0
    def _get_streams(self):
        match = re.search("/v/(\d+)", self.url)
        if not match:
            return

        vid = match.group(1)
        params = dict(client_name="Bambuser AS2", context="b_broadcastpage",
                      raw_user_input=1, api_key="005f64509e19a868399060af746a00aa",
                      vid=vid, r=random.random())

        self.logger.debug("Fetching stream info")
        res = http.get(PLAYER_URL, params=params)
        json = http.json(res)

        error = json and json.get("errorCode")
        if error:
            error = error and json.get("error")
            self.logger.error(error)
            return

        json = verifyjson(json, "result")
        playpath = verifyjson(json, "id")
        url = verifyjson(json, "url")
        (width, height) = verifyjson(json, "size").split("x")
        name = "{0}p".format(height)

        parsed = urlparse(url)
        streams  = {}

        if parsed.scheme.startswith("rtmp"):
            if not RTMPStream.is_usable(self.session):
                raise PluginError("rtmpdump is not usable and required by Bambuser plugin")
            streams[name] = RTMPStream(self.session, {
                "rtmp": url,
                "playpath": playpath,
                "pageUrl": self.url,
                "live": True
            })
        elif parsed.scheme == "http":
            streams[name] = HTTPStream(self.session, url)

        return streams
Exemple #48
0
    def _get_streams(self):
        if not RTMPStream.is_usable(self.session):
            raise PluginError("rtmpdump is not usable and required by Filmon_us plugin")

        streams = {}

        try:
            # history video
            if "filmon.us/history" in self.url or "filmon.us/video/history/hid" in self.url:
                streams['default'] = self._get_history()
            # uploaded video
            elif "filmon.us/video" in self.url:
                streams['default'] = self._get_stream_upload()
            # live video
            else:
                streams['default'] = self._get_stream_live()
        except NoStreamsError:
            pass

        return streams
Exemple #49
0
    def _get_streams(self):
        res = urlget(self.url)
        streams = {}

        if RTMPStream.is_usable(self.session):
            try:
                rtmpstreams = self._get_rtmp_streams(res.text)
                streams.update(rtmpstreams)
            except PluginError as err:
                self.logger.error("Error when fetching RTMP stream info: {0}", str(err))
        else:
            self.logger.warning("rtmpdump is not usable, only HLS streams will be available")

        try:
            hlsstreams = self._get_hls_streams(res.text)
            streams.update(hlsstreams)
        except PluginError as err:
            self.logger.error("Error when fetching HLS stream info: {0}", str(err))

        return streams
    def _get_streams(self):
        channelname = urlparse(self.url).path.rstrip("/").rpartition("/")[-1].lower()
        streams = {}

        if RTMPStream.is_usable(self.session):
            try:
                rtmpstreams = self._get_rtmp_streams(channelname)
                streams.update(rtmpstreams)
            except PluginError as err:
                self.logger.error("Error when fetching RTMP stream info: {0}", str(err))
        else:
            self.logger.warning("rtmpdump is not usable, only HLS streams will be available")

        try:
            hlsstreams = self._get_hls_streams(channelname)
            streams.update(hlsstreams)
        except PluginError as err:
            self.logger.error("Error when fetching HLS stream info: {0}", str(err))

        return streams
Exemple #51
0
    def _get_streams(self):
        self.channelname = self._get_channel_name(self.url)

        if not self.channelname:
            raise NoStreamsError(self.url)

        streams = {}

        if RTMPStream.is_usable(self.session):
            try:
                rtmpstreams = self._get_rtmp_streams()

                for name, stream in rtmpstreams.items():
                    if "iphone" in name:
                        name = name.replace("iphone", "mobile_")

                    streams[name] = stream
            except PluginError as err:
                self.logger.error("Error when fetching RTMP stream info: {0}", str(err))
        else:
            self.logger.warning("rtmpdump is not usable, only HLS streams will be available")

        try:
            hlsstreams = self._get_hls_streams()

            for name, stream in hlsstreams.items():
                if name in ("high", "low"):
                    name = "mobile_{0}".format(name)

                if "iphone" in name:
                    name = name.replace("iphone", "mobile_")

                if name in streams:
                    streams[name] = [streams[name], stream]
                else:
                    streams[name] = stream

        except PluginError as err:
            self.logger.error("Error when fetching HLS stream info: {0}", str(err))

        return streams
Exemple #52
0
    def _get_streams(self):
        if not RTMPStream.is_usable(self.session):
            raise PluginError("rtmpdump is not usable and required by Hashd plugin")

        self.logger.debug("Fetching stream info")
        res = http.get(self.url.rstrip("/").lower()+".json?first=true")
        json = http.json(res)

        if not isinstance(json, dict):
            raise PluginError("Invalid JSON response")
        elif not ("live" in json or "file" in json):
            raise PluginError("Invalid JSON response")

        if "file" in json:
            streams = self._parse_vod(json)
        elif json["live"]:
            streams = self._parse_live(json)
        else:
            raise NoStreamsError(self.url)

        return streams
    def _get_streams(self):
        if not RTMPStream.is_usable(self.session):
            raise PluginError("rtmpdump is not usable and required by Furstream plugin")

        self.logger.debug("Fetching stream info")
        res = http.get(self.url)

        match = re.search("rtmp://(?:(?!\").)*", res.text)
        if match:
            self.logger.debug("Stream URL: " + match.group(0))
            rtmp = match.group(0)
        else:
            return

        streams = {}
        streams["live"] = RTMPStream(self.session, {
            "rtmp": rtmp,
            "pageUrl": self.url,
            "live": True
        })

        return streams
Exemple #54
0
    def _get_live_streams(self):
        self.channel_id = self._get_channel_id(self.url)

        if not self.channel_id:
            raise NoStreamsError(self.url)

        streams = defaultdict(list)

        if not RTMPStream.is_usable(self.session):
            self.logger.warning("rtmpdump is not usable. "
                                "Not all streams may be available.")

        if HAS_LIBRTMP:
            desktop_streams = self._get_streams_from_rtmp
        else:
            self.logger.warning("python-librtmp is not installed. "
                                "Not all streams may be available.")
            desktop_streams = self._get_streams_from_amf

        try:
            for name, stream in desktop_streams().items():
                streams[name].append(stream)
        except PluginError as err:
            self.logger.error("Unable to fetch desktop streams: {0}", err)
        except NoStreamsError:
            pass

        try:
            mobile_streams = self._get_hls_streams(wait_for_transcode=not streams)
            for name, stream in mobile_streams.items():
                streams[name].append(stream)
        except PluginError as err:
            self.logger.error("Unable to fetch mobile streams: {0}", err)
        except NoStreamsError:
            pass

        return streams
Exemple #55
0
    def _get_streams(self):
        if not RTMPStream.is_usable(self.session):
            raise PluginError("rtmpdump is not usable and required by Cybergame plugin")

        if "/videos/" in self.url:
            return self._get_vod_streams()

        self.logger.debug("Fetching live stream info")
        res = http.get(self.url)

        match = re.search("channel=([^\"]+)", res.text)
        if not match:
            raise NoStreamsError(self.url)

        channelname = match.group(1)

        res = http.get(CONFIG_URL, params=dict(c=channelname, ports="y"))
        json = http.json(res)
        servers = json.get("servers")
        if not servers:
            raise NoStreamsError(self.url)

        alternative = ""
        streams  = {}

        for server in servers:
            srv, port = server.split(":")
            params = dict(channel=channelname, server=srv, port=port)
            tmpstreams = self._get_rtmp_streams(params, alternative)
            streams.update(tmpstreams)
            if not alternative:
                alternative = "_alt"
            else:
                break

        return streams
Exemple #56
0
    def _get_streaminfo(self, channelname):
        def clean_tag(tag):
            if tag[0] == "_":
                return tag[1:]
            else:
                return tag


        chansub = None
        if self.options.get("cookie") is not None:
            self.logger.debug("Attempting to authenticate using cookie")

            metadata = self._get_metadata(channelname)
            chansub = metadata["access_guid"]

            if "login" in metadata and metadata["login"] is not None:
                self.logger.debug("Successfully logged in as {0}", metadata["login"])


        randomp = int(random.random() * 999999)
        url = self.StreamInfoURL.format(channelname, randomp, chansub)

        self.logger.debug("Fetching stream info")
        data = urlget(url)

        # fix invalid xml
        data = re.sub(b"<(\d+)", b"<_\g<1>", data)
        data = re.sub(b"</(\d+)", b"</_\g<1>", data)

        streams = {}

        try:
            dom = xml.dom.minidom.parseString(data)
        except Exception as err:
            raise PluginError(("Unable to parse config XML: {0})").format(err))

        nodes = dom.getElementsByTagName("nodes")[0]

        self.logger.debug("Verifying SWF: {0}", self.SWFURL)
        swfhash, swfsize = swfverify(self.SWFURL)

        for node in nodes.childNodes:
            info = {}
            for child in node.childNodes:
                info[child.tagName] = self._get_node_text(child)

            stream = RTMPStream(self.session, {
                "rtmp": ("{0}/{1}").format(info["connect"], info["play"]),
                "swfUrl": self.SWFURL,
                "swfhash": swfhash,
                "swfsize": swfsize,
                "live": True
            })

            sname = clean_tag(node.tagName)

            if "token" in info:
                stream.params["jtv"] = info["token"]
            else:
                self.logger.warning("No token found for stream {0}, this stream may fail to play", sname)

            streams[sname] = stream

        return streams
Exemple #57
0
    def _get_streams(self):
        channelid = self._get_channel_id(self.url)

        if not channelid:
            raise NoStreamsError(self.url)


        self.logger.debug("Fetching stream info")
        res = urlget(self.AMFURL.format(channelid))

        try:
            packet = AMFPacket.deserialize(BytesIO(res.content))
        except (IOError, AMFError) as err:
            raise PluginError(("Failed to parse AMF packet: {0}").format(str(err)))

        result = None
        for message in packet.messages:
            if message.target_uri == "/1/onResult":
                result = message.value
                break

        if not result:
            raise PluginError("No result found in AMF packet")

        streams = {}

        if RTMPStream.is_usable(self.session) and "streamName" in result:
            if "cdnUrl" in result:
                cdn = result["cdnUrl"]
            elif "fmsUrl" in result:
                cdn = result["fmsUrl"]
            else:
                self.logger.warning("Missing cdnUrl and fmsUrl from result")
                return streams

            if "videoCodec" in result and result["videoCodec"]["height"] > 0:
                streamname = "{0}p".format(int(result["videoCodec"]["height"]))
            else:
                streamname = "live"

            streams[streamname] = self._create_stream(cdn, result["streamName"])

        if RTMPStream.is_usable(self.session) and "streamVersions" in result:
            for version, info in result["streamVersions"].items():
                if "streamVersionCdn" in info:
                    for name, cdn in info["streamVersionCdn"].items():
                        if "cdnStreamUrl" in cdn and "cdnStreamName" in cdn:
                            cdnname = "live_alt_{0}".format(name)
                            streams[cdnname] = self._create_stream(cdn["cdnStreamUrl"],
                                                                   cdn["cdnStreamName"])

        # On some channels the AMF API will not return any streams,
        # attempt to access the HLS playlist directly instead.
        #
        # HLS streams are created on demand, so we may have to wait
        # for a transcode to be started.
        attempts = 10
        playlist_url = result.get("liveHttpUrl",
                                  self.HLSPlaylistURL.format(channelid))

        while attempts:
            try:
                hls_streams = HLSStream.parse_variant_playlist(self.session,
                                                               playlist_url)
                streams.update(hls_streams)
            except IOError:
                # Channel is probably offline
                break

            if streams:
                break

            attempts -= 1
            sleep(3)

        return streams
Exemple #58
0
    def _get_streams(self):
        channelname = urlparse(self.url).path.rstrip("/").rpartition("/")[-1].lower()
        self.logger.debug("Fetching stream info")

        headers = {
            "Referer": self.SWFURL
        }

        form = dict(cid=channelname, watchTime="0",
                    firstConnect="1", ip="NaN")

        res = urlopen(self.APIURL, data=form, headers=headers)

        params = parse_qsd(res.text)

        if "0" in params and int(params["0"]) <= 0:
            raise PluginError("Server refused to send required parameters.")

        rtmp = params["10"]
        playpath = params["11"]
        multibitrate = int(params["20"])
        premiumuser = params["5"]
        blocktype = int(params["13"])

        if blocktype != 0:
            if blocktype == 1:
                blocktime = params["14"]
                reconnectiontime = params["16"]
                msg = ("You have crossed free viewing limit. ",
                       "You have been blocked for %s minutes. " % blocktime,
                       "Try again in %s minutes." % reconnectiontime)
                raise PluginError(msg)
            elif blocktype == 11:
                raise PluginError("No free slots available.")

        if "73" in params:
            token = params["73"]
        else:
            raise PluginError("Server seems busy, please try after some time.")

        if not RTMPStream.is_usable(self.session):
            raise PluginError("rtmpdump is not usable and required by Weeb plugin")

        streams = {}
        stream_name = "sd"

        if multibitrate:
            streams[stream_name] = RTMPStream(self.session, {
                "rtmp": "{0}/{1}".format(rtmp, playpath),
                "pageUrl": self.url,
                "swfVfy": self.SWFURL,
                "weeb": token,
                "live": True
            })
            playpath += "HI"
            stream_name = "hd"

        streams[stream_name] = RTMPStream(self.session, {
            "rtmp": "{0}/{1}".format(rtmp, playpath),
            "pageUrl": self.url,
            "swfVfy": self.SWFURL,
            "weeb": token,
            "live": True
        })

        return streams