mirror of
https://github.com/FliegendeWurst/googleplay-api.git
synced 2024-10-18 06:50:45 +00:00
23937e6cb8
* 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.
191 lines
8.6 KiB
Python
191 lines
8.6 KiB
Python
from . import googleplay_pb2
|
|
from time import time
|
|
from os import path
|
|
from sys import version_info
|
|
from re import match
|
|
|
|
VERSION = version_info[0]
|
|
if VERSION == 2:
|
|
import ConfigParser
|
|
else:
|
|
import configparser
|
|
|
|
|
|
DFE_TARGETS = "CAEScFfqlIEG6gUYogFWrAISK1WDAg+hAZoCDgIU1gYEOIACFkLMAeQBnASLATlASUuyAyqCAjY5igOMBQzfA/IClwFbApUC4ANbtgKVAS7OAX8YswHFBhgDwAOPAmGEBt4OfKkB5weSB5AFASkiN68akgMaxAMSAQEBA9kBO7UBFE1KVwIDBGs3go6BBgEBAgMECQgJAQIEAQMEAQMBBQEBBAUEFQYCBgUEAwMBDwIBAgOrARwBEwMEAg0mrwESfTEcAQEKG4EBMxghChMBDwYGASI3hAEODEwXCVh/EREZA4sBYwEdFAgIIwkQcGQRDzQ2fTC2AjfVAQIBAYoBGRg2FhYFBwEqNzACJShzFFblAo0CFxpFNBzaAd0DHjIRI4sBJZcBPdwBCQGhAUd2A7kBLBVPngEECHl0UEUMtQETigHMAgUFCc0BBUUlTywdHDgBiAJ+vgKhAU0uAcYCAWQ/5ALUAw1UwQHUBpIBCdQDhgL4AY4CBQICjARbGFBGWzA1CAEMOQH+BRAOCAZywAIDyQZ2MgM3BxsoAgUEBwcHFia3AgcGTBwHBYwBAlcBggFxSGgIrAEEBw4QEqUCASsWadsHCgUCBQMD7QICA3tXCUw7ugJZAwGyAUwpIwM5AwkDBQMJA5sBCw8BNxBVVBwVKhebARkBAwsQEAgEAhESAgQJEBCZATMdzgEBBwG8AQQYKSMUkAEDAwY/CTs4/wEaAUt1AwEDAQUBAgIEAwYEDx1dB2wGeBFgTQ"
|
|
GOOGLE_PUBKEY = "AAAAgMom/1a/v0lblO2Ubrt60J2gcuXSljGFQXgcyZWveWLEwo6prwgi3iJIZdodyhKZQrNWp5nKJ3srRXcUW+F1BD3baEVGcmEgqaLZUNBjm057pKRI16kB0YppeGx5qIQ5QjKzsR8ETQbKLNWgRY0QRNVz34kMJR3P/LgHax/6rmf5AAAAAwEAAQ=="
|
|
ACCOUNT = "HOSTED_OR_GOOGLE"
|
|
|
|
# parse phone config from the file 'device.properties'.
|
|
# if you want to add another phone, just create another section in
|
|
# the file. Some configurations for common phones can be found here:
|
|
# https://github.com/yeriomin/play-store-api/tree/master/src/main/resources
|
|
filepath = path.join(path.dirname(path.realpath(__file__)),
|
|
'device.properties')
|
|
|
|
if VERSION == 2:
|
|
config = ConfigParser.ConfigParser()
|
|
else:
|
|
config = configparser.ConfigParser()
|
|
config.read(filepath)
|
|
|
|
|
|
def getDevicesCodenames():
|
|
"""Returns a list containing devices codenames"""
|
|
return config.sections()
|
|
|
|
|
|
def getDevicesReadableNames():
|
|
"""Returns codename and readable name for each device"""
|
|
return [{'codename': s,
|
|
'readableName': config.get(s).get('userreadablename')}
|
|
for s in getDevicesCodenames()]
|
|
|
|
|
|
class DeviceBuilder(object):
|
|
|
|
def __init__(self, device):
|
|
self.device = {}
|
|
for (key, value) in config.items(device):
|
|
self.device[key] = value
|
|
|
|
def setLocale(self, locale):
|
|
# test if provided locale is valid
|
|
if locale is None or type(locale) is not str:
|
|
raise Exception('Wrong locale supplied')
|
|
|
|
# check if locale matches the structure of a common
|
|
# value like "en_US"
|
|
if match(r'[a-z]{2}\_[A-Z]{2}', locale) is None:
|
|
raise Exception('Wrong locale supplied')
|
|
self.locale = locale
|
|
|
|
def set_timezone(self, timezone):
|
|
if timezone is None or type(timezone) is not str:
|
|
timezone = self.device.get('timezone')
|
|
if timezone is None:
|
|
raise Exception('Wrong timezone supplied')
|
|
self.timezone = timezone
|
|
|
|
def getUserAgent(self):
|
|
version_string = self.device.get('vending.versionstring')
|
|
if version_string is None:
|
|
version_string = '8.4.19.V-all [0] [FP] 175058788'
|
|
return ("Android-Finsky/{versionString} ("
|
|
"api=3"
|
|
",versionCode={versionCode}"
|
|
",sdk={sdk}"
|
|
",device={device}"
|
|
",hardware={hardware}"
|
|
",product={product}"
|
|
",platformVersionRelease={platform_v}"
|
|
",model={model}"
|
|
",buildId={build_id}"
|
|
",isWideScreen=0"
|
|
",supportedAbis={supported_abis}"
|
|
")").format(versionString=version_string,
|
|
versionCode=self.device.get('vending.version'),
|
|
sdk=self.device.get('build.version.sdk_int'),
|
|
device=self.device.get('build.device'),
|
|
hardware=self.device.get('build.hardware'),
|
|
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):
|
|
return {"Email": email,
|
|
"EncryptedPasswd": passwd,
|
|
"accountType": ACCOUNT,
|
|
"has_permission": "1",
|
|
"source": "android",
|
|
"device_country": self.locale[0:2],
|
|
"service": "androidmarket",
|
|
"app": "com.android.vending",
|
|
"lang": self.locale,
|
|
"sdk_version": self.device['build.version.sdk_int']}
|
|
|
|
def getLoginParams(self, email, encryptedPass):
|
|
return {"Email": email,
|
|
"EncryptedPasswd": encryptedPass,
|
|
"service": "ac2dm",
|
|
"add_account": "1",
|
|
"accountType": ACCOUNT,
|
|
"has_permission": "1",
|
|
"app": "com.google.android.gsf",
|
|
"source": "android",
|
|
"device_country": self.locale[0:2],
|
|
"lang": self.locale,
|
|
"sdk_version": self.device['build.version.sdk_int']}
|
|
|
|
def getAndroidCheckinRequest(self):
|
|
request = googleplay_pb2.AndroidCheckinRequest()
|
|
request.id = 0
|
|
request.checkin.CopyFrom(self.getAndroidCheckin())
|
|
request.locale = self.locale
|
|
request.timeZone = self.timezone
|
|
request.version = 3
|
|
request.deviceConfiguration.CopyFrom(self.getDeviceConfig())
|
|
request.fragment = 0
|
|
return request
|
|
|
|
def getDeviceConfig(self):
|
|
libList = self.device['sharedlibraries'].split(",")
|
|
featureList = self.device['features'].split(",")
|
|
localeList = self.device['locales'].split(",")
|
|
glList = self.device['gl.extensions'].split(",")
|
|
platforms = self.device['platforms'].split(",")
|
|
|
|
hasFiveWayNavigation = (self.device['hasfivewaynavigation'] == 'true')
|
|
hasHardKeyboard = (self.device['hashardkeyboard'] == 'true')
|
|
deviceConfig = googleplay_pb2.DeviceConfigurationProto()
|
|
deviceConfig.touchScreen = int(self.device['touchscreen'])
|
|
deviceConfig.keyboard = int(self.device['keyboard'])
|
|
deviceConfig.navigation = int(self.device['navigation'])
|
|
deviceConfig.screenLayout = int(self.device['screenlayout'])
|
|
deviceConfig.hasHardKeyboard = hasHardKeyboard
|
|
deviceConfig.hasFiveWayNavigation = hasFiveWayNavigation
|
|
deviceConfig.screenDensity = int(self.device['screen.density'])
|
|
deviceConfig.screenWidth = int(self.device['screen.width'])
|
|
deviceConfig.screenHeight = int(self.device['screen.height'])
|
|
deviceConfig.glEsVersion = int(self.device['gl.version'])
|
|
for x in platforms:
|
|
deviceConfig.nativePlatform.append(x)
|
|
for x in libList:
|
|
deviceConfig.systemSharedLibrary.append(x)
|
|
for x in featureList:
|
|
deviceConfig.systemAvailableFeature.append(x)
|
|
for x in localeList:
|
|
deviceConfig.systemSupportedLocale.append(x)
|
|
for x in glList:
|
|
deviceConfig.glExtension.append(x)
|
|
return deviceConfig
|
|
|
|
def getAndroidBuild(self):
|
|
androidBuild = googleplay_pb2.AndroidBuildProto()
|
|
androidBuild.id = self.device['build.fingerprint']
|
|
androidBuild.product = self.device['build.hardware']
|
|
androidBuild.carrier = self.device['build.brand']
|
|
androidBuild.radio = self.device['build.radio']
|
|
androidBuild.bootloader = self.device['build.bootloader']
|
|
androidBuild.device = self.device['build.device']
|
|
androidBuild.sdkVersion = int(self.device['build.version.sdk_int'])
|
|
androidBuild.model = self.device['build.model']
|
|
androidBuild.manufacturer = self.device['build.manufacturer']
|
|
androidBuild.buildProduct = self.device['build.product']
|
|
androidBuild.client = self.device['client']
|
|
androidBuild.otaInstalled = False
|
|
androidBuild.timestamp = int(time()/1000)
|
|
androidBuild.googleServices = int(self.device['gsf.version'])
|
|
return androidBuild
|
|
|
|
def getAndroidCheckin(self):
|
|
androidCheckin = googleplay_pb2.AndroidCheckinProto()
|
|
androidCheckin.build.CopyFrom(self.getAndroidBuild())
|
|
androidCheckin.lastCheckinMsec = 0
|
|
androidCheckin.cellOperator = self.device['celloperator']
|
|
androidCheckin.simOperator = self.device['simoperator']
|
|
androidCheckin.roaming = self.device['roaming']
|
|
androidCheckin.userNumber = 0
|
|
return androidCheckin
|