def _get_broadcast(self, username): data = { "szBjId": username } res = http.post(BROAD_INFO_URL, headers=HEADERS, data=data) return http.json(res, schema=_broadcast_schema)
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 })
def _authenticate(self, email, password): csrf_token = http.get(LOGIN_PAGE_URL, schema=_csrf_token_schema) if not csrf_token: raise PluginError("Unable to find CSRF token") data = { "authenticity_token": csrf_token, "channel_id": "", "commit": "Login", "plan_id": "", "session[email]": email, "session[password]": password, "utf8": "\xE2\x9C\x93", # Check Mark Character } res = http.post(LOGIN_POST_URL, data=data, acceptable_status=(200, 422)) result = http.json(res, schema=_login_schema) errors = result.get("errors") if errors: errors = ", ".join(errors) raise PluginError("Unable to authenticate: {0}".format(errors)) self.logger.info("Successfully logged in as {0}", result["email"])
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 })
def _get_channel_info(self, username): data = { "bid": username } res = http.post(CHANNEL_INFO_URL, data=data) return http.json(res, schema=_channel_schema)
def _get_streams(self): match = _url_re.match(self.url) channel = match.group("channel") http.headers.update({"User-Agent": USER_AGENT}) room_id = http.get(self.url, schema=_room_id_schema) channel = room_id["room_id"] res = http.get(MAPI_URL.format(channel)) room = http.json(res, schema=_room_schema) if not room: return if room["show_status"] != SHOW_STATUS_ONLINE: return ts = int(time.time() / 60) did = uuid.uuid4().hex.upper() sign = hashlib.md5( ("{0}{1}{2}{3}".format(channel, did, LAPI_SECRET, ts)).encode("utf-8")).hexdigest() data = {"cdn": "ws", "rate": "0", "tt": ts, "did": did, "sign": sign} res = http.post(LAPI_URL.format(channel), data=data) room = http.json(res, schema=_lapi_schema) url = "{room[rtmp_url]}/{room[rtmp_live]}".format(room=room) stream = HTTPStream(self.session, url) yield "source", stream data = {"cdn": "ws", "rate": "2", "tt": ts, "did": did, "sign": sign} res = http.post(LAPI_URL.format(channel), data=data) room = http.json(res, schema=_lapi_schema) url = "{room[rtmp_url]}/{room[rtmp_live]}".format(room=room) stream = HTTPStream(self.session, url) yield "middle", stream data = {"cdn": "ws", "rate": "1", "tt": ts, "did": did, "sign": sign} res = http.post(LAPI_URL.format(channel), data=data) room = http.json(res, schema=_lapi_schema) url = "{room[rtmp_url]}/{room[rtmp_live]}".format(room=room) stream = HTTPStream(self.session, url) yield "low", stream
def _send_amf_request(self, req, key): headers = { "content-type": "application/x-amf" } res = http.post(AMF_GATEWAY, data=bytes(req.serialize()), headers=headers, params=dict(playerKey=key)) return AMFPacket.deserialize(BytesIO(res.content))
def _send_amf_request(self, req, key): headers = {"content-type": "application/x-amf"} res = http.post(AMF_GATEWAY, data=bytes(req.serialize()), headers=headers, params=dict(playerKey=key)) return AMFPacket.deserialize(BytesIO(res.content))
def _get_channel_info(self, bid): headers = { "Referer": "http://play.afreecatv.com", "Content-Type": "application/x-www-form-urlencoded; charset=UTF-8", } params = {"bid": bid} res = http.post(CHANNEL_INFO_URL, data=params, headers=headers) #print res.text return http.json(res, schema=_channel_schema)
def _get_channel_info(self, username): headers = { "Referer": self.url } data = { "uid": username } res = http.post(CHANNEL_INFO_URL, data=data, headers=headers) return http.json(res, schema=_channel_schema)
def _get_streams(self): """ Find all the streams for the ITV url :return: Mapping of quality to stream """ soap_message = self._soap_request() headers = { 'Content-Length': '{0:d}'.format(len(soap_message)), 'Content-Type': 'text/xml; charset=utf-8', 'Host': 'mercury.itv.com', 'Origin': 'http://www.itv.com', 'Referer': 'http://www.itv.com/Mercury/Mercury_VideoPlayer.swf?v=null', 'SOAPAction': "http://tempuri.org/PlaylistService/GetPlaylist", 'User-Agent': ITV_PLAYER_USER_AGENT, "X-Requested-With": "ShockwaveFlash/16.0.0.305" } res = http.post("http://mercury.itv.com/PlaylistService.svc?wsdl", headers=headers, data=soap_message) # looking for the <MediaFiles> tag xmldoc = http.xml(res) mediafiles = xmldoc.find(".//VideoEntries//MediaFiles") # No mediafiles, no streams if not mediafiles: return None rtmp = mediafiles.attrib['base'] streams = {} for mediafile in mediafiles.findall("MediaFile"): playpath = mediafile.find("URL").text rtmp_url = urlparse(rtmp) app = (rtmp_url.path[1:] + '?' + rtmp_url.query).rstrip('?') live = app == "live" params = dict( rtmp="{u.scheme}://{u.netloc}{u.path}".format(u=rtmp_url), app=app.rstrip('?'), playpath=playpath, swfVfy=LIVE_SWF_URL if live else ONDEMAND_SWF_URL, timeout=10) if live: params['live'] = True bitrate = int(mediafile.attrib['bitrate']) / 1000 quality = "{0}k".format(bitrate) streams[quality] = RTMPStream(self.session, params) 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
def _get_streams(self): """ Find all the streams for the ITV url :return: Mapping of quality to stream """ soap_message = self._soap_request() headers = { "Content-Length": "{0:d}".format(len(soap_message)), "Content-Type": "text/xml; charset=utf-8", "Host": "mercury.itv.com", "Origin": "http://www.itv.com", "Referer": "http://www.itv.com/Mercury/Mercury_VideoPlayer.swf?v=null", "SOAPAction": "http://tempuri.org/PlaylistService/GetPlaylist", "User-Agent": ITV_PLAYER_USER_AGENT, "X-Requested-With": "ShockwaveFlash/16.0.0.305", } res = http.post("http://mercury.itv.com/PlaylistService.svc?wsdl", headers=headers, data=soap_message) # looking for the <MediaFiles> tag xmldoc = http.xml(res) mediafiles = xmldoc.find(".//VideoEntries//MediaFiles") # No mediafiles, no streams if not mediafiles: return None rtmp = mediafiles.attrib["base"] streams = {} for mediafile in mediafiles.findall("MediaFile"): playpath = mediafile.find("URL").text rtmp_url = urlparse(rtmp) app = (rtmp_url.path[1:] + "?" + rtmp_url.query).rstrip("?") live = app == "live" params = dict( rtmp="{u.scheme}://{u.netloc}{u.path}".format(u=rtmp_url), app=app.rstrip("?"), playpath=playpath, swfVfy=LIVE_SWF_URL if live else ONDEMAND_SWF_URL, timeout=10, ) if live: params["live"] = True bitrate = int(mediafile.attrib["bitrate"]) / 1000 quality = "{0}k".format(bitrate) streams[quality] = RTMPStream(self.session, params) return streams
def _get_streams(self): match = _url_re.match(self.url) channel_name = match.group("channel") form = { "cid": channel_name, "watchTime": 0, "firstConnect": 1, "ip": "NaN" } res = http.post(API_URL, data=form, headers=HEADERS) params = parse_query(res.text, schema=_schema) if params["status"] <= 0: return if params["block_type"] != 0: if params["block_type"] == BLOCK_TYPE_VIEWING_LIMIT: msg = BLOCKED_MSG_FORMAT.format( params.get("block_time", "UNKNOWN"), params.get("reconnect_time", "UNKNOWN")) raise PluginError(msg) elif params["block_type"] == BLOCK_TYPE_NO_SLOTS: raise PluginError("No free slots available") else: raise PluginError("Blocked for unknown reasons") if "token" not in params: raise PluginError("Server seems busy, retry again later") streams = {} stream_names = ["sd"] if params["multibitrate"]: stream_names += ["hd"] for stream_name in stream_names: playpath = params["playpath"] if stream_name == "hd": playpath += "HI" stream = RTMPStream( self.session, { "rtmp": "{0}/{1}".format(params["rtmp"], playpath), "pageUrl": self.url, "swfVfy": SWF_URL, "weeb": params["token"], "live": True }) streams[stream_name] = stream return streams
def _get_streams(self): match = _url_re.match(self.url) channel_name = match.group("channel") form = { "cid": channel_name, "watchTime": 0, "firstConnect": 1, "ip": "NaN" } res = http.post(API_URL, data=form, headers=HEADERS) params = parse_query(res.text, schema=_schema) if params["status"] <= 0: return if params["block_type"] != 0: if params["block_type"] == BLOCK_TYPE_VIEWING_LIMIT: msg = BLOCKED_MSG_FORMAT.format( params.get("block_time", "UNKNOWN"), params.get("reconnect_time", "UNKNOWN") ) raise PluginError(msg) elif params["block_type"] == BLOCK_TYPE_NO_SLOTS: raise PluginError("No free slots available") else: raise PluginError("Blocked for unknown reasons") if "token" not in params: raise PluginError("Server seems busy, retry again later") streams = {} stream_names = ["sd"] if params["multibitrate"]: stream_names += ["hd"] for stream_name in stream_names: playpath = params["playpath"] if stream_name == "hd": playpath += "HI" stream = RTMPStream(self.session, { "rtmp": "{0}/{1}".format(params["rtmp"], playpath), "pageUrl": self.url, "swfVfy": SWF_URL, "weeb": params["token"], "live": True }) 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
def _get_hls_key(self, broad_key, bid): headers = { "Referer": self.url, "Content-Type": "application/x-www-form-urlencoded; charset=UTF-8", } data = { "bid": bid, "bno": broad_key, "type": "pwd", "player_type": "html5", "quality": quality, } res = http.post(CHANNEL_INFO_URL, data=data, headers=headers) return http.json(res, schema=_channel_aid_schema)
def _get_live_streams(self, channel_id): params = dict(channel_id=channel_id) res = http.post(CHINFO_URL, data=params, headers=AJAX_HEADERS) channel = http.json(res, schema=_channel_schema) streams = {} for stream in channel["streams"]: name = stream["quality"] rtmp = stream["url"] playpath = stream["name"] app = self._get_rtmp_app(rtmp) stream = RTMPStream(self.session, { "rtmp": rtmp, "pageUrl": self.url, "swfUrl": SWF_URL, "playpath": playpath, "app": app, "live": True }) streams[name] = stream return streams
def _authenticate(self, email, password): csrf_token = http.get(LOGIN_PAGE_URL, schema=_csrf_token_schema) if not csrf_token: raise PluginError("Unable to find CSRF token") data = { "authenticity_token": csrf_token, "channel_id": "", "commit": "Login", "plan_id": "", "session[email]": email, "session[password]": password, "utf8": "\xE2\x9C\x93", # Check Mark Character } res = http.post(LOGIN_POST_URL, data=data, acceptable_status=(200, 422)) result = http.json(res, schema=_login_schema) errors = result.get("errors") if errors: errors = ", ".join(errors) raise PluginError("Unable to authenticate: {0}".format(errors)) self.logger.info("Successfully logged in as {0}", result["email"])
def _resolve_stream(self): res = http.get(self.url) match = _data_stream_re.search(res.text) if not match: return data_stream = match.group(1) resolve_data = { 'stream': data_stream } res = http.post( 'http://www-ipv4.nos.nl/livestream/resolve/', data=json.dumps(resolve_data) ) data = http.json(res) res = http.get(data['url']) match = _js_re.search(res.text) if not match: return stream_url = parse_json(match.group(1)) return HLSStream.parse_variant_playlist(self.session, stream_url)
def _get_live_streams(self, channel_id): params = dict(channel_id=channel_id) res = http.post(CHINFO_URL, data=params, headers=AJAX_HEADERS) channel = http.json(res, schema=_channel_schema) streams = {} for stream in channel["streams"]: name = stream["quality"] rtmp = stream["url"] playpath = stream["name"] app = self._get_rtmp_app(rtmp) stream = RTMPStream( self.session, { "rtmp": rtmp, "pageUrl": self.url, "swfUrl": SWF_URL, "playpath": playpath, "app": app, "live": True }) streams[name] = stream return streams
def ajax(*args, **kwargs): kwargs["headers"] = AJAX_HEADERS return http.post(*args, **kwargs)
def _get_channel_info(self, username): data = {"bid": username} res = http.post(CHANNEL_INFO_URL, data=data) return http.json(res, schema=_channel_schema)
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 = http.post(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
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 = http.post(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
def _get_broadcast(self, username): data = {"szBjId": username} res = http.post(BROAD_INFO_URL, headers=HEADERS, data=data) return http.json(res, schema=_broadcast_schema)