def _get_streams(self): self.logger.debug("Fetching stream info") res = urlget(self.url) match = re.search("\"User_channelid\".+?value=\"(.+?)\"", res.text) if not match: raise NoStreamsError(self.url) headers = { "Referer": self.url } res = urlget(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
def _get_streams(self): res = urlget(self.url) channel_id = self._find_channel_id(res.text) if not channel_id: return stream_id = self._get_stream_id(channel_id) if not stream_id: return res = urlget(STREAM_API_URL.format(stream_id), params=dict(format="all")) json = res_json(res) data = verifyjson(json, "data") items = verifyjson(data, "items") streams = {} for stream in filter(valid_stream, items): parser = STREAM_TYPES[stream["format"]] try: streams.update(parser(self.session, stream["url"])) except IOError as err: if not re.search(r"(404|400) Client Error", str(err)): self.logger.error("Failed to extract {0} streams: {1}", stream["format"].upper(), err) return streams
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
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 = urlget(swfurl) swf = swfdecompress(res.content) match = re.search("customURL[^h]+(https://.*?)\\\\", swf) if not match: raise NoStreamsError(self.url) res = urlget(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)
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
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+)&s=(.+?)&", res.text) if not match: raise NoStreamsError(self.url) channelname = "{0}?{1}".format(match.group(2), 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
def _choose_server(self, json): res = urlget(self.GEOIPURL) loc = res_json(res) loc = [loc["latitude"], loc["longitude"]] sel_dist = float("inf") i = 0 primary = -1 secondary = -1 for server in json["server"]: res = urlget(self.GEOURL+server["server"]["name"]+"&sensor=false") cord = res_json(res) cord = [cord["results"][0]["geometry"]["location"]["lat"], cord["results"][0]["geometry"]["location"]["lng"]] cur_dist = self._distance(loc, cord) if cur_dist < sel_dist: sel_dist = cur_dist if server["server"]["used"] < 90: # nearest server with load < 90% primary = i else: # nearest server with load > 90% secondary = i i += 1 if primary == -1: # if all servers have load over 90% use nearest one return secondary return primary
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/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, redirect=True) return streams
def _get_streams(self): self.logger.debug("Fetching stream info") media_is_live = 0 match = re.search(r".*hitbox.tv/([^/]*)/?(\d+)?", self.url) if not match: raise NoStreamsError(self.url) stream_name, media_id = match.groups() if stream_name != "video": res = urlget(LIVE_API.format(stream_name)) json = res_json(res) livestream = verifyjson(json, "livestream") media_id = verifyjson(livestream[0], "media_id") media_is_live = int(verifyjson(livestream[0], "media_is_live")) if not media_is_live: raise NoStreamsError(self.url) media_type = "live" if media_is_live else "video" res = urlget(PLAYER_API.format(media_type, media_id)) json = res_json(res) clip = verifyjson(json, "clip") live = verifyjson(clip, "live") bitrates = verifyjson(clip, "bitrates") streams = {} if live: for bitrate in bitrates: connection_provider = clip.get("connectionProvider", "clustering") plugins = verifyjson(json, "plugins") provider_plugin = verifyjson(plugins, connection_provider) swf = verifyjson(provider_plugin, "url") rtmp = verifyjson(provider_plugin, "netConnectionUrl") quality = self._get_quality(verifyjson(bitrate, "label")) url = verifyjson(bitrate, "url") streams[quality] = RTMPStream( self.session, { "rtmp": rtmp, "pageUrl": self.url, "playpath": url, "swfVfy": SWF_BASE + swf, "live": True }) else: for bitrate in bitrates: base_url = verifyjson(clip, "baseUrl") url = verifyjson(bitrate, "url") quality = self._get_quality(verifyjson(bitrate, "label")) streams[quality] = HTTPStream(self.session, base_url + "/" + url) return streams
def _get_streams(self): self.logger.debug("Fetching stream info") media_is_live = 0 match = re.search(r".*hitbox.tv/([^/]*)/?(\d+)?", self.url) if not match: raise NoStreamsError(self.url) stream_name, media_id = match.groups() if stream_name != "video": res = urlget(LIVE_API.format(stream_name)) json = res_json(res) livestream = verifyjson(json, "livestream") media_id = verifyjson(livestream[0], "media_id") media_is_live = int(verifyjson(livestream[0], "media_is_live")) if not media_is_live: raise NoStreamsError(self.url) media_type = "live" if media_is_live else "video" res = urlget(PLAYER_API.format(media_type, media_id)) json = res_json(res) clip = verifyjson(json, "clip") live = verifyjson(clip, "live") bitrates = verifyjson(clip, "bitrates") streams = {} if live: for bitrate in bitrates: connection_provider = clip.get("connectionProvider", "clustering") plugins = verifyjson(json, "plugins") provider_plugin = verifyjson(plugins, connection_provider) swf = verifyjson(provider_plugin, "url") rtmp = verifyjson(provider_plugin, "netConnectionUrl") quality = self._get_quality(verifyjson(bitrate, "label")) url = verifyjson(bitrate, "url") streams[quality] = RTMPStream(self.session, { "rtmp": rtmp, "pageUrl": self.url, "playpath": url, "swfVfy": SWF_BASE + swf, "live": True }) else: for bitrate in bitrates: base_url = verifyjson(clip, "baseUrl") url = verifyjson(bitrate, "url") quality = self._get_quality(verifyjson(bitrate, "label")) streams[quality] = HTTPStream(self.session, base_url + "/" + url) return streams
def grabLivePage(self, gomtvLiveURL): response = urlget(gomtvLiveURL, opener=self.opener) # If a special event occurs, we know that the live page response # will just be some JavaScript that redirects the browser to the # real live page. We assume that the entireity of this JavaScript # is less than 200 characters long, and that real live pages are # more than that. if len(response) < 200: # Grabbing the real live page URL gomtvLiveURL = self.getEventLivePageURL(gomtvLiveURL, response) response = urlget(gomtvLiveURL, opener=self.opener) return response
def _get_stream_info(self, url): res = urlget(url) config = self._find_config(res.text) if not config: watch_match = re.search("href=\"/(watch\?v=.+?)\"", res.text) if watch_match: watch_url = "http://youtube.com/{0}".format(watch_match.group(1)) res = urlget(watch_url) config = self._find_config(res.text) if config: return parse_json(config, "config JSON")
def _get_stream_info(self, url): res = urlget(url) config = self._find_config(res.text) if not config: watch_match = re.search("href=\"/(watch\?v=.+?)\"", res.text) if watch_match: watch_url = "http://youtube.com/%s" % watch_match.group(1) res = urlget(watch_url) config = self._find_config(res.text) if config: return parse_json(config, "config JSON")
def _get_vod_streams(self): res = urlget(self.url) flashvars = re.search("FlashVars=\"(.+?)\"", res.text) if not flashvars: raise PluginError("Unable to find flashvars on page") flashvars = parse_qs(flashvars.group(1)) for var in ("vjoinid", "conid", "leagueid"): if not var in flashvars: raise PluginError( ("Missing key '{0}' in flashvars").format(var)) streams = {} qualities = ["SQ", "HQ"] for quality in qualities: params = dict(leagueid=flashvars["leagueid"][0], vjoinid=flashvars["vjoinid"][0], conid=flashvars["conid"][0], title="", ref="", tmpstamp=int(time.time()), strLevel=quality) res = urlget(self.GOXVODURL, params=params, session=self.rsession) if res.text != "1002" and len(res.text) > 0: gox = self._parse_gox_file(res.text) entry = gox[0] nokey = False for var in ("NODEIP", "NODEID", "UNO", "USERIP"): if not var in entry: nokey = True if nokey: self.logger.warning( "Unable to fetch key, make sure that you have access to this VOD" ) continue key = self._check_vod_key(entry["NODEIP"], entry["NODEID"], entry["UNO"], entry["USERIP"]) streams[quality.lower()] = HTTPStream( self.session, gox[0]["REF"], params=dict(key=key), headers=self.StreamHeaders) return streams
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
def _get_live_page(self, url): res = urlget(url, session=self.rsession) # If a special event occurs, we know that the live page response # will just be some JavaScript that redirects the browser to the # real live page. We assume that the entireity of this JavaScript # is less than 200 characters long, and that real live pages are # more than that. if len(res.text) < 200: # Grabbing the real live page URL url = self._parse_event_url(url, res.text) res = urlget(url, session=self.rsession) return res
def _get_hls_streams(self): url = self.HLSStreamTokenURL.format(self.channelname) try: res = urlget(url, params=dict(type="any", connection="wifi"), exception=IOError) except IOError: self.logger.debug("HLS streams not available") return {} json = res_json(res, "stream token JSON") if not isinstance(json, list): raise PluginError("Invalid JSON response") if len(json) == 0: raise PluginError("No stream token in JSON") streams = {} token = verifyjson(json[0], "token") hashed = hmac.new(self.HLSStreamTokenKey, bytes(token, "utf8"), sha1) fulltoken = hashed.hexdigest() + ":" + token url = self.HLSSPlaylistURL.format(self.channelname) try: params = dict(token=fulltoken, hd="true") playlist = HLSStream.parse_variant_playlist(self.session, url, params=params) except IOError as err: raise PluginError(err) return playlist
def _get_streams(self): parsed = urlparse(self.url) if parsed.fragment: channelid = parsed.fragment else: channelid = parsed.path.rpartition("view/")[-1] if not channelid: raise NoStreamsError(self.url) channelid = channelid.lower().replace("/", "_") self.logger.debug("Fetching stream info") res = urlget(self.APIURL.format(channelid)) json = res_json(res) if not isinstance(json, dict): raise PluginError("Invalid JSON response") elif not ("success" in json and "payload" in json): raise PluginError("Invalid JSON response") elif json["success"] == False: raise NoStreamsError(self.url) streams = {} streams["live"] = HTTPStream(self.session, json["payload"]) return streams
def _get_streams(self): self.rsession = requests.session(prefetch=True) options = self.options if options.get("cookie"): self._authenticate(cookies=options.get("cookie")) else: self._authenticate(options.get("username"), options.get("password")) streams = {} qualities = ["HQ", "SQ", "HQTest", "SQTest"] res = self._get_live_page(self.url) urls = self._find_stream_urls(res.text) for quality in qualities: for url in urls: # Grab the response of the URL listed on the Live page for a stream url = url.format(quality=quality) res = urlget(url, session=self.rsession) # The response for the GOX XML if an incorrect stream quality is chosen is 1002. if res.text != "1002" and len(res.text) > 0: streamurl = self._parse_gox_file(res.text) streams[quality.lower()] = HTTPStream(self.session, streamurl, headers=self.StreamHeaders) return streams
def _parse_smil(self, url): res = urlget(url) try: dom = xml.dom.minidom.parseString(res.text) except Exception as err: raise PluginError(("Unable to parse config XML: {0})").format(err)) httpbase = None streams = {} for meta in dom.getElementsByTagName("meta"): if meta.getAttribute("name") == "httpBase": httpbase = meta.getAttribute("content") break if not httpbase: raise PluginError("Missing HTTP base in SMIL") for video in dom.getElementsByTagName("video"): url = "{0}/{1}".format(httpbase, video.getAttribute("src")) bitrate = int(video.getAttribute("system-bitrate")) streams[bitrate] = AkamaiHDStream(self.session, url) return streams
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 = AMF0Packet.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 "liveHttpUrl" in result: try: hlsstreams = HLSStream.parse_variant_playlist(self.session, result["liveHttpUrl"]) streams.update(hlsstreams) except IOError as err: self.logger.warning("Failed to get variant playlist: {0}", err) if "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 "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: streams["cdn_" + name] = self._create_stream(cdn["cdnStreamUrl"], cdn["cdnStreamName"]) return streams
def find(self, channel, password=None, **extra_params): url = self.url(USHER_FIND_PATH, channel) params = dict(p=int(random() * 999999), type="any", private_code=password or "null", **extra_params) return res_json(urlget(url, params=params), "stream info JSON")
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
def _get_hls_streams(self): url = self.HLSStreamTokenURL.format(self.channelname) try: res = urlget(url, params=dict(type="any", connection="wifi"), exception=IOError) except IOError: return {} if not isinstance(res.json, list): raise PluginError("Stream info response is not JSON") if len(res.json) == 0: raise PluginError("No stream token in JSON") streams = {} token = verifyjson(res.json[0], "token") hashed = hmac.new(self.HLSStreamTokenKey, bytes(token, "utf8"), sha1) fulltoken = hashed.hexdigest() + ":" + token url = self.HLSSPlaylistURL.format(self.channelname) try: params = dict(token=fulltoken, hd="true") playlist = HLSStream.parse_variant_playlist(self.session, url, params=params) except IOError as err: raise PluginError(err) return playlist
def _get_streams(self): res = urlget(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
def _get_streams(self): self.rsession = requests.session(prefetch=True) options = self.options if options.get("cookie"): self._authenticate(cookies=options.get("cookie")) else: self._authenticate(options.get("username"), options.get("password")) streams = {} qualities = ["HQ", "SQ", "HQTest", "SQTest"] res = self._get_live_page(self.url) urls = self._find_stream_urls(res.text) for quality in qualities: for url in urls: # Grab the response of the URL listed on the Live page for a stream url = url.format(quality=quality) res = urlget(url, session=self.rsession) # The response for the GOX XML if an incorrect stream quality is chosen is 1002. if res.text != "1002" and len(res.text) > 0: streamurl = self._parse_gox_file(res.text) streams[quality.lower()] = HTTPStream( self.session, streamurl, headers=self.StreamHeaders) return streams
def _get_streams(self): res = urlget(self.PlayerURL) 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
def _get_streams_from_id(self, stream_id): res = urlget(CONFIG_URL, params=dict(id=stream_id)) config = res_json(res) media = verifyjson(config, "media") if not (media and isinstance(media, list)): return streams = {} media = media[0] hds_manifest = media.get("name") hls_manifest = media.get("hlsUrl") if hds_manifest: try: hds_streams = HDSStream.parse_manifest(self.session, hds_manifest) streams.update(hds_streams) except IOError as err: if not re.search(r"(404|400) Client Error", str(err)): self.logger.error("Failed to parse HDS manifest: {0}", err) if hls_manifest: try: hls_streams = HLSStream.parse_variant_playlist(self.session, hls_manifest, nameprefix="mobile_") streams.update(hls_streams) except IOError as err: if not re.search(r"(404|400) Client Error", str(err)): self.logger.error("Failed to parse HLS playlist: {0}", err) return streams
def _get_streams(self): def get_amf_value(data, key): pattern = ("{0}\x02..(.*?)\x00").format(key) match = re.search(bytes(pattern, "ascii"), data) if match: return str(match.group(1), "ascii") streams = {} channelid = self._get_channel_id(self.url) if not channelid: raise NoStreamsError(self.url) self.logger.debug("Fetching stream info") data = urlget(self.AMFURL.format(channelid)) playpath = get_amf_value(data, "streamName") cdnurl = get_amf_value(data, "cdnUrl") fmsurl = get_amf_value(data, "fmsUrl") if playpath: stream = RTMPStream(self.session, { "rtmp": ("{0}/{1}").format(cdnurl or fmsurl, playpath), "pageUrl": self.url, "swfUrl": self.SWFURL, "live": True }) streams["live"] = stream return streams
def _find_broadcast(self, username): res = urlget(CHANNEL_URL, headers=HEADERS, params=dict(szBjId=username)) match = re.search(r"<thumb>.+\/(\d+)\.gif</thumb>", res.text) if match: return match.group(1)
def get_live_streams(self): res = self._get_live_page(self.res) match = re.search("this\.playObj = ({.+?})", res.text, re.DOTALL) if not match: raise NoStreamsError(self.url) flashvars = parse_json(match.group(1), "playObj JSON") match = re.search("goxkey=([A-z0-9]+)", res.text) if not match: raise NoStreamsError(self.url) flashvars["goxkey"] = match.group(1) flashvars["target"] = "live" streams = {} for strlevel in self.LiveQualityLevels: params = self._create_gox_params(flashvars, strlevel, "live") res = urlget(self.GOXURL, params=params, session=self.rsession) gox = GOXFile(res.text) for entry in gox.entries: streams[strlevel.lower()] = HTTPStream(self.session, entry.ref[0], headers=self.StreamHeaders) break return streams
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 = AMF0Packet.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 "liveHttpUrl" in result: try: hlsstreams = HLSStream.parse_variant_playlist( self.session, result["liveHttpUrl"]) streams.update(hlsstreams) except IOError as err: self.logger.warning("Failed to get variant playlist: {0}", err) if "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 "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: streams["cdn_" + name] = self._create_stream( cdn["cdnStreamUrl"], cdn["cdnStreamName"]) return streams
def _get_streams(self): self.rsession = requests.session() options = self.options if options.get("cookie"): self._authenticate(cookies=options.get("cookie")) else: self._authenticate(options.get("username"), options.get("password")) res = urlget(self.url, session=self.rsession) player = GomTV3(self.url, res, self.rsession) streams = {} if "/vod/" in self.url: return player.get_vod_streams() else: try: streams.update(player.get_live_streams()) except NoStreamsError: pass try: streams.update(player.get_alt_live_streams()) except NoStreamsError: pass try: streams.update(player.get_limelight_live_streams()) except NoStreamsError: pass return streams
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
def _get_streams(self): self.logger.debug("Fetching stream info") res = urlget(self.url, params=dict(output="json")) json = res_json(res) if not isinstance(json, dict): raise PluginError("Invalid JSON response") streams = {} video = verifyjson(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
def _get_streams(self): self.logger.debug("Fetching stream info") res = urlget(self.url) match = re.search("var info = (.*);", res.text) if not match: raise NoStreamsError(self.url) json = parse_json(match.group(1)) if not isinstance(json, dict): return ios_url = json.get("ios_url") swf_url = json.get("swf_url") streams = {} if ios_url: hls = HLSStream.parse_variant_playlist(self.session, ios_url) streams.update(hls) if swf_url: try: streams["live"] = self._get_rtmp_streams(swf_url) except NoStreamsError: pass return streams
def _get_channel_info(self, url): self.logger.debug("Fetching channel info") res = urlget(url) data = res.text channelid = None swfurl = None match = re.search('flashvars.config = "livecfg/(\d+)', data) if match: channelid = int(match.group(1)) match = re.search("document.location.hash='/live/(\d+)'", data) if match: channelid = int(match.group(1)) match = re.search("xajax_load_live_config\((\d+),", data) if match: channelid = int(match.group(1)) match = re.search("""swfobject.embedSWF\(\n.+"(.+)", "player",""", data) if match: swfurl = match.group(1) return (channelid, swfurl)
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 _authenticate(self, username=None, password=None, cookies=None): if (username is None or password is None) and cookies is None: raise PluginError("GOMTV.net requires a username and password or a cookie") if cookies is not None: for cookie in cookies.split(";"): try: name, value = cookie.split("=") except ValueError: continue self.rsession.cookies[name.strip()] = value.strip() self.logger.info("Attempting to authenticate with cookies") else: form = dict(cmd="login", rememberme="1", mb_username=username, mb_password=password) self.logger.info("Attempting to authenticate with username and password") urlopen(self.LoginURL, data=form, headers=self.LoginHeaders, session=self.rsession) res = urlget(self.LoginCheckURL, session=self.rsession) if "Please need login" in res.text: raise PluginError("Authentication failed") if "SES_USERNICK" in self.rsession.cookies: username = self.rsession.cookies["SES_USERNICK"] self.logger.info(("Successfully logged in as {0}").format(username))
def get_live_streams(self): res = self._get_live_page(self.res) match = re.search("flashvars\s+=\s+({.+?});", res.text) if not match: raise NoStreamsError(self.url) flashvars = parse_json(match.group(1), "flashvars JSON") flashvars["uip"] = self._get_user_ip() levels = re.findall("setFlashLevel\((\d+)\);", res.text) streams = {} for level in levels: params = self._create_gox_params(flashvars, level) res = urlget(self.GOXLiveURL, params=params, session=self.rsession) gox = GOXFile(res.text) for entry in gox.filter_entries("live"): try: s = HDSStream.parse_manifest(self.session, entry.ref[0]) streams.update(s) except IOError: self.logger.warning("Unable to parse manifest") break return streams
def _get_streams(self): options = self.options # Setting urllib up so that we can store cookies self.cookiejar = cookielib.LWPCookieJar() self.opener = urllib.build_opener(urllib.HTTPCookieProcessor(self.cookiejar)) if options.get("cookie"): self.authenticate(cookie=options.get("cookie")) else: self.authenticate(options.get("username"), options.get("password")) streams = {} qualities = ["HQ", "SQ", "HQTest", "SQTest"] streamChoice = "both" response = self.grabLivePage(self.url) goxUrls = [] validGoxFound = False failedGoxAll = False for quality in qualities: urls = self.parseHTML(response, quality) for url in urls: # Grab the response of the URL listed on the Live page for a stream goxFile = urlget(url, opener=self.opener) # The response for the GOX XML if an incorrect stream quality is chosen is 1002. if goxFile != "1002" and goxFile != "": streamUrl = self.parseStreamURL(goxFile) req = urllib.Request(streamUrl, headers={"User-Agent": "KPeerClient"}) streams[quality] = HTTPStream(self.session, req) validGoxFound = True return streams
def _get_streams(self, type): if type not in (None, StreamType.HTTP): return {} self.rsession = requests.session(prefetch=True) options = self.options if options.get("cookie"): self._authenticate(cookies=options.get("cookie")) else: self._authenticate(options.get("username"), options.get("password")) streams = {} qualities = ["HQ", "SQ", "HQTest", "SQTest"] res = self._get_live_page(self.url) goxurl = self._find_gox_url(res.text) if not goxurl: raise PluginError("Unable to find GOX URL") for quality in qualities: # Grab the response of the URL listed on the Live page for a stream url = goxurl.format(quality=quality) res = urlget(url, session=self.rsession) # The response for the GOX XML if an incorrect stream quality is chosen is 1002. if res.text != "1002" and len(res.text) > 0: streamurl = self._parse_gox_file(res.text) streams[quality.lower()] = HTTPStream(self.session, streamurl, headers=self.StreamHeaders) return streams
def download_chunk(self, chunk_id): self.stream.logger.debug("[{0}] Downloading chunk".format(chunk_id)) url = self.format_chunk_url(chunk_id) attempts = 3 while attempts and self.running: try: res = urlget(url, stream=True, exception=IOError, timeout=10) break except IOError as err: self.stream.logger.error("[{0}] Failed to open chunk: {1}".format( chunk_id, err)) attempts -= 1 else: return while self.running: try: data = res.raw.read(8192) except IOError as err: self.stream.logger.error("[{0}] Failed to read chunk {1}".format( chunk_id, err)) break if not data: break if not self.header_written: flv_header = Header(has_video=True, has_audio=True) self.stream.buffer.write(flv_header.serialize()) self.header_written = True self.stream.buffer.write(data)
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
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, 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
def _get_streams(self): res = urlget(self.url, headers=HEADERS) match = re.search(URL_REGEX, res.text) if match: url = match.group(0) plugin = self.session.resolve_url(url) return plugin.get_streams()
def _get_channel_id(self, url): match = re.search("ustream.tv/embed/(\d+)", url) if match: return int(match.group(1)) match = re.search("\"cid\":(\d+)", urlget(url).text) if match: return int(match.group(1))