googleplay-api/gpapi/config.py
Domenico Iezzi 24a3e1a09b
Changed Locale and TimeZone initialization
Before, if locale wasn't specified as a parameter, it was picked from
the system running gpapi. Similar thing happened for timezone, but its
value was hardcoded in config.py.
To avoid problems related to missing or unavailable apps, this commit
enforces users to provide a locale and a timezone value. Without them,
gpapi can't be initialized.
2018-01-25 11:36:25 +01:00

182 lines
8.1 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}"
"").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'))
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