Skip to content

Commit

Permalink
Fix #16
Browse files Browse the repository at this point in the history
Signed-off-by: Domenico Iezzi <[email protected]>
  • Loading branch information
Domenico Iezzi committed Oct 13, 2017
1 parent 2ab7ce0 commit 9d0d144
Show file tree
Hide file tree
Showing 2 changed files with 105 additions and 106 deletions.
192 changes: 94 additions & 98 deletions gpapi/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,20 +19,14 @@
# 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 = os.path.join(os.path.dirname(os.path.realpath(__file__)),
'device.properties')

if VERSION == 2:
config = ConfigParser.ConfigParser()
else:
config = configparser.ConfigParser()

filepath = os.path.join(os.path.dirname(os.path.realpath(__file__)),
'device.properties')
config.read(filepath)
device = {}
# initialize device, because we need to setup UserAgent
# before the end of login method. If the login defines a different
# device, it won't cause conflicts
for (key, value) in config.items('angler'):
device[key] = value


def getDevicesCodenames():
Expand All @@ -50,92 +44,94 @@ def getDevicesReadableNames():
return output


def getUserAgent():
return ("Android-Finsky/8.1.72.S-all [6] [PR] 165478484 ("
"api=3"
",versionCode={versionCode}"
",sdk={sdk}"
",device={device}"
",hardware={hardware}"
",product={product}").format(versionCode=device['vending.version'],
sdk=device['build.version.sdk_int'],
device=device['build.device'],
hardware=device['build.hardware'],
product=device['build.product'])


def getDeviceConfig():
libList = device['sharedlibraries'].split(",")
featureList = device['features'].split(",")
localeList = device['locales'].split(",")
glList = device['gl.extensions'].split(",")
platforms = device['platforms'].split(",")

hasFiveWayNavigation = (device['hasfivewaynavigation'] == 'true')
hasHardKeyboard = (device['hashardkeyboard'] == 'true')
deviceConfig = googleplay_pb2.DeviceConfigurationProto()
deviceConfig.touchScreen = int(device['touchscreen'])
deviceConfig.keyboard = int(device['keyboard'])
deviceConfig.navigation = int(device['navigation'])
deviceConfig.screenLayout = int(device['screenlayout'])
deviceConfig.hasHardKeyboard = hasHardKeyboard
deviceConfig.hasFiveWayNavigation = hasFiveWayNavigation
deviceConfig.screenDensity = int(device['screen.density'])
deviceConfig.screenWidth = int(device['screen.width'])
deviceConfig.screenHeight = int(device['screen.height'])
deviceConfig.glEsVersion = int(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():
androidBuild = googleplay_pb2.AndroidBuildProto()
androidBuild.id = device['build.fingerprint']
androidBuild.product = device['build.hardware']
androidBuild.carrier = device['build.brand']
androidBuild.radio = device['build.radio']
androidBuild.bootloader = device['build.bootloader']
androidBuild.device = device['build.device']
androidBuild.sdkVersion = int(device['build.version.sdk_int'])
androidBuild.model = device['build.model']
androidBuild.manufacturer = device['build.manufacturer']
androidBuild.buildProduct = device['build.product']
androidBuild.client = device['client']
androidBuild.otaInstalled = False
androidBuild.timestamp = int(time.time())
androidBuild.googleServices = int(device['gsf.version'])
return androidBuild


def getAndroidCheckin():
androidCheckin = googleplay_pb2.AndroidCheckinProto()
androidCheckin.build.CopyFrom(getAndroidBuild())
androidCheckin.lastCheckinMsec = 0
androidCheckin.cellOperator = device['celloperator']
androidCheckin.simOperator = device['simoperator']
androidCheckin.roaming = device['roaming']
androidCheckin.userNumber = 0
return androidCheckin


def getAndroidCheckinRequest(device_codename):
for (key, value) in config.items(device_codename):
device[key] = value
request = googleplay_pb2.AndroidCheckinRequest()
request.id = 0
request.checkin.CopyFrom(getAndroidCheckin())
request.locale = LANG
request.timeZone = TIMEZONE
request.version = 3
request.deviceConfiguration.CopyFrom(getDeviceConfig())
request.fragment = 0
return request
class DeviceBuilder(object):

def __init__(self, device):
self.device = {}
for (key, value) in config.items(device):
self.device[key] = value

def getUserAgent(self):
return ("Android-Finsky/8.1.72.S-all [6] [PR] 165478484 ("
"api=3"
",versionCode={versionCode}"
",sdk={sdk}"
",device={device}"
",hardware={hardware}"
",product={product}"
"").format(versionCode=self.device['vending.version'],
sdk=self.device['build.version.sdk_int'],
device=self.device['build.device'],
hardware=self.device['build.hardware'],
product=self.device['build.product'])

def getAndroidCheckinRequest(self):
request = googleplay_pb2.AndroidCheckinRequest()
request.id = 0
request.checkin.CopyFrom(self.getAndroidCheckin())
request.locale = LANG
request.timeZone = 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.time())
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
19 changes: 11 additions & 8 deletions gpapi/googleplay.py
Original file line number Diff line number Diff line change
Expand Up @@ -46,11 +46,12 @@ class GooglePlayAPI(object):
AUTHURL = BASE + "auth"
ACCOUNT = "HOSTED_OR_GOOGLE"

