예제 #1
0
    def _purchase_free(self, app, data):
        """"Purchases" an application. Google Play requires this even for free applications.
            Basically, it is used to associate the application with the provided account.
            Additionally, this returns a download token required to get the app from the server.
        
        Parameters
        ----------
        app : App
            The app to purchase.
        data : dict
            Parameters required for a successful query.

        Returns
        -------
        str
            A download token required to access the app on the server.
        """
        response = verbose_post(SERVER + 'fdfe/purchase',
                                data=data,
                                headers=self._base_headers())
        proto_response = ResponseWrapper.FromString(response.content)
        error = proto_response.commands.displayErrorMessage
        if error == "":
            return proto_response.payload.buyResponse.downloadToken
        elif error == 'Can\'t install. Please try again later.':
            raise Retry(app.package_name())
        elif 'busy' in error:
            raise Wait(app.package_name())
        else:
            raise RequestError(error)
예제 #2
0
 def _upload_device_configuration(self):
     """Uploads the device configuration to Google Play.
         Necessary for any login as we simulate an Android device.
     """
     LOGGER.info(f'Uploading Device Configuration for {self.device.userreadablename}')
     upload = UploadDeviceConfigRequest()
     upload.deviceConfiguration.CopyFrom(self.device.get_device_config())
     headers = self._base_headers()
     headers['X-DFE-Enabled-Experiments'] = "cl:billing.select_add_instrument_by_default"
     headers['X-DFE-Unsupported-Experiments'] = ('nocache:billing.use_charging_poller,'
                                                 'market_emails,buyer_currency,prod_baseline,'
                                                 'checkin.set_asset_paid_app_field, '
                                                 'shekel_test,content_ratings,buyer_currency_in_app,'
                                                 'nocache:encrypted_apk,recent_changes')
     headers['X-DFE-SmallestScreenWidthDp'] = "320"
     headers['X-DFE-Filter-Level'] = "3"
     data = upload.SerializeToString()
     response = verbose_post('https://android.clients.google.com/fdfe/uploadDeviceConfig',
                             data=data, headers=headers)
     proto_response = ResponseWrapper.FromString(response.content)
     try:
         if proto_response.payload.HasField('uploadDeviceConfigResponse'):
             self.device_config_token = proto_response.payload.uploadDeviceConfigResponse.uploadDeviceConfigToken
     except ValueError:
         pass
예제 #3
0
    def _issue_checkin(self, ac2dm_token):
        """Perform a checkin (two actually), which is necessary to complete a login to Google Play.

        Parameters
        ----------
        ac2dm_token : str
            An ac2dm token issued by Google Play.
        Returns
        -------
        str
            An Android ID.
        """
        headers = self._base_headers()
        headers['Content-Type'] = 'application/x-protobuf'
        request = AndroidCheckinRequest()
        request.id = 0
        request.checkin.CopyFrom(self.device.get_checkin())
        request.locale = 'em_US'
        request.timeZone = 'UTC'
        request.version = 3
        request.deviceConfiguration.CopyFrom(self.device.get_device_config())
        request.fragment = 0
        data = request.SerializeToString()
        response = verbose_post('https://android.clients.google.com/checkin',
                                data=data, headers=headers)
        proto_response = AndroidCheckinResponse()
        proto_response.ParseFromString(response.content)
        self.device_checkin_consistency_token = proto_response.deviceCheckinConsistencyToken
        android_id = proto_response.androidId
        security_token = proto_response.securityToken
        # TODO We may not need the second checkin
        second_request = request
        second_request.id = android_id
        second_request.securityToken = security_token
        second_request.accountCookie.append(f'[{self.mail}]')
        second_request.accountCookie.append(ac2dm_token)
        second_data = second_request.SerializeToString()
        verbose_post('https://android.clients.google.com/checkin',
                     data=second_data, headers=headers)
        LOGGER.info(f'Successfully checked in, got Android id {android_id}')
        return android_id
예제 #4
0
    def _authorize(self, auth_string):
        """Authorizes a login to Google Play.

        Parameters
        ----------
        auth_string : str
            The authorization string as issued by Google Play.
        """
        params, headers = self._login_parameters(auth_string)
        params['app'] = headers['app'] = 'com.android.vending'
        params['service'] = 'androidmarket'
        response = verbose_post('https://android.clients.google.com/auth', data=params, headers=headers)
        master_token = get_token(response, 'token')
        params['Token'] = master_token
        params['check_email'] = '1'
        params['token_request_options'] = 'CAA4AQ=='
        params['system_partition'] = '1'
        params['_opt_is_called_from_account_manager'] = '1'
        params.pop('Email')
        params.pop('EncryptedPasswd')
        response = verbose_post('https://android.clients.google.com/auth', data=params, headers=headers)
        second_token = get_token(response, 'auth')
        self.auth_token = second_token
        LOGGER.info('Successfully authorized the device with Google Play')
예제 #5
0
    def _retrieve_ac2dm_token(self, auth_string):
        """Retrieves an ac2dm token, part of the login procedure.
            Should never be called on its own.

        Parameters
        ----------
        auth_string : str
            An authentication string derived from Google Play credentials.

        Returns
        -------
        str
            The retrieved token.
        """
        LOGGER.info(f'Retrieving ac2dm-Token with authentication string {auth_string}')
        login_parameters, login_headers = self._login_parameters(auth_string)
        login_headers['app'] = 'com.google.android.gms'
        response = verbose_post('https://android.clients.google.com/auth',
                                data=login_parameters, headers=login_headers)
        ac2dm_token = get_token(response, 'auth')
        return ac2dm_token