def remove_device(self, uid): """ Remove the specified device. :param str uid: The ID of the device to remove. """ util.http_post(SOLOCOO_API + '/devices', token_bearer=self._account.jwt_token, data={'delete': [uid]})
def verify_pin(self, pin): """ Verify the PIN. :param str pin: The PIN to validate. :returns: Returns true if the PIN is valid. :rtype: boolean """ try: util.http_post(SOLOCOO_API + '/pin/parental/verify', token_bearer=self._tokens.jwt_token, data={ "pin": pin, }) return True except HTTPError: return False
def _get_jwt_token(self, sapi_token, device_name, device_serial): reply = util.http_post(SOLOCOO_API + '/session', data=dict( sapiToken=sapi_token, deviceModel=device_name, deviceType="PC", deviceSerial=device_serial, osVersion="Linux undefined", appVersion="84.0", memberId="0", brand=self._tenant.get('app'), )) return json.loads(reply.text).get('token')
def get_stream(self, asset_id): """ Get stream information for the requested asset. :param str asset_id: The ID of the asset :returns: Information on how to play this asset. :rtype: StreamInfo """ _LOGGER.debug('Requesting stream info for channel %s', asset_id) try: reply = util.http_post( SOLOCOO_API + '/assets/{asset_id}/play'.format(asset_id=asset_id), token_bearer=self._tokens.jwt_token, data={ "player": { "name": "Bitmovin", "version": "8.22.0", "capabilities": { "mediaTypes": ["DASH"], # ["DASH", "HLS", "MSSS", "Unspecified"] "drmSystems": ["Widevine"] }, "drmSystems": ["Widevine"] } }) except HTTPError as ex: if ex.response.status_code == 402: raise NotAvailableInOfferException if ex.response.status_code == 403: raise UnavailableException if ex.response.status_code == 404: raise UnavailableException raise data = json.loads(reply.text) stream = StreamInfo( url=data.get('url'), protocol=data.get('mediaType'), drm_protocol=data.get('drm', {}).get('system'), drm_license_url=data.get('drm', {}).get('licenseUrl'), drm_certificate=data.get('drm', {}).get('cert'), ) return stream
def _get_oauth_code(self, username, password): """ Do login with the sso and return the OAuth code. :param str username: The username to authenticate with. :param str password: The password to authenticate with. :returns: An OAuth code we can use to continue authenticating. :rtype: string """ # This is probably not necessary for all providers, and this also might need some factory pattern to support # other providers. # Ask to forward us to the login form. login_page = util.http_get( 'https://{domain}/{env}/sso.aspx'.format( domain=self._tenant.get('domain'), env=self._tenant.get('env')), params=dict( a=self._tenant.get('app'), s=time.time() * 100, # unixtime in milliseconds d='PC', )) # Extract the path from the form, the form posts to / form_action = re.compile(r'<form action="([^"]+)"').search( login_page.text).group(1) login_url = urljoin(login_page.url, form_action) # Submit credentials reply = util.http_post(login_url, form=dict( Username=username, Password=password, )) # We should get redirected, if not, there was an issue with the credentials. if not reply.history: raise InvalidLoginException # Extract query parameters from redirected url params = parse_qs(urlparse(reply.url).query) return params.get('code')[0]
def _do_challenge(self, device_name, device_serial, username, password): """ Do an authentication challenge. :param str device_name: The device name of this running Kodi instance. :param str device_serial: The device serial of this running Kodi instance. :param str username: The username to authenticate with. :param str password: The password to authenticate with. :return: A tuple (challenge_id, challenge_secret) that can be used to fetch a token. :rtype: tuple(str, str) """ if username and password: # Do authenticated login oauth_code = self._get_oauth_code(username, password) data = dict( autotype='nl', app=self._tenant.get('app'), prettyname=device_name, model='web', serial=device_serial, oauthcode=oauth_code, apikey='', ) else: # Do anonymous login data = dict( autotype='nl', app=self._tenant.get('app'), prettyname=device_name, model='web', serial=device_serial, ) # TODO: catch exception reply = util.http_post('https://{domain}/{env}/challenge.aspx'.format( domain=self._tenant.get('domain'), env=self._tenant.get('env')), data=data) challenge = json.loads(reply.text) return challenge.get('id'), challenge.get('secret')
def _get_jwt_token(self, sapi_token, device_name, device_serial): """ Get a JWT token. :param str sapi_token: The SAPI token we got when authenticating. :param str device_name: The name of this device. :param str device_serial: The serial number of this device. :returns: A JWT token. :rtype: str """ reply = util.http_post(SOLOCOO_API + '/session', data=dict( sapiToken=sapi_token, deviceModel=device_name, deviceType="PC", deviceSerial=device_serial, osVersion="Linux undefined", appVersion="84.0", memberId="0", brand=self._tenant.get('app'), )) return json.loads(reply.text).get('token')
def _get_aspx_cookie(self, challenge_id, challenge_secret, device_serial): """ Get an ASPX cookie. :param str challenge_id: The challenge ID we got from logging in. :param str challenge_secret: The challenge secret we got from logging in. :param str device_serial: The device serial of this running Kodi instance. :returns: An ASPX token. :rtype: str """ reply = util.http_post('https://{domain}/{env}/login.aspx'.format( domain=self._tenant.get('domain'), env=self._tenant.get('env')), form=dict( secret=challenge_id + '\t' + challenge_secret, uid=device_serial, app=self._tenant.get('app'), )) # We got redirected, and the last response doesn't contain the cookie we need. # We need to get it from the redirect history. return reply.history[0].cookies.get('.ASPXAUTH')
def _get_oauth_code(self, username, password): """ Do login with the sso and return the OAuth code. :return: An OAuth code we can use to continue authenticating. :rtype: string """ # This is probably not necessary for all providers, and this also might need some factory pattern to support # other providers. # Ask to forward us to the login form. util.http_get( 'https://{domain}/{env}/sso.aspx'.format( domain=self._tenant.get('domain'), env=self._tenant.get('env')), params=dict( a=self._tenant.get('app'), s=time.time() * 100, # unixtime in milliseconds )) # TODO: we could extract the correct url from the form in the html, but this is probably provider dependant anyway. # Submit credentials reply = util.http_post( 'https://{auth}/'.format(auth=self._tenant.get('auth')), form=dict( Username=username, Password=password, )) if 'De gebruikersnaam of het wachtwoord dat u heeft ingegeven is niet correct' in reply.text: raise InvalidLoginException # Extract query parameters from redirected url params = parse_qs(urlparse(reply.url).query) return params.get('code')[0]