def __init__(self, debug=False):
def __init__(self, debug=False, device_codename='bacon'):
self.authSubToken = None
self.gsfId = None
self.lang = config.LANG
self.debug = debug
self.deviceBuilder = config.DeviceBuilder(device_codename)

def encrypt_password(self, login, passwd):
"""Encrypt the password using the google publickey, using
Expand Down Expand Up @@ -87,19 +88,19 @@ def getDefaultHeaders(self):
headers = {
"Accept-Language": config.LANG.replace('_', '-'),
"X-DFE-Encoded-Targets": config.DFE_TARGETS,
"User-Agent": config.getUserAgent()
"User-Agent": self.deviceBuilder.getUserAgent()
}
if self.gsfId is not None:
headers["X-DFE-Device-Id"] = "{0:x}".format(self.gsfId)
if self.authSubToken is not None:
headers["Authorization"] = "GoogleLogin auth=%s" % self.authSubToken
return headers

def checkin(self, email, ac2dmToken, device_codename):
def checkin(self, email, ac2dmToken):
headers = self.getDefaultHeaders()
headers["Content-Type"] = "application/x-protobuffer"

request = config.getAndroidCheckinRequest(device_codename)
request = self.deviceBuilder.getAndroidCheckinRequest()

stringRequest = request.SerializeToString()
res = requests.post(self.CHECKINURL, data=stringRequest,
Expand All @@ -125,7 +126,7 @@ def uploadDeviceConfig(self):
*device.properties* to the google account. Default device is a Google Nexus 6P"""

upload = googleplay_pb2.UploadDeviceConfigRequest()
upload.deviceConfiguration.CopyFrom(config.getDeviceConfig())
upload.deviceConfiguration.CopyFrom(self.deviceBuilder.getDeviceConfig())
headers = self.getDefaultHeaders()
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"
Expand All @@ -137,8 +138,7 @@ def uploadDeviceConfig(self):
headers=headers, verify=ssl_verify)
googleplay_pb2.ResponseWrapper.FromString(res.content)

def login(self, email=None, password=None, gsfId=None,
authSubToken=None, device_codename='bacon'):
def login(self, email=None, password=None, gsfId=None, authSubToken=None):
"""Login to your Google Account.
For first time login you should provide:
* email
Expand Down Expand Up @@ -185,7 +185,7 @@ def login(self, email=None, password=None, gsfId=None,
else:
raise LoginError("Auth token not found.")

self.gsfId = self.checkin(email, ac2dmToken, device_codename)
self.gsfId = self.checkin(email, ac2dmToken)
if self.debug:
print("Google Services Framework Id: %s" % "{0:x}".format(self.gsfId))
self.getAuthSubToken(email, encryptedPass)
Expand Down Expand Up @@ -496,6 +496,9 @@ def download(self, packageName, versionCode,
return self.delivery(packageName, versionCode,
offerType, dlToken, progress_bar=progress_bar)

def changeDevice(self, device_codename):
self.deviceBuilder = config.DeviceBuilder(device_codename)

@staticmethod
def getDevicesCodenames():
return config.getDevicesCodenames()
Expand Down

0 comments on commit 9d0d144

Please sign in to comment.