mirror of
https://github.com/FliegendeWurst/googleplay-api.git
synced 2024-11-22 12:54:58 +00:00
Improved file delivery + minor changes
* Updated user agent string with data taken from play-store-api * *download* and *delivery* functions will now return a python generator rather than raw bytes, to prevent app loading entire files in memory. This generator can be iterated to get chunk of bytes to write, as discussed in issue #35. * as a consequence of the previous point, there is no more progress bar feature for downloading. It should be implemented by developers using the API.
This commit is contained in:
parent
e1c73c8af0
commit
23937e6cb8
@ -77,12 +77,21 @@ class DeviceBuilder(object):
|
|||||||
",device={device}"
|
",device={device}"
|
||||||
",hardware={hardware}"
|
",hardware={hardware}"
|
||||||
",product={product}"
|
",product={product}"
|
||||||
"").format(versionString=version_string,
|
",platformVersionRelease={platform_v}"
|
||||||
|
",model={model}"
|
||||||
|
",buildId={build_id}"
|
||||||
|
",isWideScreen=0"
|
||||||
|
",supportedAbis={supported_abis}"
|
||||||
|
")").format(versionString=version_string,
|
||||||
versionCode=self.device.get('vending.version'),
|
versionCode=self.device.get('vending.version'),
|
||||||
sdk=self.device.get('build.version.sdk_int'),
|
sdk=self.device.get('build.version.sdk_int'),
|
||||||
device=self.device.get('build.device'),
|
device=self.device.get('build.device'),
|
||||||
hardware=self.device.get('build.hardware'),
|
hardware=self.device.get('build.hardware'),
|
||||||
product=self.device.get('build.product'))
|
product=self.device.get('build.product'),
|
||||||
|
platform_v=self.device.get('build.version.release'),
|
||||||
|
model=self.device.get('build.model'),
|
||||||
|
build_id=self.device.get('build.id'),
|
||||||
|
supported_abis=self.device.get('platforms'))
|
||||||
|
|
||||||
def getAuthParams(self, email, passwd):
|
def getAuthParams(self, email, passwd):
|
||||||
return {"Email": email,
|
return {"Email": email,
|
||||||
|
@ -5,7 +5,6 @@ from Crypto.Util import asn1
|
|||||||
from Crypto.PublicKey import RSA
|
from Crypto.PublicKey import RSA
|
||||||
from Crypto.Hash import SHA
|
from Crypto.Hash import SHA
|
||||||
from Crypto.Cipher import PKCS1_OAEP
|
from Crypto.Cipher import PKCS1_OAEP
|
||||||
from clint.textui import progress
|
|
||||||
|
|
||||||
import requests
|
import requests
|
||||||
from base64 import b64decode, urlsafe_b64encode
|
from base64 import b64decode, urlsafe_b64encode
|
||||||
@ -478,30 +477,16 @@ class GooglePlayAPI(object):
|
|||||||
output.append(review)
|
output.append(review)
|
||||||
return output
|
return output
|
||||||
|
|
||||||
def _deliver_data(self, url, cookies, progress_bar):
|
def _deliver_data(self, url, cookies):
|
||||||
headers = self.getDefaultHeaders()
|
headers = self.getDefaultHeaders()
|
||||||
if not progress_bar:
|
|
||||||
return requests.get(url, headers=headers,
|
|
||||||
cookies=cookies, verify=ssl_verify,
|
|
||||||
stream=True,
|
|
||||||
timeout=60,
|
|
||||||
proxies=self.proxies_config).content
|
|
||||||
response_content = bytes()
|
|
||||||
response = requests.get(url, headers=headers,
|
response = requests.get(url, headers=headers,
|
||||||
cookies=cookies, verify=ssl_verify,
|
cookies=cookies, verify=ssl_verify,
|
||||||
stream=True, timeout=60,
|
stream=True, timeout=60,
|
||||||
proxies=self.proxies_config)
|
proxies=self.proxies_config)
|
||||||
total_length = int(response.headers.get('content-length'))
|
return response.iter_content(chunk_size=(32 * 1 << 10))
|
||||||
chunk_size = 32 * (1 << 10) # 32 KB
|
|
||||||
bar = progress.Bar(expected_size=(total_length >> 10))
|
|
||||||
for index, chunk in enumerate(response.iter_content(chunk_size=chunk_size)):
|
|
||||||
response_content += chunk
|
|
||||||
bar.show(index * chunk_size >> 10)
|
|
||||||
bar.done()
|
|
||||||
return response_content
|
|
||||||
|
|
||||||
def delivery(self, packageName, versionCode=None, offerType=1,
|
def delivery(self, packageName, versionCode=None, offerType=1,
|
||||||
downloadToken=None, progress_bar=False, expansion_files=False):
|
downloadToken=None, expansion_files=False):
|
||||||
"""Download an already purchased app.
|
"""Download an already purchased app.
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
@ -553,7 +538,7 @@ class GooglePlayAPI(object):
|
|||||||
cookies = {
|
cookies = {
|
||||||
str(cookie.name): str(cookie.value)
|
str(cookie.name): str(cookie.value)
|
||||||
}
|
}
|
||||||
result['data'] = self._deliver_data(downloadUrl, cookies, progress_bar)
|
result['data'] = self._deliver_data(downloadUrl, cookies)
|
||||||
if not expansion_files:
|
if not expansion_files:
|
||||||
return result
|
return result
|
||||||
for obb in resObj.payload.deliveryResponse.appDeliveryData.additionalFile:
|
for obb in resObj.payload.deliveryResponse.appDeliveryData.additionalFile:
|
||||||
@ -566,12 +551,11 @@ class GooglePlayAPI(object):
|
|||||||
obbType = 'patch'
|
obbType = 'patch'
|
||||||
a['type'] = obbType
|
a['type'] = obbType
|
||||||
a['versionCode'] = obb.versionCode
|
a['versionCode'] = obb.versionCode
|
||||||
a['data'] = self._deliver_data(obb.downloadUrl, None, progress_bar)
|
a['data'] = self._deliver_data(obb.downloadUrl, None)
|
||||||
result['additionalData'].append(a)
|
result['additionalData'].append(a)
|
||||||
return result
|
return result
|
||||||
|
|
||||||
def download(self, packageName, versionCode=None, offerType=1,
|
def download(self, packageName, versionCode=None, offerType=1, expansion_files=False):
|
||||||
progress_bar=False, expansion_files=False):
|
|
||||||
"""Download an app and return its raw data (APK file). Free apps need
|
"""Download an app and return its raw data (APK file). Free apps need
|
||||||
to be "purchased" first, in order to retrieve the download cookie.
|
to be "purchased" first, in order to retrieve the download cookie.
|
||||||
If you want to download an already purchased app, use *delivery* method.
|
If you want to download an already purchased app, use *delivery* method.
|
||||||
@ -612,7 +596,7 @@ class GooglePlayAPI(object):
|
|||||||
else:
|
else:
|
||||||
dlToken = resObj.payload.buyResponse.downloadToken
|
dlToken = resObj.payload.buyResponse.downloadToken
|
||||||
return self.delivery(packageName, versionCode, offerType, dlToken,
|
return self.delivery(packageName, versionCode, offerType, dlToken,
|
||||||
progress_bar=progress_bar, expansion_files=expansion_files)
|
expansion_files=expansion_files)
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def getDevicesCodenames():
|
def getDevicesCodenames():
|
||||||
|
1
setup.py
1
setup.py
@ -11,5 +11,4 @@ setup(name='gpapi',
|
|||||||
package_data={'gpapi': ['device.properties']},
|
package_data={'gpapi': ['device.properties']},
|
||||||
install_requires=['pycryptodome',
|
install_requires=['pycryptodome',
|
||||||
'protobuf',
|
'protobuf',
|
||||||
'clint',
|
|
||||||
'requests'])
|
'requests'])
|
||||||
|
12
test.py
12
test.py
@ -37,9 +37,10 @@ for a in apps:
|
|||||||
docid = apps[0]['docId']
|
docid = apps[0]['docId']
|
||||||
print('\nTelegram docid is: %s\n' % docid)
|
print('\nTelegram docid is: %s\n' % docid)
|
||||||
print('\nAttempting to download %s\n' % docid)
|
print('\nAttempting to download %s\n' % docid)
|
||||||
fl = server.download(docid, None, progress_bar=True)
|
fl = server.delivery(docid, versionCode=None)
|
||||||
with open(docid + '.apk', 'wb') as f:
|
with open(docid + '.apk', 'wb') as apk_file:
|
||||||
f.write(fl['data'])
|
for chunk in fl.get('data'):
|
||||||
|
apk_file.write(chunk)
|
||||||
print('\nDownload successful\n')
|
print('\nDownload successful\n')
|
||||||
|
|
||||||
# DOWNLOAD APP NOT PURCHASED
|
# DOWNLOAD APP NOT PURCHASED
|
||||||
@ -52,10 +53,7 @@ try:
|
|||||||
app = server.search('nova launcher prime', 3, None)
|
app = server.search('nova launcher prime', 3, None)
|
||||||
app = filter(lambda x: x['docId'] == 'com.teslacoilsw.launcher.prime', app)
|
app = filter(lambda x: x['docId'] == 'com.teslacoilsw.launcher.prime', app)
|
||||||
app = list(app)[0]
|
app = list(app)[0]
|
||||||
fl = server.delivery(app['docId'], app['versionCode'], progress_bar=True)
|
fl = server.delivery(app['docId'], app['versionCode'])
|
||||||
with open(docid + '.apk', 'wb') as f:
|
|
||||||
f.write(fl['data'])
|
|
||||||
print('\nDownload successful\n')
|
|
||||||
except RequestError as e:
|
except RequestError as e:
|
||||||
errorThrown = True
|
errorThrown = True
|
||||||
print(e)
|
print(e)
|
||||||
|
Loading…
Reference in New Issue
Block a user