def process_module_info(self): if self.closed: return result = self.fetch_module_info() if not result: return providers = result.get("stream") if providers == "offline": self.logger.debug("Stream went offline") self.close() return elif not isinstance(providers, list): return for provider in filter(valid_provider, providers): if provider.get("name") == self.stream.provider: break else: return try: stream = provider.get("streams")[self.stream.stream_index] except IndexError: self.logger.error("Stream index not in result") return filename_format = stream.get("streamName").replace("%", "%s") filename_format = urljoin(provider.get("url"), filename_format) self.filename_format = filename_format self.update_chunk_info(stream)
def _get_event_url(self, prefix, data): match = re.search(' \"(.*)\";', data) if not match: raise PluginError("Event live page URL not found") return urljoin(prefix, match.group(1))
def _parse_smil(self, url, swf_url): res = http.get(url) smil = http.xml(res, "SMIL config", schema=_smil_schema) for src, bitrate in smil["videos"]: url = urljoin(smil["http_base"], src) yield bitrate, AkamaiHDStream(self.session, url, swf=swf_url)
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
def process_module_info(self): if self.closed: return try: result = self.fetch_module_info() except PluginError as err: self.logger.error("{0}", err) return providers = result.get("stream") if not providers or providers == "offline": self.logger.debug("Stream went offline") self.close() return for provider in providers: if provider.get("name") == self.stream.provider: break else: return try: stream = provider["streams"][self.stream.stream_index] except IndexError: self.logger.error("Stream index not in result") return filename_format = stream["streamName"].replace("%", "%s") filename_format = urljoin(provider["url"], filename_format) self.filename_format = filename_format self.update_chunk_info(stream)
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
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_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 _parse_smil(self, url): res = urlget(url) smil = res_xml(res, "SMIL config") streams = {} httpbase = smil.find("{http://www.w3.org/2001/SMIL20/Language}head/" "{http://www.w3.org/2001/SMIL20/Language}meta[@name='httpBase']") if not (httpbase is not None and httpbase.attrib.get("content")): raise PluginError("Missing HTTP base in SMIL") httpbase = httpbase.attrib.get("content") videos = smil.findall("{http://www.w3.org/2001/SMIL20/Language}body/" "{http://www.w3.org/2001/SMIL20/Language}switch/" "{http://www.w3.org/2001/SMIL20/Language}video") for video in videos: url = urljoin(httpbase, video.attrib.get("src")) bitrate = int(video.attrib.get("system-bitrate")) streams[bitrate] = AkamaiHDStream(self.session, url) return streams
def process_module_info(self): try: result = self.conn.process_packets(invoked_method="moduleInfo", timeout=30) except (IOError, librtmp.RTMPError) as err: self.stream.logger.error( "Failed to get module info: {0}".format(err)) return result = validate_module_info(result) if not result: return providers = result.get("stream") if providers == "offline": self.stream.logger.debug("Stream went offline") self.stop() elif not isinstance(providers, list): return for provider in providers: if provider.get("name") == self.stream.stream.provider: break else: return try: stream = provider.get("streams")[self.stream_index] except IndexError: self.stream.logger.debug("Stream index not in result") return filename_format = stream.get("streamName").replace("%", "%s") filename_format = urljoin(provider.get("url"), filename_format) self.filename_format = filename_format self.update_chunk_info(stream)
def process_module_info(self): try: result = self.conn.process_packets(invoked_method="moduleInfo", timeout=30) except (IOError, librtmp.RTMPError) as err: self.stream.logger.error("Failed to get module info: {0}".format(err)) return result = validate_module_info(result) if not result: return providers = result.get("stream") if providers == "offline": self.stream.logger.debug("Stream went offline") self.stop() elif not isinstance(providers, list): return for provider in filter(valid_provider, providers): if provider.get("name") == self.stream.stream.provider: break else: return try: stream = provider.get("streams")[self.stream_index] except IndexError: self.stream.logger.debug("Stream index not in result") return filename_format = stream.get("streamName").replace("%", "%s") filename_format = urljoin(provider.get("url"), filename_format) self.filename_format = filename_format self.update_chunk_info(stream)
def get_vod_streams(self): match = re.search("flashvars\s+=\s+({.+?});", self.res.text) if not match: raise NoStreamsError(self.url) flashvars = parse_json(match.group(1), "flashvars JSON") match = re.search("var jsonData\s+= eval \((.+?)\);", self.res.text, re.DOTALL) if not match: raise NoStreamsError(self.url) playlists = parse_json(match.group(1), "playlist JSON") self.logger.info("Playlist items found:") for i, playlist in enumerate(playlists): for fvars in playlist: if self.url[-1] != "/": url = self.url + "/" else: url = self.url url = urljoin(url, "?set={1}&lang={0}".format(i, fvars["set"])) self.logger.info("[Set {1} ({0})] {2}", self.Lang[i], fvars["set"], url) params = parse_qsd(urlparse(self.url).query) currentset = int(params.get("set", "1")) lang = int(params.get("lang", "0")) flashvars.update(playlists[lang][currentset - 1]) flashvars["uip"] = self._get_user_ip() streams = {} for level, levelname in self.VODQualityLevels.items(): params = self._create_gox_params(flashvars, level) res = urlget(self.GOXVODURL, params=params, session=self.rsession) gox = GOXFile(res.text) entries = gox.filter_entries("vod") for entry in entries: streamurl = entry.ref[0] params = {} try: params["key"] = self._create_stream_key(streamurl) except PluginError as err: self.logger.warning("{0}", str(err)) continue streams[levelname] = HTTPStream(self.session, streamurl, params=params) if len(streams) == 0: self.logger.warning(("Unable to access any streams, " "make sure you have access to this VOD")) return streams
def url(self, path, *args, **kwargs): path = path.format(*args, **kwargs) return urljoin("http://usher." + self.host, path)