2017-09-18 14:33:11 +00:00
|
|
|
import struct
|
2017-10-04 11:42:52 +00:00
|
|
|
import sys
|
2018-12-12 16:23:07 +00:00
|
|
|
from google.protobuf.message import Message
|
2017-12-09 09:06:34 +00:00
|
|
|
from . import googleplay_pb2
|
2017-10-04 11:42:52 +00:00
|
|
|
|
|
|
|
VERSION = sys.version_info[0]
|
2017-09-18 14:33:11 +00:00
|
|
|
|
2018-12-12 16:23:07 +00:00
|
|
|
def isIterable(obj):
|
|
|
|
try:
|
|
|
|
iter(obj)
|
|
|
|
return True
|
|
|
|
except TypeError:
|
|
|
|
return False
|
2017-09-18 14:33:11 +00:00
|
|
|
|
2018-12-12 16:23:07 +00:00
|
|
|
def isProtobuf(obj):
|
|
|
|
"""Really bad workaround to check if an object is an
|
|
|
|
instance of a protobuf message"""
|
|
|
|
return hasattr(obj, "MergeFrom")
|
|
|
|
|
|
|
|
def parseProtobufObj(obj):
|
|
|
|
output = {}
|
|
|
|
for (fd, value) in obj.ListFields():
|
|
|
|
key = fd.name
|
|
|
|
if isProtobuf(value):
|
|
|
|
if not isIterable(value):
|
|
|
|
output.update({key: parseProtobufObj(value)})
|
|
|
|
else:
|
|
|
|
output.update({
|
|
|
|
key: [parseProtobufObj(i) for i in value]
|
|
|
|
})
|
|
|
|
else:
|
|
|
|
output.update({key: value})
|
|
|
|
return output
|
2017-10-10 16:35:40 +00:00
|
|
|
|
2017-09-18 14:33:11 +00:00
|
|
|
def readInt(byteArray, start):
|
|
|
|
"""Read the byte array, starting from *start* position,
|
|
|
|
as an 32-bit unsigned integer"""
|
|
|
|
return struct.unpack("!L", byteArray[start:][0:4])[0]
|
|
|
|
|
|
|
|
|
|
|
|
def toBigInt(byteArray):
|
|
|
|
"""Convert the byte array to a BigInteger"""
|
2017-10-10 16:35:40 +00:00
|
|
|
array = byteArray[::-1] # reverse array
|
2017-09-18 14:33:11 +00:00
|
|
|
out = 0
|
|
|
|
for key, value in enumerate(array):
|
2017-10-04 11:42:52 +00:00
|
|
|
if VERSION == 3:
|
|
|
|
decoded = struct.unpack("B", bytes([value]))[0]
|
|
|
|
else:
|
|
|
|
decoded = struct.unpack("B", value)[0]
|
2017-10-10 16:35:40 +00:00
|
|
|
out = out | decoded << key * 8
|
2017-09-18 14:33:11 +00:00
|
|
|
return out
|
2017-12-09 09:06:34 +00:00
|
|
|
|
2017-12-09 09:58:00 +00:00
|
|
|
def hasPrefetch(obj):
|
2017-12-09 09:06:34 +00:00
|
|
|
try:
|
2017-12-09 09:58:00 +00:00
|
|
|
return len(obj.preFetch) > 0
|
2017-12-09 09:06:34 +00:00
|
|
|
except ValueError:
|
|
|
|
return False
|
|
|
|
|
2017-12-09 09:58:00 +00:00
|
|
|
def hasListResponse(obj):
|
2017-12-09 09:06:34 +00:00
|
|
|
try:
|
2017-12-09 09:58:00 +00:00
|
|
|
return obj.HasField('listResponse')
|
2017-12-09 09:06:34 +00:00
|
|
|
except ValueError:
|
|
|
|
return False
|
|
|
|
|
2017-12-09 09:58:00 +00:00
|
|
|
def hasSearchResponse(obj):
|
2017-12-09 09:06:34 +00:00
|
|
|
try:
|
2017-12-09 09:58:00 +00:00
|
|
|
return obj.HasField('searchResponse')
|
2017-12-09 09:06:34 +00:00
|
|
|
except ValueError:
|
|
|
|
return False
|
2017-12-09 09:58:00 +00:00
|
|
|
|
2018-12-12 16:23:07 +00:00
|
|
|
def hasCluster(obj):
|
|
|
|
try:
|
|
|
|
return obj.HasField('cluster')
|
|
|
|
except ValueError:
|
|
|
|
return False
|
|
|
|
|
|
|
|
def hasTosContent(tocResponse):
|
|
|
|
try:
|
|
|
|
return tocResponse.HasField('tosContent')
|
|
|
|
except ValueError:
|
|
|
|
return False
|
|
|
|
|
|
|
|
def hasTosToken(tocResponse):
|
|
|
|
try:
|
|
|
|
return tocResponse.HasField('tosToken')
|
|
|
|
except ValueError:
|
|
|
|
return False
|
|
|
|
|
|
|
|
def hasCookie(tocResponse):
|
|
|
|
try:
|
|
|
|
return tocResponse.HasField('cookie')
|
|
|
|
except ValueError:
|
|
|
|
return False
|
|
|
|
|
2017-12-09 09:58:00 +00:00
|
|
|
def hasDoc(obj):
|
|
|
|
# doc an be a single object or a
|
|
|
|
# RepeatedComposite object
|
|
|
|
try:
|
|
|
|
existance = obj.HasField('doc')
|
|
|
|
except ValueError:
|
|
|
|
try:
|
|
|
|
existance = len(obj.doc) > 0
|
|
|
|
except TypeError:
|
|
|
|
existance = False
|
|
|
|
|
2018-03-18 20:18:47 +00:00
|
|
|
return existance
|