def new_session(self, force=False, channels=False): cookies = settings.get(key='_cookies') if len(cookies) > 0 and force == False: self._session = Session(cookies_key='_cookies') self.logged_in = True return self.logged_in = False creds = get_credentials() username = creds['username'] password = creds['password'] if not len(username) > 0: return if not len(password) > 0: password = gui.numeric(message=_.ASK_PASSWORD).strip() if not len(password) > 0: gui.ok(message=_.EMPTY_PASS, heading=_.LOGIN_ERROR_TITLE) return self.login(username=username, password=password, channels=channels)
def login(**kwargs): if len(settings.get(key='_devicekey')) == 0: settings.set(key='_devicekey', value=''.join( random.choice(string.ascii_uppercase + string.ascii_lowercase + string.digits) for _ in range(64))) creds = get_credentials() username = gui.numeric(message=_.ASK_USERNAME, default=creds['username']).strip() if not len(username) > 0: gui.ok(message=_.EMPTY_USER, heading=_.LOGIN_ERROR_TITLE) return password = gui.numeric(message=_.ASK_PASSWORD).strip() if not len(password) > 0: gui.ok(message=_.EMPTY_PASS, heading=_.LOGIN_ERROR_TITLE) return api.login(username=username, password=password, channels=True) plugin.logged_in = api.logged_in gui.refresh()
def new_session(self, force=False, channels=False): access_token = settings.get(key='_access_token') creds = get_credentials() username = creds['username'] password = creds['password'] if len(access_token) > 0 and len(username) > 0 and force == False: user_agent = settings.get(key='_user_agent') HEADERS = { 'User-Agent': user_agent, 'X-Client-Id': settings.get(key='_client_id') + "||" + user_agent, 'X-OESP-Token': access_token, 'X-OESP-Username': username, } self._session = Session(headers=HEADERS) self.logged_in = True return self.logged_in = False if not len(username) > 0: return if not len(password) > 0: password = gui.numeric(message=_.ASK_PASSWORD).strip() if not len(password) > 0: gui.ok(message=_.EMPTY_PASS, heading=_.LOGIN_ERROR_TITLE) return self.login(username=username, password=password, channels=channels)
def replaytv_list(character, label='', start=0, **kwargs): start = int(start) folder = plugin.Folder(title=label) data = load_file(file='list_replay.json', isJSON=True) if not data: gui.ok(message=_.NO_REPLAY_TV_INFO, heading=_.NO_REPLAY_TV_INFO) return folder if not check_key(data, character): return folder processed = process_replaytv_list(data=data[character], start=start) if check_key(processed, 'items'): folder.add_items(processed['items']) if check_key(processed, 'count') and len(data[character]) > processed['count']: folder.add_item( label=_(_.NEXT_PAGE, _bold=True), path=plugin.url_for(func_or_url=replaytv_list, character=character, label=label, start=processed['count']), ) return folder
def replaytv_content(label, day, station='', start=0, **kwargs): day = int(day) start = int(start) folder = plugin.Folder(title=label) data = load_file(file=station + "_replay.json", isJSON=True) if not data: gui.ok(_.DISABLE_ONLY_STANDARD, _.NO_REPLAY_TV_INFO) return folder totalrows = len(data) processed = process_replaytv_content(data=data, day=day, start=start) if check_key(processed, 'items'): folder.add_items(processed['items']) if check_key(processed, 'count') and totalrows > processed['count']: folder.add_item( label=_(_.NEXT_PAGE, _bold=True), path=plugin.url_for(func_or_url=replaytv_content, label=label, day=day, station=station, start=processed['count']), ) return folder
def login(ask=1, **kwargs): ask = int(ask) profile_settings = load_profile(profile_id=1) if len(profile_settings['devicekey']) == 0: _devicekey = 'w{uuid}'.format(uuid=uuid.uuid4()) query = "UPDATE `vars` SET `devicekey`='{devicekey}' WHERE profile_id={profile_id}".format( devicekey=_devicekey, profile_id=1) query_settings(query=query, return_result=False, return_insert=False, commit=True) creds = get_credentials() if len(creds['username']) < 1 or len(creds['password']) < 1 or ask == 1: username = gui.input(message=_.ASK_USERNAME, default=creds['username']).strip() if not len(username) > 0: gui.ok(message=_.EMPTY_USER, heading=_.LOGIN_ERROR_TITLE) return password = gui.input(message=_.ASK_PASSWORD, hide_input=True).strip() if not len(password) > 0: gui.ok(message=_.EMPTY_PASS, heading=_.LOGIN_ERROR_TITLE) return set_credentials(username=username, password=password) login_result = api.login() if login_result['result'] == False: query = "UPDATE `vars` SET `pswd`='', `last_login_success`='{last_login_success}' WHERE profile_id={profile_id}".format( last_login_success=0, profile_id=1) query_settings(query=query, return_result=False, return_insert=False, commit=True) if check_key(login_result['data'], 'error') and login_result['data']['error'] == 'toomany': gui.ok(message=_.TOO_MANY_DEVICES, heading=_.LOGIN_ERROR_TITLE) else: gui.ok(message=_.LOGIN_ERROR, heading=_.LOGIN_ERROR_TITLE) else: gui.ok(message=_.LOGIN_SUCCESS) query = "UPDATE `vars` SET `last_login_success`='{last_login_success}' WHERE profile_id={profile_id}".format( last_login_success=1, profile_id=1) query_settings(query=query, return_result=False, return_insert=False, commit=True) gui.refresh()
def _error(e): try: error = str(e) except: error = e.message.encode('utf-8') if not hasattr(e, 'heading') or not e.heading: e.heading = _(_.PLUGIN_ERROR, addon=ADDON_NAME) log.error(error) _close() gui.ok(error, heading=e.heading) resolve()
def login(self, username, password, channels=False): settings.remove(key='_cookies') self._session = Session(cookies_key='_cookies') session_url = '{api_url}/USER/SESSIONS/'.format(api_url=settings.get(key='_api_url')) session_post_data = { "credentialsStdAuth": { 'username': username, 'password': password, 'remember': 'Y', 'deviceRegistrationData': { 'deviceId': settings.get(key='_devicekey'), 'accountDeviceIdType': 'DEVICEID', 'deviceType' : 'PCTV', 'vendor' : settings.get(key='_browser_name'), 'model' : settings.get(key='_browser_version'), 'deviceFirmVersion' : settings.get(key='_os_name'), 'appVersion' : settings.get(key='_os_version') } }, } resp = self._session.post(session_url, json=session_post_data) if resp.status_code != 200: gui.ok(message=_.LOGIN_ERROR, heading=_.LOGIN_ERROR_TITLE) self.clear_session() return try: data = resp.json() except: return if not data or not check_key(data, 'resultCode') or data['resultCode'] == 'KO': gui.ok(message=_.LOGIN_ERROR, heading=_.LOGIN_ERROR_TITLE) self.clear_session() return if channels == True or settings.getInt(key='_channels_age') < int(time.time() - 86400): self.get_channels_for_user() self.vod_subscription() if settings.getBool(key='save_password', default=False): set_credentials(username=username, password=password) else: set_credentials(username=username, password='') self.logged_in = True
def login(ask=1, **kwargs): ask = int(ask) profile_settings = load_profile(profile_id=1) if len(profile_settings['devicekey']) == 0: devicekey = ''.join(random.choice(string.digits) for _ in range(10)) query = "UPDATE `vars` SET `devicekey`='{devicekey}' WHERE profile_id={profile_id}".format(devicekey=devicekey, profile_id=1) query_settings(query=query, return_result=False, return_insert=False, commit=True) creds = get_credentials() if len(creds['username']) < 1 or len(creds['password']) < 1 or ask == 1: username = gui.numeric(message=_.ASK_USERNAME, default=creds['username']).strip() if not len(username) > 0: gui.ok(message=_.EMPTY_USER, heading=_.LOGIN_ERROR_TITLE) return password = gui.numeric(message=_.ASK_PASSWORD).strip() if not len(password) > 0: gui.ok(message=_.EMPTY_PASS, heading=_.LOGIN_ERROR_TITLE) return set_credentials(username=username, password=password) login_result = api.login() if login_result['result'] == False: query = "UPDATE `vars` SET `pswd`='', `last_login_success`='{last_login_success}' WHERE profile_id={profile_id}".format(last_login_success=0, profile_id=1) query_settings(query=query, return_result=False, return_insert=False, commit=True) if check_key(login_result['data'], 'result') and check_key(login_result['data']['result'], 'retCode') and login_result['data']['result']['retCode'] == "157022007": gui.ok(message=_.TOO_MANY_DEVICES, heading=_.LOGIN_ERROR_TITLE) else: gui.ok(message=_.LOGIN_ERROR, heading=_.LOGIN_ERROR_TITLE) else: query = "UPDATE `vars` SET `last_login_success`='{last_login_success}' WHERE profile_id={profile_id}".format(last_login_success=1, profile_id=1) query_settings(query=query, return_result=False, return_insert=False, commit=True) gui.ok(message=_.LOGIN_SUCCESS) gui.refresh()
def login(**kwargs): creds = get_credentials() username = gui.numeric(message=_.ASK_USERNAME, default=creds['username']).strip() if not len(username) > 0: gui.ok(message=_.EMPTY_USER, heading=_.LOGIN_ERROR_TITLE) return password = gui.numeric(message=_.ASK_PASSWORD).strip() if not len(password) > 0: gui.ok(message=_.EMPTY_PASS, heading=_.LOGIN_ERROR_TITLE) return api.login(username=username, password=password, channels=True) plugin.logged_in = api.logged_in gui.refresh()
def login(self, username, password, channels=False): settings.remove(key='_access_token') user_agent = settings.get(key='_user_agent') HEADERS = { 'User-Agent': user_agent, 'X-Client-Id': settings.get(key='_client_id') + "||" + user_agent, 'X-OESP-Token': '', 'X-OESP-Username': username, } self._session = Session(headers=HEADERS) data = self.download(url=settings.get(key='_session_url'), type="post", code=[200], data={ "username": username, "password": password }, json_data=True, data_return=True, return_json=True, retry=True, check_data=False) if not data or not check_key(data, 'oespToken'): gui.ok(message=_.LOGIN_ERROR, heading=_.LOGIN_ERROR_TITLE) return settings.set(key='_access_token', value=data['oespToken']) self._session.headers.update({'X-OESP-Token': data['oespToken']}) if channels == True or settings.getInt( key='_channels_age') < int(time.time() - 86400): self.get_channels_for_user(location=data['locationId']) if settings.getBool(key='save_password', default=False): set_credentials(username=username, password=password) else: set_credentials(username=username, password='') self.logged_in = True
def check_entitlements(**kwargs): if plugin.logged_in: user_agent = settings.get(key='_user_agent') media_groups_url = '{mediagroups_url}/lgi-nl-vod-myprime-movies?byHasCurrentVod=true&range=1-1&sort=playCount7%7Cdesc'.format(mediagroups_url=settings.get('_mediagroupsfeeds_url')) data = api.download(url=media_groups_url, type="get", code=[200], data=None, json_data=False, data_return=True, return_json=True, retry=True, check_data=False) if not data or not check_key(data, 'entryCount'): gui.ok(message=_.NO_MOVIES_SERIES, heading=_.CHECKED_ENTITLEMENTS) settings.setBool(key='showMoviesSeries', value=False) return media_item_url = '{mediaitem_url}/{mediaitem_id}'.format(mediaitem_url=settings.get(key='_mediaitems_url'), mediaitem_id=data['mediaGroups'][0]['id']) data = api.download(url=media_item_url, type="get", code=[200], data=None, json_data=False, data_return=True, return_json=True, retry=True, check_data=False) if not data or not check_key(data, 'videoStreams'): gui.ok(message=_.NO_MOVIES_SERIES, heading=_.CHECKED_ENTITLEMENTS) settings.setBool(key='showMoviesSeries', value=False) return urldata = get_play_url(content=data['videoStreams']) if not urldata or not check_key(urldata, 'play_url') or not check_key(urldata, 'locator'): gui.ok(message=_.NO_MOVIES_SERIES, heading=_.CHECKED_ENTITLEMENTS) settings.setBool(key='showMoviesSeries', value=False) return token = api.get_play_token(locator=urldata['locator'], force=True) if not token or not len(token) > 0: gui.ok(message=_.NO_MOVIES_SERIES, heading=_.CHECKED_ENTITLEMENTS) settings.setBool(key='showMoviesSeries', value=False) return gui.ok(message=_.YES_MOVIES_SERIES, heading=_.CHECKED_ENTITLEMENTS) settings.setBool(key='showMoviesSeries', value=True) return
def login(self, username, password, channels=False, retry=True): if self._debug_mode: log.debug('Executing: api.login') log.debug( 'Vars: username={username}, password={password}, channels={channels}, retry={retry}' .format(username=username, password=password, channels=channels, retry=retry)) settings.remove(key='_cookies') self._cookies = '' self._session = Session(cookies_key='_cookies') session_url = '{api_url}/USER/SESSIONS/'.format(api_url=self._api_url) if self._debug_mode: log.debug('Clear Setting _cookies') log.debug('Creating new Requests Session') log.debug('Request Session Headers') log.debug(self._session.headers) email_or_pin = settings.getBool(key='email_instead_of_customer') if email_or_pin: session_post_data = { "credentialsExtAuth": { 'credentials': { 'loginType': 'UsernamePassword', 'username': username, 'password': password, 'appId': 'KPN', }, 'remember': 'Y', 'deviceInfo': { 'deviceId': self._devicekey, 'deviceIdType': 'DEVICEID', 'deviceType': 'PCTV', 'deviceVendor': settings.get(key='_browser_name'), 'deviceModel': settings.get(key='_browser_version'), 'deviceFirmVersion': settings.get(key='_os_name'), 'appVersion': settings.get(key='_os_version') } }, } else: session_post_data = { "credentialsStdAuth": { 'username': username, 'password': password, 'remember': 'Y', 'deviceRegistrationData': { 'deviceId': settings.get(key='_devicekey'), 'accountDeviceIdType': 'DEVICEID', 'deviceType': 'PCTV', 'vendor': settings.get(key='_browser_name'), 'model': settings.get(key='_browser_version'), 'deviceFirmVersion': settings.get(key='_os_name'), 'appVersion': settings.get(key='_os_version') } }, } data = self.download(url=session_url, type='post', code=[200], data=session_post_data, json_data=True, data_return=True, return_json=True, retry=retry, check_data=False) if not data or not check_key( data, 'resultCode') or data['resultCode'] == 'KO': if self._debug_mode: log.debug('Failure to retrieve expected data') log.debug('Execution Done: api.login') if email_or_pin: gui.ok(message=_.LOGIN_ERROR2, heading=_.LOGIN_ERROR_TITLE) else: gui.ok(message=_.LOGIN_ERROR, heading=_.LOGIN_ERROR_TITLE) self.clear_session() return False self._session_age = time.time() settings.setInt(key='_session_age', value=self._session_age) if self._debug_mode: log.debug('Settings _channels_age: {channels_age}'.format( channels_age=self._channels_age)) log.debug('Time - 86400 seconds: {time}'.format( time=int(time.time() - 86400))) if channels or self._channels_age < int(time.time() - 86400): self.get_channels_for_user() self.vod_subscription() self._username = username self._password = password if settings.getBool(key='save_password', default=False): set_credentials(username=username, password=password) else: set_credentials(username=username, password='') self.logged_in = True if self._debug_mode: log.debug('Execution Done: api.login') return True
def login(self, username, password, channels=False): settings.remove(key='_cookies') self._session = Session(cookies_key='_cookies') login_url = '{base_url}/inloggen'.format(base_url=CONST_BASE_URL) resp = self.download(url=login_url, type="get", code=None, data=None, json_data=False, data_return=True, return_json=False, retry=False, check_data=False) if resp.status_code != 200 and resp.status_code != 302: gui.ok(message=_.LOGIN_ERROR, heading=_.LOGIN_ERROR_TITLE) self.clear_session() return if self.check_data(resp=resp) == False: resp.encoding = 'utf-8' frmtoken = re.findall( r'name=\"form\[_token\]\"\s+value=\"([\S]*)\"', resp.text) session_post_data = { "form[password]": password, "form[email]": username, "form[login]": '', 'form[_token]': frmtoken[0], } resp = self.download(url=login_url, type="post", code=None, data=session_post_data, json_data=False, data_return=True, return_json=False, retry=False, check_data=False) if (resp.status_code != 200 and resp.status_code != 302) or self.check_data( resp=resp) == False: gui.ok(message=_.LOGIN_ERROR, heading=_.LOGIN_ERROR_TITLE) self.clear_session() return data = self.download( url='{base_url}/api/info'.format(base_url=CONST_BASE_URL), type="get", code=[200], data=None, json_data=False, data_return=True, return_json=True, retry=False, check_data=True) if not data or not check_key(data, 'sessionToken') or not check_key( data, 'emp'): gui.ok(message=_.LOGIN_ERROR, heading=_.LOGIN_ERROR_TITLE) self.clear_session() return settings.set(key='_session_token', value=data['sessionToken']) settings.set(key='_emp_url', value=data['emp']['url']) settings.set(key='_emp_customer', value=data['emp']['customer']) settings.set(key='_emp_businessunit', value=data['emp']['businessunit']) if channels == True or settings.getInt( key='_channels_age') < int(time.time() - 86400): self.get_channels_for_user(channels=data['channels']) if settings.getBool(key='save_password', default=False): set_credentials(username=username, password=password) else: set_credentials(username=username, password='') self.logged_in = True
def play_url(self, type, channel=None, id=None): playdata = {'path': '', 'license': '', 'token': ''} license = '' asset_id = '' militime = int(time.time() * 1000) if type == 'channel': play_url = '{api_url}/CONTENT/VIDEOURL/LIVE/{channel}/{id}/?deviceId={device_key}&profile=G02&time={time}'.format(api_url=settings.get(key='_api_url'), channel=channel, id=id, device_key=settings.get(key='_devicekey'), time=militime) else: if type == 'program': typestr = "PROGRAM" else: typestr = "VOD" program_url = '{api_url}/CONTENT/USERDATA/{type}/{id}'.format(api_url=settings.get(key='_api_url'), type=typestr, id=id) data = self.download(url=program_url, type='get', code=[200], data=None, json_data=False, data_return=True, return_json=True, retry=True, check_data=True) if not data or not check_key(data['resultObj'], 'containers'): return playdata for row in data['resultObj']['containers']: if check_key(row, 'entitlement') and check_key(row['entitlement'], 'assets'): for asset in row['entitlement']['assets']: if type == 'program': if check_key(asset, 'videoType') and check_key(asset, 'programType') and asset['videoType'] == 'SD_DASH_PR' and asset['programType'] == 'CUTV': asset_id = asset['assetId'] break else: if check_key(asset, 'videoType') and check_key(asset, 'assetType') and asset['videoType'] == 'SD_DASH_PR' and asset['assetType'] == 'MASTER': if check_key(asset, 'rights') and asset['rights'] == 'buy': gui.ok(message=_.NO_STREAM_AUTH, heading=_.PLAY_ERROR) return playdata asset_id = asset['assetId'] break if len(str(asset_id)) == 0: return playdata play_url = '{api_url}/CONTENT/VIDEOURL/{type}/{id}/{asset_id}/?deviceId={device_key}&profile=G02&time={time}'.format(api_url=settings.get(key='_api_url'), type=typestr, id=id, asset_id=asset_id, device_key=settings.get(key='_devicekey'), time=militime) data = self.download(url=play_url, type='get', code=[200], data=None, json_data=False, data_return=True, return_json=True, retry=True, check_data=True) if not data or not check_key(data['resultObj'], 'token') or not check_key(data['resultObj'], 'src') or not check_key(data['resultObj']['src'], 'sources') or not check_key(data['resultObj']['src']['sources'], 'src'): return playdata if check_key(data['resultObj']['src']['sources'], 'contentProtection') and check_key(data['resultObj']['src']['sources']['contentProtection'], 'widevine') and check_key(data['resultObj']['src']['sources']['contentProtection']['widevine'], 'licenseAcquisitionURL'): license = data['resultObj']['src']['sources']['contentProtection']['widevine']['licenseAcquisitionURL'] path = data['resultObj']['src']['sources']['src'] token = data['resultObj']['token'] real_url = "{hostscheme}://{hostname}".format(hostscheme=urlparse(path).scheme, hostname=urlparse(path).hostname) proxy_url = "http://127.0.0.1:{proxy_port}".format(proxy_port=settings.get(key='_proxyserver_port')) settings.set(key='_stream_hostname', value=real_url) path = path.replace(real_url, proxy_url) playdata = {'path': path, 'license': license, 'token': token} return playdata
def play_url(self, type, channel=None, id=None, test=False, from_beginning=False): if not self.get_session(): return None profile_settings = load_profile(profile_id=1) playdata = { 'path': '', 'license': '', 'token': '', 'type': '', 'info': '' } license = '' asset_id = '' militime = int(time.time() * 1000) typestr = 'PROGRAM' info = [] program_id = None if not test: counter = 0 while not self._abortRequested and not xbmc.Monitor( ).abortRequested() and counter < 5: profile_settings = load_profile(profile_id=1) if profile_settings['test_running'] == 0: break counter += 1 query = "UPDATE `vars` SET `last_playing`={last_playing} WHERE profile_id={profile_id}".format( last_playing=int(time.time()), profile_id=1) query_settings(query=query, return_result=False, return_insert=False, commit=True) if self._abortRequested or xbmc.Monitor().waitForAbort(1): self._abortRequested = True break if self._abortRequested or xbmc.Monitor().abortRequested(): return playdata if type == 'channel': if not test: info_url = '{api_url}/TRAY/SEARCH/LIVE?maxResults=1&filter_airingTime=now&filter_channelIds={channel}&orderBy=airingStartTime&sortOrder=desc'.format( api_url=profile_settings['api_url'], channel=channel) download = self.download(url=info_url, type='get', headers=None, data=None, json_data=False, return_json=True) data = download['data'] resp = download['resp'] if not resp or not resp.status_code == 200 or not data or not check_key( data, 'resultCode' ) or not data['resultCode'] == 'OK' or not check_key( data, 'resultObj') or not check_key( data['resultObj'], 'containers'): return playdata for row in data['resultObj']['containers']: program_id = row['id'] info = data play_url = '{api_url}/CONTENT/VIDEOURL/LIVE/{channel}/{id}/?deviceId={device_key}&profile=G02&time={time}'.format( api_url=profile_settings['api_url'], channel=channel, id=id, device_key=profile_settings['devicekey'], time=militime) else: if type == 'program': typestr = "PROGRAM" else: typestr = "VOD" program_id = id program_url = '{api_url}/CONTENT/USERDATA/{type}/{id}'.format( api_url=profile_settings['api_url'], type=typestr, id=id) download = self.download(url=program_url, type='get', headers=None, data=None, json_data=False, return_json=True) data = download['data'] resp = download['resp'] if not resp or not resp.status_code == 200 or not data or not check_key( data, 'resultCode' ) or not data['resultCode'] == 'OK' or not check_key( data, 'resultObj') or not check_key( data['resultObj'], 'containers'): return playdata for row in data['resultObj']['containers']: if check_key(row, 'entitlement') and check_key( row['entitlement'], 'assets'): for asset in row['entitlement']['assets']: if type == 'program': if check_key(asset, 'videoType') and check_key( asset, 'programType' ) and asset['videoType'] == 'SD_DASH_PR' and asset[ 'programType'] == 'CUTV': asset_id = asset['assetId'] break else: if check_key(asset, 'videoType') and check_key( asset, 'assetType' ) and asset['videoType'] == 'SD_DASH_PR' and asset[ 'assetType'] == 'MASTER': if check_key( asset, 'rights') and asset['rights'] == 'buy': gui.ok(message=_.NO_STREAM_AUTH, heading=_.PLAY_ERROR) return playdata asset_id = asset['assetId'] break if len(unicode(asset_id)) == 0: return playdata play_url = '{api_url}/CONTENT/VIDEOURL/{type}/{id}/{asset_id}/?deviceId={device_key}&profile=G02&time={time}'.format( api_url=profile_settings['api_url'], type=typestr, id=id, asset_id=asset_id, device_key=profile_settings['devicekey'], time=militime) if self._abortRequested or xbmc.Monitor().abortRequested(): return playdata if program_id and not test: info_url = '{api_url}/CONTENT/DETAIL/{type}/{id}'.format( api_url=profile_settings['api_url'], type=typestr, id=program_id) download = self.download(url=info_url, type='get', headers=None, data=None, json_data=False, return_json=True) data = download['data'] resp = download['resp'] if not resp or not resp.status_code == 200 or not data or not check_key( data, 'resultCode' ) or not data['resultCode'] == 'OK' or not check_key( data, 'resultObj') or not check_key( data['resultObj'], 'containers'): return playdata info = data if self._abortRequested or xbmc.Monitor().waitForAbort(1): return playdata download = self.download(url=play_url, type='get', headers=None, data=None, json_data=False, return_json=True) data = download['data'] resp = download['resp'] if not resp or not resp.status_code == 200 or not data or not check_key( data, 'resultCode' ) or not data['resultCode'] == 'OK' or not check_key( data, 'resultObj') or not check_key( data['resultObj'], 'token') or not check_key( data['resultObj'], 'src') or not check_key( data['resultObj']['src'], 'sources') or not check_key( data['resultObj']['src']['sources'], 'src'): return playdata if check_key( data['resultObj']['src']['sources'], 'contentProtection') and check_key( data['resultObj']['src']['sources']['contentProtection'], 'widevine') and check_key( data['resultObj']['src']['sources'] ['contentProtection']['widevine'], 'licenseAcquisitionURL'): license = data['resultObj']['src']['sources']['contentProtection'][ 'widevine']['licenseAcquisitionURL'] path = data['resultObj']['src']['sources']['src'] token = data['resultObj']['token'] if not test: real_url = "{hostscheme}://{netloc}".format( hostscheme=urlparse(path).scheme, netloc=urlparse(path).netloc) proxy_url = "http://127.0.0.1:{proxy_port}".format( proxy_port=profile_settings['proxyserver_port']) path = path.replace(real_url, proxy_url) query = "UPDATE `vars` SET `stream_hostname`='{stream_hostname}' WHERE profile_id={profile_id}".format( stream_hostname=real_url, profile_id=1) query_settings(query=query, return_result=False, return_insert=False, commit=True) playdata = { 'path': path, 'license': license, 'token': token, 'type': typestr, 'info': info } return playdata
def install_widevine(reinstall=False): ia_addon = get_ia_addon(required=True) system, arch = _get_system_arch() kodi_version = get_kodi_version() if kodi_version < 18: raise InputStreamError(_(_.IA_KODI18_REQUIRED, system=system)) elif system == 'Android': return True elif system == 'UWP': raise InputStreamError(_.IA_UWP_ERROR) elif 'aarch64' in arch or 'arm64' in arch: raise InputStreamError(_.IA_AARCH64_ERROR) last_check = int(ia_addon.getSetting('_last_check') or 0) ver_slug = system + arch + str(kodi_version) + ia_addon.getAddonInfo( 'version') if ver_slug != ia_addon.getSetting(IA_VERSION_KEY): reinstall = True if not reinstall and time.time() - last_check < 86400: return True ia_addon.setSetting(IA_VERSION_KEY, '') ia_addon.setSetting('_last_check', str(int(time.time()))) r = load_file(file="settings.json", isJSON=True) widevine = r['widevine']['widevine'] wv_platform = widevine['platforms'].get(system + arch, None) if not wv_platform: raise InputStreamError( _(_.IA_NOT_SUPPORTED, system=system, arch=arch, kodi_version=kodi_version)) decryptpath = xbmc.translatePath(ia_addon.getSetting('DECRYPTERPATH')) if sys.version_info < (3, 0): decryptpath = decryptpath.decode("utf-8") if 'arm' in arch: url = wv_platform['zip'] else: url = widevine['base_url'] + wv_platform['zip'] wv_path = os.path.join(decryptpath, wv_platform['dst']) if not os.path.isdir(decryptpath): os.makedirs(decryptpath) if not os.path.isdir(ADDON_PROFILE + "tmp"): os.makedirs(ADDON_PROFILE + "tmp") if not _download(url, wv_platform['dst'], wv_path, arch, wv_platform['md5']): return False ia_addon.setSetting(IA_VERSION_KEY, ver_slug) if reinstall: gui.ok(_.IA_WV_INSTALL_OK) return True
def play_video(type=None, id=None, locator=None, catchup=None, duration=0, **kwargs): properties = {} label = '' info = {} art = {} if not type or not len(type) > 0: return False if (catchup and len(catchup) > 0) or type=='program': if catchup and len(catchup) > 0: id = catchup properties['seekTime'] = 1 type = 'program' if not id or not len(id) > 0: return False if type == "program": listings_url = "{listings_url}/{id}".format(listings_url=settings.get(key='_listings_url'), id=id) data = api.download(url=listings_url, type="get", code=[200], data=None, json_data=False, data_return=True, return_json=True, retry=True, check_data=False) if not data or not check_key(data, 'program') or not check_key(data['program'], 'videoStreams'): gui.ok(message=_.STREAM_NOT_AVAILABLE, heading=_.STREAM_NOT_FOUND) return False urldata = get_play_url(content=data['program']['videoStreams']) if not urldata or not check_key(urldata, 'play_url') or not check_key(urldata, 'locator'): gui.ok(message=_.STREAM_NOT_AVAILABLE, heading=_.STREAM_NOT_FOUND) return False playdata = api.play_url(type='program', path=urldata['play_url'], locator=urldata['locator']) if check_key(data['program'], 'duration'): duration = int(data['program']['duration']) elif check_key(data, 'startTime') and check_key(data, 'endTime'): duration = int(int(data['endTime']) - int(data['startTime'])) // 1000 label = data['program']['title'] info = { 'plot': data['program']['description'], 'duration': duration, 'mediatype': 'video'} art = {'thumb': get_image("boxart", data['program']['images'])} elif type == "vod": playdata = api.play_url(type='vod', path=id) elif type == "channel": if not locator or not len(locator) > 0: return False playdata = api.play_url(type='channel', path=id, locator=locator) if not check_key(playdata, 'path') or not check_key(playdata, 'license') or not check_key(playdata, 'token') or not check_key(playdata, 'locator'): return False user_agent = settings.get(key='_user_agent') creds = get_credentials() CDMHEADERS = { 'User-Agent': user_agent, 'X-Client-Id': settings.get(key='_client_id') + '||' + user_agent, 'X-OESP-Token': settings.get(key='_access_token'), 'X-OESP-Username': creds['username'], 'X-OESP-License-Token': settings.get(key='_drm_token'), 'X-OESP-DRM-SchemeIdUri': 'urn:uuid:edef8ba9-79d6-4ace-a3c8-27dcd51d21ed', 'X-OESP-Content-Locator': playdata['locator'], } settings.setInt(key='_stream_duration', value=duration) listitem = plugin.Item( properties = properties, label = label, info = info, art = art, playable = True, path = playdata['path'], headers = CDMHEADERS, inputstream = inputstream.Widevine( license_key = playdata['license'], media_renewal_url = plugin.url_for(func_or_url=renew_token, id=playdata['path'], type=type, locator=playdata['locator']), media_renewal_time = 60, ), ) return listitem
def play_url(self, type, path=None, locator=None): playdata = {'path': '', 'license': '', 'token': '', 'locator': ''} if not type or not len(type) > 0: return playdata if type == 'vod': if not path or not len(path) > 0: return playdata mediaitems_url = '{mediaitems_url}/{path}'.format( mediaitems_url=settings.get(key='_mediaitems_url'), path=path) data = self.download(url=mediaitems_url, type="get", code=[200], data=None, json_data=False, data_return=True, return_json=True, retry=True, check_data=False) if not data or not check_key(data, 'videoStreams'): return playdata urldata = get_play_url(content=data['videoStreams']) if urldata and check_key(urldata, 'play_url') and check_key( urldata, 'locator'): path = urldata['play_url'] locator = urldata['locator'] if not path or not locator or not len(path) > 0 or not len( locator) > 0: return playdata license = settings.get('_widevine_url') token = self.get_play_token(locator=locator, force=True) if not token or not len(token) > 0: gui.ok(message=_.NO_STREAM_AUTH, heading=_.PLAY_ERROR) return playdata token = 'WIDEVINETOKEN' token_regex = re.search(r"(?<=;vxttoken=)(.*?)(?=/)", path) if token_regex and token_regex.group(1) and len( token_regex.group(1)) > 0: path = path.replace(token_regex.group(1), token) else: if 'sdash/' in path: spliturl = path.split('sdash/', 1) if len(spliturl) == 2: path = '{urlpart1}sdash;vxttoken={token}/{urlpart2}?device=Orion-Replay-DASH'.format( urlpart1=spliturl[0], token=token, urlpart2=spliturl[1]) else: spliturl = path.rsplit('/', 1) if len(spliturl) == 2: path = '{urlpart1};vxttoken={token}/{urlpart2}'.format( urlpart1=spliturl[0], token=token, urlpart2=spliturl[1]) real_url = "{hostscheme}://{hostname}".format( hostscheme=urlparse(path).scheme, hostname=urlparse(path).hostname) proxy_url = "http://127.0.0.1:{proxy_port}".format( proxy_port=settings.get(key='_proxyserver_port')) settings.set(key='_stream_hostname', value=real_url) path = path.replace(real_url, proxy_url) playdata = { 'path': path, 'license': license, 'token': token, 'locator': locator } return playdata
def new_session(self, force=False, retry=True, channels=False): self.check_vars() if self._debug_mode: log.debug('Executing: api.new_session') log.debug( 'Vars: force={force}, retry={retry}, channels={channels}'. format(force=force, retry=retry, channels=channels)) log.debug('Cookies: {cookies}'.format(cookies=self._cookies)) username = self._username password = self._password if len(self._cookies) > 0 and len( username ) > 0 and not force and not channels and self._session_age > int( time.time() - 7200) and self._last_login_success: self.logged_in = True try: self._session except: self._session = Session(cookies_key='_cookies') if self._debug_mode: log.debug('Creating new Requests Session') log.debug('Request Session Headers') log.debug(self._session.headers) log.debug('api.logged_in: {logged_in}'.format( logged_in=self.logged_in)) return True self.logged_in = False if self._debug_mode: log.debug( 'api.logged_in: {logged_in}'.format(logged_in=self.logged_in)) if not len(username) > 0: if self._debug_mode: log.debug('Username length = 0') log.debug('Execution Done: api.new_session') settings.setBool(key="_last_login_success", value=self.logged_in) self._last_login_success = self.logged_in return False if not len(password) > 0: email_or_pin = settings.getBool(key='email_instead_of_customer') if not force: if self._debug_mode: log.debug('Password length = 0 and force is false') log.debug('Execution Done: api.new_session') settings.setBool(key="_last_login_success", value=self.logged_in) self._last_login_success = self.logged_in return False if email_or_pin: password = gui.input(message=_.ASK_PASSWORD2, hide_input=True).strip() else: password = gui.numeric(message=_.ASK_PASSWORD).strip() if not len(password) > 0: if self._debug_mode: log.debug('Password length = 0') log.debug('Execution Done: api.new_session') if email_or_pin: gui.ok(message=_.EMPTY_PASS2, heading=_.LOGIN_ERROR_TITLE) else: gui.ok(message=_.EMPTY_PASS, heading=_.LOGIN_ERROR_TITLE) settings.setBool(key="_last_login_success", value=self.logged_in) self._last_login_success = self.logged_in return False self.login(username=username, password=password, channels=channels, retry=retry) if self._debug_mode: log.debug('Execution Done: api.new_session') log.debug( 'api.logged_in: {logged_in}'.format(logged_in=self.logged_in)) settings.setBool(key="_last_login_success", value=self.logged_in) self._last_login_success = self.logged_in if self.logged_in: return True return False
def play_url(self, type, channel=None, id=None, test=False, from_beginning=False): if self._debug_mode: log.debug('Executing: api.play_url') log.debug( 'Vars: type={type}, channel={channel}, id={id}, test={test}'. format(type=type, channel=channel, id=id, test=test)) playdata = {'path': '', 'license': '', 'token': ''} license = '' asset_id = '' militime = int(time.time() * 1000) typestr = 'PROGRAM' info = [] program_id = None if not test: while not self._abortRequested and not xbmc.Monitor( ).abortRequested() and settings.getBool(key='_test_running'): settings.setInt(key='_last_playing', value=time.time()) if self._abortRequested or xbmc.Monitor().waitForAbort(1): self._abortRequested = True break if self._abortRequested or xbmc.Monitor().abortRequested(): return playdata if type == 'channel': if not test: info_url = '{api_url}/TRAY/SEARCH/LIVE?maxResults=1&filter_airingTime=now&filter_channelIds={channel}&orderBy=airingStartTime&sortOrder=desc'.format( api_url=self._api_url, channel=channel) data = self.download(url=info_url, type='get', code=[200], data=None, json_data=False, data_return=True, return_json=True, retry=True, check_data=True) if not data or not check_key(data['resultObj'], 'containers'): if self._debug_mode: log.debug('Failure to retrieve expected data') log.debug('Execution Done: api.play_url') return playdata for row in data['resultObj']['containers']: program_id = row['id'] info = data play_url = '{api_url}/CONTENT/VIDEOURL/LIVE/{channel}/{id}/?deviceId={device_key}&profile=G02&time={time}'.format( api_url=self._api_url, channel=channel, id=id, device_key=self._devicekey, time=militime) else: if type == 'program': typestr = "PROGRAM" else: typestr = "VOD" program_id = id program_url = '{api_url}/CONTENT/USERDATA/{type}/{id}'.format( api_url=self._api_url, type=typestr, id=id) data = self.download(url=program_url, type='get', code=[200], data=None, json_data=False, data_return=True, return_json=True, retry=True, check_data=True) if not data or not check_key(data['resultObj'], 'containers'): if self._debug_mode: log.debug('Failure to retrieve expected data') log.debug('Execution Done: api.play_url') return playdata for row in data['resultObj']['containers']: if check_key(row, 'entitlement') and check_key( row['entitlement'], 'assets'): for asset in row['entitlement']['assets']: if type == 'program': if check_key(asset, 'videoType') and check_key( asset, 'programType' ) and asset['videoType'] == 'SD_DASH_PR' and asset[ 'programType'] == 'CUTV': asset_id = asset['assetId'] break else: if check_key(asset, 'videoType') and check_key( asset, 'assetType' ) and asset['videoType'] == 'SD_DASH_PR' and asset[ 'assetType'] == 'MASTER': if check_key( asset, 'rights') and asset['rights'] == 'buy': gui.ok(message=_.NO_STREAM_AUTH, heading=_.PLAY_ERROR) return playdata asset_id = asset['assetId'] break if len(unicode(asset_id)) == 0: if self._debug_mode: log.debug('Failure, empty asset_id') log.debug('Execution Done: api.play_url') return playdata play_url = '{api_url}/CONTENT/VIDEOURL/{type}/{id}/{asset_id}/?deviceId={device_key}&profile=G02&time={time}'.format( api_url=self._api_url, type=typestr, id=id, asset_id=asset_id, device_key=self._devicekey, time=militime) if self._abortRequested or xbmc.Monitor().abortRequested(): return playdata if program_id and not test: info_url = '{api_url}/CONTENT/DETAIL/{type}/{id}'.format( api_url=self._api_url, type=typestr, id=program_id) data = self.download(url=info_url, type='get', code=[200], data=None, json_data=False, data_return=True, return_json=True, retry=True, check_data=True) if not data or not check_key(data['resultObj'], 'containers'): if self._debug_mode: log.debug('Failure to retrieve expected data') log.debug('Execution Done: api.play_url') return playdata info = data if self._abortRequested or xbmc.Monitor().waitForAbort(1): return playdata data = self.download(url=play_url, type='get', code=[200], data=None, json_data=False, data_return=True, return_json=True, retry=True, check_data=True) if not data or not check_key( data['resultObj'], 'token') or not check_key( data['resultObj'], 'src') or not check_key( data['resultObj']['src'], 'sources') or not check_key( data['resultObj']['src']['sources'], 'src'): if self._debug_mode: log.debug('Failure, empty token or source') log.debug('Execution Done: api.play_url') return playdata if check_key( data['resultObj']['src']['sources'], 'contentProtection') and check_key( data['resultObj']['src']['sources']['contentProtection'], 'widevine') and check_key( data['resultObj']['src']['sources'] ['contentProtection']['widevine'], 'licenseAcquisitionURL'): license = data['resultObj']['src']['sources']['contentProtection'][ 'widevine']['licenseAcquisitionURL'] path = data['resultObj']['src']['sources']['src'] token = data['resultObj']['token'] if not test: real_url = "{hostscheme}://{netloc}".format( hostscheme=urlparse(path).scheme, netloc=urlparse(path).netloc) proxy_url = "http://127.0.0.1:{proxy_port}".format( proxy_port=settings.getInt(key='_proxyserver_port')) if self._debug_mode: log.debug('Real url: {real_url}'.format(real_url=real_url)) log.debug('Proxy url: {proxy_url}'.format(proxy_url=proxy_url)) settings.set(key='_stream_hostname', value=real_url) path = path.replace(real_url, proxy_url) settings.setInt(key='_drm_token_age', value=time.time()) settings.set(key='_renew_path', value=path) settings.set(key='_renew_token', value=token) playdata = { 'path': path, 'license': license, 'token': token, 'type': typestr, 'info': info } if self._debug_mode: log.debug( 'Returned Playdata: {playdata}'.format(playdata=playdata)) log.debug('Execution Done: api.play_url') return playdata
def login(self, username, password, channels=False, retry=True): if self._debug_mode: log.debug('Executing: api.login') log.debug('Vars: username={username}, password={password}, channels={channels}, retry={retry}'.format(username=username, password=password, channels=channels, retry=retry)) oauth = '' settings.remove(key='_cookies') self._cookies = '' settings.remove(key='_session_token') self._session_token = '' self._session = Session(cookies_key='_cookies') self._session.headers = CONST_BASE_HEADERS auth_url = '{login_url}/authenticate?redirect_uri=https%3A%2F%2Flivetv.canaldigitaal.nl%2Fauth.aspx&state={state}&response_type=code&scope=TVE&client_id=StreamGroup'.format(login_url=CONST_LOGIN_URL, state=int(time.time())) if self._debug_mode: log.debug('Clear Setting _cookies') log.debug('Creating new Requests Session') log.debug('Request Session Headers') log.debug(self._session.headers) data = self.download(url=auth_url, type="get", code=[200], data=None, json_data=False, data_return=True, return_json=False, retry=retry, check_data=False, allow_redirects=False) if not data: if self._debug_mode: log.debug('Failure to retrieve expected data') log.debug('Execution Done: api.login') gui.ok(message=_.LOGIN_ERROR, heading=_.LOGIN_ERROR_TITLE) self.clear_session() return False self._session.headers = CONST_LOGIN_HEADERS self._session.headers.update({'Referer': auth_url}) session_post_data = { "Password": password, "Username": username, } if self._debug_mode: log.debug('Request Session Headers') log.debug(self._session.headers) resp = self.download(url=CONST_LOGIN_URL, type="post", code=None, data=session_post_data, json_data=False, data_return=True, return_json=False, retry=retry, check_data=False, allow_redirects=False) if (resp.status_code != 302): if self._debug_mode: log.debug('Failure to retrieve expected data') log.debug('Execution Done: api.login') gui.ok(message=_.LOGIN_ERROR, heading=_.LOGIN_ERROR_TITLE) self.clear_session() return False params = parse_qs(urlparse(resp.headers['Location']).query) if check_key(params, 'code'): oauth = params['code'][0] if self._debug_mode: log.debug('Params: {params}'.format(params=params)) log.debug('OAuth: {oauth}'.format(oauth=oauth)) if len(oauth) == 0: if self._debug_mode: log.debug('Failure to retrieve expected data') log.debug('Execution Done: api.login') gui.ok(message=_.LOGIN_ERROR, heading=_.LOGIN_ERROR_TITLE) self.clear_session() return False challenge_url = "{base_url}/m7be2iphone/challenge.aspx".format(base_url=CONST_BASE_URL) browser_name = settings.get(key='_browser_name') session_post_data = { "autotype": "nl", "app": "cds", "prettyname": browser_name, "model": "web", "serial": self._devicekey, "oauthcode": oauth } self._session.headers = CONST_BASE_HEADERS self._session.headers.update({'Content-Type': 'application/json;charset=UTF-8'}) if self._debug_mode: log.debug('Request Session Headers') log.debug(self._session.headers) data = self.download(url=challenge_url, type="post", code=[200], data=session_post_data, json_data=True, data_return=True, return_json=True, retry=retry, check_data=False, allow_redirects=False) if not data or not check_key(data, 'id') or not check_key(data, 'secret'): if check_key(data, 'error') and data['error'] == 'toomany': gui.ok(message=_.TOO_MANY_DEVICES, heading=_.LOGIN_ERROR_TITLE) else: gui.ok(message=_.LOGIN_ERROR, heading=_.LOGIN_ERROR_TITLE) if self._debug_mode: log.debug('Failure to retrieve expected data') log.debug('Execution Done: api.login') self.clear_session() return False login_url = "{base_url}/m7be2iphone/login.aspx".format(base_url=CONST_BASE_URL) self._session.headers = CONST_BASE_HEADERS self._session.headers.update({'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8'}) if self._debug_mode: log.debug('Request Session Headers') log.debug(self._session.headers) secret = '{id}\t{secr}'.format(id=data['id'], secr=data['secret']) session_post_data = { "secret": secret, "uid": self._devicekey, "app": "cds", } resp = self.download(url=login_url, type="post", code=None, data=session_post_data, json_data=False, data_return=True, return_json=False, retry=retry, check_data=False, allow_redirects=False) if (resp.status_code != 302): if self._debug_mode: log.debug('Failure to retrieve expected data') log.debug('Execution Done: api.login') gui.ok(message=_.LOGIN_ERROR, heading=_.LOGIN_ERROR_TITLE) self.clear_session() return False ssotoken_url = "{base_url}/m7be2iphone/capi.aspx?z=ssotoken".format(base_url=CONST_BASE_URL) self._session.headers = CONST_BASE_HEADERS if self._debug_mode: log.debug('Request Session Headers') log.debug(self._session.headers) data = self.download(url=ssotoken_url, type="get", code=[200], data=None, json_data=False, data_return=True, return_json=True, retry=retry, check_data=False, allow_redirects=False) if not data or not check_key(data, 'ssotoken'): if self._debug_mode: log.debug('Failure to retrieve expected data') log.debug('Execution Done: api.login') gui.ok(message=_.LOGIN_ERROR, heading=_.LOGIN_ERROR_TITLE) self.clear_session() return False session_url = "{api_url}/session".format(api_url=CONST_DEFAULT_API) session_post_data = { "sapiToken": data['ssotoken'], "deviceType": "PC", "deviceModel": browser_name, "osVersion": '{name} {version}'.format(name=settings.get(key='_os_name'), version=settings.get(key='_os_version')), "deviceSerial": self._devicekey, "appVersion": settings.get(key='_browser_version'), "brand": "cds" } self._session.headers = CONST_BASE_HEADERS self._session.headers.update({'Content-Type': 'application/json;charset=UTF-8'}) if self._debug_mode: log.debug('Request Session Headers') log.debug(self._session.headers) data = self.download(url=session_url, type="post", code=[200], data=session_post_data, json_data=True, data_return=True, return_json=True, retry=retry, check_data=False, allow_redirects=False) if not data or not check_key(data, 'token'): if self._debug_mode: log.debug('Failure to retrieve expected data') log.debug('Execution Done: api.login') gui.ok(message=_.LOGIN_ERROR, heading=_.LOGIN_ERROR_TITLE) self.clear_session() return False self._session_token = data['token'] settings.set(key='_session_token', value=self._session_token) self._session_age = time.time() settings.setInt(key='_session_age', value=self._session_age) if self._debug_mode: log.debug('Session Token: {session_token}'.format(session_token=self._session_token)) log.debug('Settings _channels_age: {channels_age}'.format(channels_age=self._channels_age)) log.debug('Time - 86400 seconds: {time}'.format(time=int(time.time() - 86400))) if channels or self._channels_age < int(time.time() - 86400): self.get_channels_for_user() self._username = username self._password = password if settings.getBool(key='save_password', default=False): set_credentials(username=username, password=password) else: set_credentials(username=username, password='') self.logged_in = True self._session.headers = CONST_BASE_HEADERS self._session.headers.update({'Authorization': 'Bearer ' + self._session_token}) if self._debug_mode: log.debug('Request Session Headers') log.debug(self._session.headers) log.debug('Execution Done: api.login') return True