def _get_vod_streams(self): url = 'http://ida.omroep.nl/odi/?prid={}&puboptions=adaptive,h264_bb,h264_sb,h264_std&adaptive=no&part=1&token={}'\ .format(quote(self.npo_id), quote(self.get_token())) res = http.get(url, headers=HTTP_HEADERS); data = res.json() streams = {} stream = http.get(data['streams'][0].replace('jsonp', 'json'), headers=HTTP_HEADERS).json() streams['best'] = streams['high'] = HTTPStream(self.session, stream['url']) return streams
def _get_vod_streams(self): url = 'http://ida.omroep.nl/odi/?prid={0}&puboptions=adaptive,h264_bb,h264_sb,h264_std&adaptive=no&part=1&token={1}'\ .format(quote(self.npo_id), quote(self.get_token())) res = http.get(url, headers=HTTP_HEADERS) data = res.json() streams = {} stream = http.get(data['streams'][0].replace('jsonp', 'json'), headers=HTTP_HEADERS).json() streams['best'] = streams['high'] = HTTPStream(self.session, stream['url']) return streams
def get_token(self): url = 'http://ida.omroep.nl/npoplayer/i.js?s={0}'.format( quote(self.url)) token = http.get(url, headers=HTTP_HEADERS).text token = re.compile(r'token.*?"(.*?)"', re.DOTALL + re.IGNORECASE).search(token).group(1) # Great the have a ['en','ok','t'].reverse() decurity option in npoplayer.js secured = list(token) token = list(token) first = -1 second = -1 for i, c in enumerate(token): if c.isdigit() and 4 < i < len(token): if first == -1: first = i else: second = i break if first == -1: first = 12 if second == -1: second = 13 secured[first] = token[second] secured[second] = token[first] return ''.join(secured)
def get_token(self): url = 'http://ida.omroep.nl/npoplayer/i.js?s={}'.format(quote(self.url)) token = http.get(url, headers=HTTP_HEADERS).text token = re.compile('token.*?"(.*?)"', re.DOTALL + re.IGNORECASE).search(token).group(1) # Great the have a ['en','ok','t'].reverse() decurity option in npoplayer.js secured = list(token) token = list(token) first = -1 second = -1 for i, c in enumerate(token): if c.isdigit() and 4 < i < len(token): if first == -1: first = i else: second = i break if first == -1: first = 12 if second == -1: second = 13 secured[first] = token[second] secured[second] = token[first] return ''.join(secured)
def _get_streams(self): m = self._live_url_re.search(self.page.text) playlist_url = m and update_scheme(self.url, m.group(1)) player_url = self.url token = self._get_token() if playlist_url: log.debug("Found playlist URL in the page") else: live_channel = None for div in itertags(self.page.text, "div"): if div.attributes.get("id") == "botonLive": live_channel = div.attributes.get("data-canal") if live_channel: log.debug("Live channel: {0}".format(live_channel)) player_url = self._channel_urls[live_channel] + quote(token) page = self.session.http.get(player_url, raise_for_status=False) if "block access from your country." in page.text: raise PluginError("Content is geo-locked") m = self._playlist_re.search(page.text) playlist_url = m and update_scheme(self.url, m.group(1)) else: log.error("Could not find the live channel") if playlist_url: stream_url = "{0}?{1}".format(playlist_url, urlencode({"iut": token})) return HLSStream.parse_variant_playlist( self.session, stream_url, headers={"referer": player_url})
def _location(self, url): url = quote(url, safe="%/:=&?~#+!$,;'@()*[]") req = self.session.http.get(url, headers=self.HEADERS, allow_redirects=False) return dict(req.headers).get('Location')
def _get_streams(self): headers = {"User-Agent": useragents.CHROME} hls_url = http.get(self.url, headers=headers, schema=self._schema) headers["Referer"] = self.url if self.isVod: url = self._url_vod.format(quote(hls_url, safe="")) hls_url = http.get(url, headers=headers, schema=self._schema_vod) return HLSStream.parse_variant_playlist(self.session, hls_url, headers=headers)
def _get_streams(self): hls_url = self.session.http.get(self.url, schema=self._schema) if "mediathek" in self.url.lower(): url = self._url_vod.format(quote(hls_url, safe="")) hls_url = self.session.http.get(url, headers={ "Referer": self.url }).url return HLSStream.parse_variant_playlist(self.session, hls_url, headers={"Referer": self.url})
def login(self, username, password): log.debug("Logging in as {0}".format(username)) redirect_to = "https://home.bt.com/ss/Satellite/secure/loginforward?view=btsport&redirectURL={0}".format( quote(self.url)) data = { "cookieExpp": "30", "Switch": "yes", "SMPostLoginUrl": "/appsyouraccount/secure/postlogin", "loginforward": "https://home.bt.com/ss/Satellite/secure/loginforward?view=btsport", "smauthreason": "0", "TARGET": redirect_to, "USER": username, "PASSWORD": password } res = self.session.http.post(self.login_url, data=data) log.debug("Redirected to: {0}".format(res.url)) if "loginerror" not in res.text: self.logger.debug("Login successful, getting SAML token") res = self.session.http.get( "https://samlfed.bt.com/sportgetfedwebhls?bt.cid={0}".format( self.acid())) d = self.saml_re.search(res.text) if d: saml_data = d.group(1) self.logger.debug("BT Sports federated login...") res = self.session.http.post(self.api_url, params={ "action": "LoginBT", "channel": "WEBHLS", "bt.cid": self.acid }, data={"SAMLResponse": saml_data}) fed_json = self.session.http.json(res) success = fed_json['resultCode'] == "OK" if not success: self.logger.error("Failed to login: {0} - {1}".format( fed_json['errorDescription'], fed_json['message'])) return success else: return False
def _get_streams(self): headers = {'User-Agent': CHROME} self.url = self.url.replace(u'ρικ', quote(u'ρικ'.encode('utf-8'))) get_page = self.session.http.get(self.url, headers=headers) tags = list(itertags(get_page.text, 'script')) if 'live-tv' in self.url: tag = [i for i in tags if 'm3u8' in i.text][0].text try: stream = re.search(r'''["'](http.+?\.m3u8)['"]''', tag).group(1) except IndexError: raise NoStreamsError('RIK Broadcast is currently disabled') else: tag = [i for i in tags if '.mp4' in i.text and 'sources' in i.text][0].text stream = re.search(r'''file: ['"](.+?\.mp4)['"]''', tag).group(1) headers.update({"Referer": self.url}) try: parse_hls = bool(strtobool(self.get_option('parse_hls'))) except AttributeError: parse_hls = True if parse_hls and 'live-tv' in self.url: return HLSStream.parse_variant_playlist(self.session, stream, headers=headers) else: return dict(stream=HTTPStream(self.session, stream, headers=headers))
def _get_streams(self): m = self._live_url_re.search(self.page.text) playlist_url = m and update_scheme(self.url, m.group(1)) player_url = self.url live_channel = None p = urlparse(player_url) channelnumber = 0 if p.netloc.endswith("tvc.com.ec"): live_channel = "Canal5" elif p.netloc.endswith("rts.com.ec"): live_channel = "Guayaquil" elif p.netloc.endswith("atv.pe"): if p.path.endswith(("ATVMas", "ATVMas/")): live_channel = "ATVMas" channelnumber = 1 else: live_channel = "ATV" token = self._get_token(channelnumber) log.debug("token {0}".format(token)) if playlist_url: log.debug("Found playlist URL in the page") else: if live_channel: log.debug("Live channel: {0}".format(live_channel)) player_url = self._channel_urls[live_channel] + quote(token) page = self.session.http.get(player_url, raise_for_status=False) if "block access from your country." in page.text: raise PluginError("Content is geo-locked") m = self._playlist_re.search(page.text) playlist_url = m and update_scheme(self.url, m.group(1)) else: log.error("Could not find the live channel") if playlist_url: stream_url = "{0}?{1}".format(playlist_url, urlencode({"iut": token})) return HLSStream.parse_variant_playlist(self.session, stream_url, headers={"referer": player_url})
def _get_streams(self): match = _url_re.match(self.url) channel = match.group("channel") res = http.get(self.url) try: channel = int(channel) except ValueError: channel = _room_id_re.search(res.text).group(1) ts = int(time.time()) url = ROOM_API_V2.format(channel, ts) res = http.get(url) try: status = _status_re.search(res.text).group(1) room_key = _room_key_re.search(res.text).group(1) hostid = _hostid_re.search(res.text).group(1) param = _param_re.search(res.text).group(1) tt = _time_re.search(res.text).group(1) sign = _sign_re.search(res.text).group(1) sd = _sd_re.search(res.text).group(1) hd = _hd_re.search(res.text).group(1) od = _od_re.search(res.text).group(1) except AttributeError: self.logger.info("Not a valid room url.") return if status != '2': self.logger.info("Stream currently unavailable.") return ts = int(time.time()) param = param.replace("\\", "") param = quote(param) url = ROOM_API.format(hostid, channel, room_key, ts, param, tt, sign) room = http.get(url) data = http.json(room, schema=_room_schema) if not isinstance(data, dict): self.logger.info("Please Check PandaTV Room API") return videoinfo = data.get('videoinfo') plflag_list = videoinfo.get('plflag_list') if not videoinfo or not plflag_list: self.logger.info("Please Check PandaTV Room API") return streams = {} plflag = videoinfo.get('plflag') if not plflag or '_' not in plflag: self.logger.info("Please Check PandaTV Room API") return plflag_list = json.loads(plflag_list) backup = plflag_list["backup"] rid = plflag_list["auth"]["rid"] sign = plflag_list["auth"]["sign"] ts = plflag_list["auth"]["time"] backup.append(plflag) plflag0 = backup plflag0 = [i.split('_')[1] for i in plflag0] # let wangsu cdn priority, flag can see here in "H5PLAYER_CDN_LINES": # https://www.panda.tv/cmstatic/global-config.js lines = ["3", "4"] try: plflag1 = [i for i in plflag0 if i in lines][0] except IndexError: plflag1 = plflag0[0] if sd == '1': streams['ehq'] = HTTPStream(self.session, SD_URL_PATTERN.format(plflag1, room_key, sign, ts, rid)) if hd == '1': streams['hq'] = HTTPStream(self.session, HD_URL_PATTERN.format(plflag1, room_key, sign, ts, rid)) if od == '1': streams['sq'] = HTTPStream(self.session, OD_URL_PATTERN.format(plflag1, room_key, sign, ts, rid)) return streams
def login(self, username, password): log.debug("Logging in as {0}".format(username)) redirect_to = "https://home.bt.com/ss/Satellite/secure/loginforward?view=btsport&redirectURL={0}".format(quote(self.url)) data = { "cookieExpp": "30", "Switch": "yes", "SMPostLoginUrl": "/appsyouraccount/secure/postlogin", "loginforward": "https://home.bt.com/ss/Satellite/secure/loginforward?view=btsport", "smauthreason": "0", "TARGET": redirect_to, "USER": username, "PASSWORD": password} res = self.session.http.post(self.login_url, data=data) log.debug("Redirected to: {0}".format(res.url)) if "loginerror" not in res.text: self.logger.debug("Login successful, getting SAML token") res = self.session.http.get("https://samlfed.bt.com/sportgetfedwebhls?bt.cid={0}".format(self.acid())) d = self.saml_re.search(res.text) if d: saml_data = d.group(1) self.logger.debug("BT Sports federated login...") res = self.session.http.post(self.api_url, params={"action": "LoginBT", "channel": "WEBHLS", "bt.cid": self.acid}, data={"SAMLResponse": saml_data}) fed_json = self.session.http.json(res) success = fed_json['resultCode'] == "OK" if not success: self.logger.error("Failed to login: {0} - {1}".format(fed_json['errorDescription'], fed_json['message'])) return success else: return False
def _get_streams(self): if self.response is None: infos = self.session.http.get(self.url, schema=self._ctcomp_schema) else: infos = self.session.http.json(self.response, schema=self._ctcomp_schema) if not infos: # playlist infos not found raise PluginError('Cannot find playlist infos!') vod_prio = len(infos) == 2 for info in infos: try: pl = info['ctcomp-data']['source']['playlist'][0] except KeyError: raise PluginError('Cannot find playlist info!') pl = self._playlist_info_schema.validate(pl) if vod_prio and pl['type'] != 'VOD': continue log.trace('{0!r}'.format(info)) if pl['type'] == 'LIVE': data = { "contentType": "live", "items": [{ "id": pl["id"], "assetId": pl["assetId"], "key": pl["key"], "playerType": "dash", "date": pl["date"], "requestSource": pl["requestSource"], "drm": pl["drm"], "quality": pl["quality"], }] } elif pl['type'] == 'VOD': data = { "contentType": "vod", "items": [{ "id": pl["id"], "key": pl["key"], "playerType": "dash", "date": pl["date"], "requestSource": pl["requestSource"], "drm": pl["drm"], "canBePlay": pl["canBePlay"], "quality": pl["quality"], "region": pl["region"] }] } headers = { "Content-Type": "application/x-www-form-urlencoded; charset=UTF-8", } data = json.dumps(data) response = self.session.http.post(self._player_api, data="data={}".format(quote(data)), headers=headers) json_data = self.session.http.json(response, schema=self._playlist_schema) log.trace('{0!r}'.format(json_data)) playlist = json_data['RESULT']['playlist'][0]['streamUrls']['main'] for s in DASHStream.parse_manifest(self.session, playlist).items(): yield s
def _get_streams(self): # Get domain name self.domain = _url_re.match(self.url).group('domain') # Set header data for user-agent hdr = {'User-Agent': USER_AGENT.format('sv_SE')} # Parse video ID from data received from supplied URL res = http.get(self.url, headers=hdr).text match = _videoid_re.search(res) if not match: # Video ID not found self.logger.error('Failed to parse video ID') return {} videoId = match.group('id') # Get data from general API to validate that stream is playable res = http.get(GENERAL_API_URL.format(self.domain, videoId), headers=hdr) data = http.json(res, schema=_api_schema) if not data['data']: # No data item found self.logger.error('Unable to find "data" item in general API response') return {} if not self._is_playable(data): # Stream not playable self.logger.error('Stream is not playable (Premium or DRM-protected content)') return {} # Get geo data, validate and form cookie consisting of # geo data + expiry timestamp (current time + 1 hour) res = http.get(GEO_DATA_URL.format(self.domain), headers=hdr) geo = http.json(res, schema=_geo_schema) timestamp = (int(time.time()) + 3600) * 1000 cookie = 'dsc-geo=%s' % quote('{"countryCode":"%s","expiry":%s}' % (geo, timestamp)) # Append cookie to headers hdr['Cookie'] = cookie # Get available streams using stream API try: res = http.get(STREAM_API_URL.format(self.domain, videoId, 'hls'), headers=hdr, verify=False) data = http.json(res, schema=_media_schema) media = data.copy() res = http.get(STREAM_API_URL.format(self.domain, videoId, 'hds'), headers=hdr, verify=False) data = http.json(res, schema=_media_schema) media.update(data) except PluginError as err: # Likely geo-restricted if any(e in str(err) for e in ('401 Client Error', '403 Client Error')): self.logger.error('Failed to access stream API, ' 'may be due to geo-restriction') raise NoStreamsError(self.url) else: raise # Reformat data into list with stream format and url streams = [{'format': k, 'url': media[k]} for k in media] # Create mapper for supported stream types (HLS/HDS) mapper = StreamMapper(cmp=lambda type, video: video['format'] == type) mapper.map('hls', self._create_streams, HLSStream.parse_variant_playlist) mapper.map('hds', self._create_streams, HDSStream.parse_manifest) # Feed stream data to mapper and return all streams found return mapper(streams)
def _get_streams(self): # Get domain name self.domain = _url_re.match(self.url).group('domain') # Set header data for user-agent hdr = {'User-Agent': USER_AGENT.format('sv_SE')} # Parse video ID from data received from supplied URL res = http.get(self.url, headers=hdr).text match = _videoid_re.search(res) if not match: # Video ID not found self.logger.error('Failed to parse video ID') return {} videoId = match.group('id') # Get data from general API to validate that stream is playable res = http.get(GENERAL_API_URL.format(self.domain, videoId), headers=hdr) data = http.json(res, schema=_api_schema) if not data['data']: # No data item found self.logger.error( 'Unable to find "data" item in general API response') return {} if not self._is_playable(data): # Stream not playable self.logger.error( 'Stream is not playable (Premium or DRM-protected content)') return {} # Get geo data, validate and form cookie consisting of # geo data + expiry timestamp (current time + 1 hour) res = http.get(GEO_DATA_URL.format(self.domain), headers=hdr) geo = http.json(res, schema=_geo_schema) timestamp = (int(time.time()) + 3600) * 1000 cookie = 'dsc-geo=%s' % quote('{"countryCode":"%s","expiry":%s}' % (geo, timestamp)) # Append cookie to headers hdr['Cookie'] = cookie # Get available streams using stream API try: res = http.get(STREAM_API_URL.format(self.domain, videoId, 'hls'), headers=hdr, verify=False) data = http.json(res, schema=_media_schema) media = data.copy() res = http.get(STREAM_API_URL.format(self.domain, videoId, 'hds'), headers=hdr, verify=False) data = http.json(res, schema=_media_schema) media.update(data) except PluginError as err: # Likely geo-restricted if any(e in str(err) for e in ('401 Client Error', '403 Client Error')): self.logger.error('Failed to access stream API, ' 'may be due to geo-restriction') raise NoStreamsError(self.url) else: raise # Reformat data into list with stream format and url streams = [{'format': k, 'url': media[k]} for k in media] # Create mapper for supported stream types (HLS/HDS) mapper = StreamMapper(cmp=lambda type, video: video['format'] == type) mapper.map('hls', self._create_streams, HLSStream.parse_variant_playlist) mapper.map('hds', self._create_streams, HDSStream.parse_manifest) # Feed stream data to mapper and return all streams found return mapper(streams)
def _get_streams(self): match = _url_re.match(self.url) prefix = match.group("prefix") channel = match.group("channel") res = http.get(self.url) if prefix == 'xingyan.': roominfo = _roominfo_re.search(res.text).group(1) roominfo = json.loads(roominfo) videoinfo = roominfo['videoinfo'] if videoinfo['hlsurl']: yield 'source', HLSStream(self.session, videoinfo['hlsurl']) #wangsu cdn prior to others, wangsu = 0, alicloud = 1, qcloud = videoinfo['streamurl'] _cdn = 0 if videoinfo['zl'][_cdn]['streamurl']: yield 'source', HTTPStream(self.session, videoinfo['zl'][_cdn]['streamurl']) if videoinfo['zl'][_cdn]['streamtrans']['mid']: yield 'medium', HTTPStream(self.session, videoinfo['zl'][_cdn]['streamtrans']['mid']) if videoinfo['zl'][_cdn]['streamtrans']['small']: yield 'low', HTTPStream(self.session, videoinfo['zl'][_cdn]['streamtrans']['small']) return try: channel = int(channel) except ValueError: channel = _room_id_re.search(res.text).group(1) ts = int(time.time()) url = ROOM_API_V2.format(channel, ts) res = http.get(url) try: status = _status_re.search(res.text).group(1) room_key = _room_key_re.search(res.text).group(1) hostid = _hostid_re.search(res.text).group(1) param = _param_re.search(res.text).group(1) tt = _time_re.search(res.text).group(1) sign = _sign_re.search(res.text).group(1) sd = _sd_re.search(res.text).group(1) hd = _hd_re.search(res.text).group(1) od = _od_re.search(res.text).group(1) except AttributeError: self.logger.info("Not a valid room url.") return if status != '2': self.logger.info("Stream currently unavailable.") return ts = int(time.time()) param = param.replace("\\", "") param = quote(param) url = ROOM_API.format(hostid, channel, room_key, ts, param, tt, sign) room = http.get(url) data = http.json(room, schema=_room_schema) if not isinstance(data, dict): self.logger.info("Please Check PandaTV Room API") return videoinfo = data.get('videoinfo') plflag_list = videoinfo.get('plflag_list') if not videoinfo or not plflag_list: self.logger.info("Please Check PandaTV Room API") return plflag = videoinfo.get('plflag') if not plflag or '_' not in plflag: self.logger.info("Please Check PandaTV Room API") return plflag_list = json.loads(plflag_list) backup = plflag_list["backup"] rid = plflag_list["auth"]["rid"] sign = plflag_list["auth"]["sign"] ts = plflag_list["auth"]["time"] backup.append(plflag) plflag0 = backup plflag0 = [i.split('_')[1] for i in plflag0] # let wangsu cdn priority, flag can see here in "H5PLAYER_CDN_LINES": # https://www.panda.tv/cmstatic/global-config.js lines = ["3", "4"] try: plflag1 = [i for i in plflag0 if i in lines][0] except IndexError: plflag1 = plflag0[0] if sd == '1': yield 'source', HTTPStream(self.session, SD_URL_PATTERN.format(plflag1, room_key, sign, ts, rid)) if hd == '1': yield 'medium', HTTPStream(self.session, HD_URL_PATTERN.format(plflag1, room_key, sign, ts, rid)) if od == '1': yield 'low', HTTPStream(self.session, OD_URL_PATTERN.format(plflag1, room_key, sign, ts, rid)) return