def from_player_key(cls, session, player_id, player_key, video_id, url=None): amf_message = AMFMessage("com.brightcove.experience.ExperienceRuntimeFacade.getDataForExperience", "/1", [ ''.join(["{0:02x}".format(random.randint(0, 255)) for _ in range(20)]), # random id ViewerExperienceRequest(experienceId=int(player_id), URL=url or "", playerKey=player_key, deliveryType=float('nan'), TTLToken="", contentOverrides=[ContentOverride( featuredRefId=None, contentRefIds=None, contentId=int(video_id) )]) ]) amf_packet = AMFPacket(version=3) amf_packet.messages.append(amf_message) res = session.http.post( cls.amf_broker, headers={"Content-Type": "application/x-amf"}, data=amf_packet.serialize(), params=dict(playerKey=player_key), raise_for_status=False ) data = AMFPacket.deserialize(BytesIO(res.content)) result = data.messages[0].value bp = cls(session=session, account_id=int(result.publisherId)) return bp.get_streams(video_id)
def from_player_key(cls, session, player_id, player_key, video_id, url=None): amf_message = AMFMessage("com.brightcove.experience.ExperienceRuntimeFacade.getDataForExperience", "/1", [ ''.join(["{0:02x}".format(random.randint(0, 255)) for _ in range(20)]), # random id ViewerExperienceRequest(experienceId=int(player_id), URL=url or "", playerKey=player_key, deliveryType=float('nan'), TTLToken="", contentOverrides=[ContentOverride( featuredRefId=None, contentRefIds=None, contentId=int(video_id) )]) ]) amf_packet = AMFPacket(version=3) amf_packet.messages.append(amf_message) res = http.post(cls.amf_broker, headers={"Content-Type": "application/x-amf"}, data=amf_packet.serialize(), params=dict(playerKey=player_key), raise_for_status=False) data = AMFPacket.deserialize(BytesIO(res.content)) result = data.messages[0].value bp = cls(session=session, account_id=int(result.publisherId)) return bp.get_streams(video_id)
def _get_streams(self): log.debug('Version 2018-07-01') log.info('This is a custom plugin. ' 'For support visit https://github.com/back-to/plugins') log.info('only FREE content is available.') http.headers.update({'User-Agent': useragents.FIREFOX}) channel = self._url_re.match(self.url).group('channel') log.info('Channel: {0}'.format(channel)) res = http.get(self.url_id.format(channel)) m = self._channel_id_re.search(res.text) if not m: raise PluginError('Invalid channel name, can\'t find channel id.') channel_id = m.group('id') data = (b'\x00\x00\x00\x00\x00\x01\x00\x10remoting.doEvent\x00\x02/1' + b'\x00\x00\x00;\n\x00\x00\x00\x02\x02\x00\n' + b'getChannel\x03\x00\x0bperformerID\x02\x00\x08' + channel_id.encode('ascii') + b'\x00\x04type\x02\x00\x04free\x00\x00\x09') res = http.post( self.url_gateway, headers={ 'Content-Type': 'application/x-amf', 'Referer': self.url_swf, }, data=data, ) data = AMFPacket.deserialize(BytesIO(res.content)) result = data.messages[0].value log.debug('--- DEBUG DATA ---'.format()) for _r in result: log.debug('{0}: {1}'.format(_r, result[_r])) log.debug('--- DEBUG DATA ---'.format()) if result['result'] != 'true': _err = self.error_code.get(str(int(result['errorCode']))) if _err: raise PluginError(_err) else: raise PluginError('Unknown error_code') channel_seq = result['channelSeq'] host = random.choice(result['freeServerIP'].split(',')) app = 'video_chat3_free_dx/{0}'.format(channel_seq) conn = [ 'O:1', 'NS:channel:{0}'.format(channel_id, result['channelID']), 'NS:pServer:{0}'.format(result['serverIP']), 'NS:langID:en', 'NS:channelSeq:{0}'.format(result['channelSeq']), 'O:O', ] params = { 'app': app, 'flashVer': 'WIN 29,0,0,171', 'swfVfy': self.url_swf, 'rtmp': 'rtmp://{0}/{1}'.format(host, app), 'live': True, 'pageUrl': self.url, 'playpath': 'free_performer', 'conn': conn } yield 'live', RTMPStream(self.session, params)
def _get_streams(self): match = url_re.match(self.url) stream_page_scheme = 'https' stream_page_domain = match.group(4) stream_page_path = match.group(5) country_code = CONST_DEFAULT_COUNTRY_CODE is_paid_show = False # create http session and set headers http_session = http http_session.headers.update(CONST_HEADERS) # get swf url and cookies r = http_session.get( urlunparse((stream_page_scheme, stream_page_domain, stream_page_path, '', '', ''))) # redirect to profile page means stream is offline if '/profile/' in r.url: raise NoStreamsError(self.url) if not r.ok: self.logger.debug("Status code for {}: {}", r.url, r.status_code) raise NoStreamsError(self.url) if len(http_session.cookies) == 0: raise PluginError("Can't get a cookies") if urlparse(r.url).netloc != stream_page_domain: # then redirected to regional subdomain country_code = urlparse(r.url).netloc.split('.')[0].lower() # time to set variables baseurl = urlunparse( (stream_page_scheme, urlparse(r.url).netloc, '', '', '', '')) amf_gateway_url = urljoin(baseurl, CONST_AMF_GATEWAY_LOCATION) stream_page_url = urljoin(baseurl, stream_page_path) match = swf_re.search(r.text) if match: swf_url = urljoin(baseurl, match.group()) self.logger.debug("swf url found: {}", swf_url) else: # most likely it means that country/region banned # can try use default swf-url swf_url = urljoin(baseurl, CONST_DEFAULT_SWF_LOCATION) self.logger.debug("swf url not found. Will try {}", swf_url) # create amf query amf_message = AMFMessage("svDirectAmf.getRoomData", "/1", [stream_page_path, is_paid_show]) amf_packet = AMFPacket(version=0) amf_packet.messages.append(amf_message) # send request and close http-session r = http_session.post(url=amf_gateway_url, params={CONST_AMF_GATEWAY_PARAM: country_code}, data=bytes(amf_packet.serialize())) http_session.close() if r.status_code != 200: raise PluginError("unexpected status code for {}: {}", r.url, r.status_code) amf_response = AMFPacket.deserialize(BytesIO(r.content)) if len(amf_response.messages ) != 1 or amf_response.messages[0].target_uri != "/1/onResult": raise PluginError("unexpected response from amf gate") stream_source_info = amf_msg_schema.validate( amf_response.messages[0].value) self.logger.debug("source stream info:\n{}", stream_source_info) stream_params = { "live": True, "realtime": True, "flashVer": CONST_FLASH_VER, "swfUrl": swf_url, "tcUrl": stream_source_info['localData']['NC_ConnUrl'], "rtmp": stream_source_info['localData']['NC_ConnUrl'], "pageUrl": stream_page_url, "playpath": "%s?uid=%s" % (''.join(('stream_', stream_page_path)), self._get_stream_uid(stream_source_info['userData']['username'])), "conn": [ "S:{0}".format(stream_source_info['userData']['username']), "S:{0}".format( stream_source_info['localData']['NC_AccessKey']), "B:0", "S:{0}".format(stream_source_info['localData']['dataKey']) ] } self.logger.debug("Stream params:\n{}", stream_params) stream = RTMPStream(self.session, stream_params) return {'live': stream}