def _build_main_request(self, subrequests, player_position=None): self.log.debug('Generating main RPC request...') request = RequestEnvelope() request.status_code = 2 request.request_id = self.get_rpc_id() if player_position is not None: request.latitude, request.longitude, request.altitude = player_position request.altitude = 8 # not as suspicious as 0 """ generate sub requests before signature generation """ request = self._build_sub_requests(request, subrequests) ticket = self._auth_provider.get_ticket() if ticket: self.log.debug('Found Session Ticket - using this instead of oauth token') request.auth_ticket.expire_timestamp_ms, request.auth_ticket.start, request.auth_ticket.end = ticket ticket_serialized = request.auth_ticket.SerializeToString() else: self.log.debug('No Session Ticket found - using OAUTH Access Token') request.auth_info.provider = self._auth_provider.get_name() request.auth_info.token.contents = self._auth_provider.get_access_token() request.auth_info.token.unknown2 = 59 ticket_serialized = request.auth_info.SerializeToString() #Sig uses this when no auth_ticket available if self._signature_gen: if self._saved_signature is not None: sig = self._saved_signature else: sig = Signature() sig.location_hash1 = generateLocation1(ticket_serialized, request.latitude, request.longitude, request.altitude) sig.location_hash2 = generateLocation2(request.latitude, request.longitude, request.altitude) for req in request.requests: hash = generateRequestHash(ticket_serialized, req.SerializeToString()) sig.request_hash.append(hash) sig.session_hash = os.urandom(32) sig.timestamp = get_time(ms=True) sig.timestamp_since_start = get_time(ms=True) - RpcApi.START_TIME signature_proto = sig.SerializeToString() #u6 = request.unknown6.add() u6 = request.unknown6 u6.request_type = 6 u6.unknown2.encrypted_signature = self._generate_signature(signature_proto) # unknown stuff request.unknown12 = 989 self.log.debug('Generated protobuf request: \n\r%s', request) return request
def _build_main_request(self, subrequests, player_position=None): self.log.debug('Generating main RPC request...') request = RequestEnvelope() request.status_code = 2 request.request_id = self.get_rpc_id() request.accuracy = random.choice((5, 5, 5, 10, 10, 30, 50, 65)) if player_position: request.latitude, request.longitude, altitude = player_position # generate sub requests before SignalAgglomUpdates generation request = self._build_sub_requests(request, subrequests) ticket = self._auth_provider.get_ticket() if ticket: self.log.debug('Found Session Ticket - using this instead of oauth token') request.auth_ticket.expire_timestamp_ms, request.auth_ticket.start, request.auth_ticket.end = ticket ticket_serialized = request.auth_ticket.SerializeToString() else: self.log.debug('No Session Ticket found - using OAUTH Access Token') request.auth_info.provider = self._auth_provider.get_name() request.auth_info.token.contents = self._auth_provider.get_access_token() request.auth_info.token.unknown2 = 59 ticket_serialized = request.auth_info.SerializeToString() #Sig uses this when no auth_ticket available if self._signal_agglom_gen: sig = SignalAgglomUpdates() sig.location_hash_by_token_seed = generate_location_hash_by_seed(ticket_serialized, request.latitude, request.longitude, request.accuracy) sig.location_hash = generate_location_hash(request.latitude, request.longitude, request.accuracy) for req in request.requests: hash = generate_request_hash(ticket_serialized, req.SerializeToString()) sig.request_hashes.append(hash) sig.field22 = self.session_hash sig.epoch_timestamp_ms = get_time(ms=True) sig.timestamp_ms_since_start = get_time(ms=True) - RpcApi.START_TIME if self.device_info: for key in self.device_info: setattr(sig.device_info, key, self.device_info[key]) signal_agglom_proto = sig.SerializeToString() sig_request = SendEncryptedSignatureRequest() sig_request.encrypted_signature = self._generate_signature(signal_agglom_proto) plat = request.platform_requests.add() plat.type = 6 plat.request_message = sig_request.SerializeToString() request.ms_since_last_locationfix = 989 self.log.debug('Generated protobuf request: \n\r%s', request) return request
def _call(self): # Need fill in the location_fix location_fix = [Signature.LocationFix( provider='fused', timestamp_snapshot=(get_time(ms=True) - RpcApi.START_TIME) - random.randint(100, 300), latitude=self._position_lat, longitude=self._position_lng, horizontal_accuracy=round(random.uniform(50, 250), 7), altitude=self._position_alt, vertical_accuracy=random.randint(2, 5), provider_status=3, location_type=1 )] sensor_info = Signature.SensorInfo( timestamp_snapshot=(get_time(ms=True) - RpcApi.START_TIME) - random.randint(200, 400), magnetometer_x=random.uniform(-0.139084026217, 0.138112977147), magnetometer_y=random.uniform(-0.2, 0.19), magnetometer_z=random.uniform(-0.2, 0.4), angle_normalized_x=random.uniform(-47.149471283, 61.8397789001), angle_normalized_y=random.uniform(-47.149471283, 61.8397789001), angle_normalized_z=random.uniform(-47.149471283, 5), accel_raw_x=random.uniform(0.0729667818829, 0.0729667818829), accel_raw_y=random.uniform(-2.788630499244109, 3.0586791383810468), accel_raw_z=random.uniform(-0.34825887123552773, 0.19347580173737935), gyroscope_raw_x=random.uniform(-0.9703824520111084, 0.8556089401245117), gyroscope_raw_y=random.uniform(-1.7470258474349976, 1.4218578338623047), gyroscope_raw_z=random.uniform(-0.9681901931762695, 0.8396636843681335), accel_normalized_x=random.uniform(-0.31110161542892456, 0.1681540310382843), accel_normalized_y=random.uniform(-0.6574847102165222, -0.07290205359458923), accel_normalized_z=random.uniform(-0.9943905472755432, -0.7463029026985168), accelerometer_axes=3 ) device_info = Signature.DeviceInfo( device_id=ApiWrapper.DEVICE_ID, device_brand='Apple', device_model='iPhone', device_model_boot='iPhone8,2', hardware_manufacturer='Apple', hardware_model='N66AP', firmware_brand='iPhone OS', firmware_type='9.3.3' ) activity_status = Signature.ActivityStatus( # walking=True, # stationary=True, # automotive=True, # tilting=True ) signature = Signature( location_fix=location_fix, sensor_info=sensor_info, device_info=device_info, activity_status=activity_status, unknown25=-8537042734809897855 ) return PGoApiRequest.call(self, signature)
def _build_main_request(self, subrequests, player_position=None): self.log.debug('Generating main RPC request...') request = RequestEnvelope() request.status_code = 2 request.request_id = self.get_rpc_id() if player_position is not None: request.latitude, request.longitude, request.altitude = player_position request.altitude = 8 # not as suspicious as 0 """ generate sub requests before signature generation """ request = self._build_sub_requests(request, subrequests) ticket = self._auth_provider.get_ticket() if ticket: self.log.debug('Found Session Ticket - using this instead of oauth token') request.auth_ticket.expire_timestamp_ms, request.auth_ticket.start, request.auth_ticket.end = ticket if self._signature_gen: ticket_serialized = request.auth_ticket.SerializeToString() sig = Signature_pb2.Signature() sig.location_hash1 = generateLocation1(ticket_serialized, request.latitude, request.longitude, request.altitude) sig.location_hash2 = generateLocation2(request.latitude, request.longitude, request.altitude) for req in request.requests: hash = generateRequestHash(ticket_serialized, req.SerializeToString()) sig.request_hash.append(hash) sig.unk22 = os.urandom(32) sig.timestamp = get_time(ms=True) sig.timestamp_since_start = get_time(ms=True) - RpcApi.START_TIME signature_proto = sig.SerializeToString() u6 = request.unknown6.add() u6.request_type = 6 u6.unknown2.unknown1 = self._generate_signature(signature_proto) else: self.log.debug('No Session Ticket found - using OAUTH Access Token') request.auth_info.provider = self._auth_provider.get_name() request.auth_info.token.contents = self._auth_provider.get_access_token() request.auth_info.token.unknown2 = 59 # unknown stuff request.unknown12 = 989 self.log.debug('Generated protobuf request: \n\r%s', request) return request
def check_access_token(self): """ Add few seconds to now so the token get refreshed before it invalidates in the middle of the request """ now_s = get_time() + 120 if self._access_token is not None: if self._access_token_expiry == 0: self.log.debug( 'No Access Token Expiry found - assuming it is still valid!' ) return True elif self._access_token_expiry > now_s: h, m, s = get_format_time_diff(now_s, self._access_token_expiry, False) self.log.debug( 'Access Token still valid for further %02d:%02d:%02d hours (%s < %s)', h, m, s, now_s, self._access_token_expiry) return True else: self.log.info('Access Token expired!') return False else: self.log.debug('No Access Token available!') return False
def check_authentication(self, response_dict): if isinstance(response_dict, dict) and ('auth_ticket' in response_dict) and \ ('expire_timestamp_ms' in response_dict['auth_ticket']) and \ (self._auth_provider.is_new_ticket(response_dict['auth_ticket']['expire_timestamp_ms'])): had_ticket = self._auth_provider.has_ticket() auth_ticket = response_dict['auth_ticket'] self._auth_provider.set_ticket([ auth_ticket['expire_timestamp_ms'], base64.standard_b64decode(auth_ticket['start']), base64.standard_b64decode(auth_ticket['end']) ]) now_ms = get_time(ms=True) h, m, s = get_format_time_diff(now_ms, auth_ticket['expire_timestamp_ms'], True) if had_ticket: self.log.debug( 'Replacing old Session Ticket with new one valid for %02d:%02d:%02d hours (%s < %s)', h, m, s, now_ms, auth_ticket['expire_timestamp_ms']) else: self.log.debug( 'Received Session Ticket valid for %02d:%02d:%02d hours (%s < %s)', h, m, s, now_ms, auth_ticket['expire_timestamp_ms'])
def get_access_token(self, force_refresh=False): token_validity = self.check_access_token() if token_validity is True and force_refresh is False: self.log.debug('Using cached PTC Access Token') return self._access_token else: if force_refresh: self.log.info('Forced request of PTC Access Token!') else: self.log.info('Request PTC Access Token...') data = { 'client_id': 'mobile-app_pokemon-go', 'redirect_uri': 'https://www.nianticlabs.com/pokemongo/error', 'client_secret': self.PTC_LOGIN_CLIENT_SECRET, 'grant_type': 'refresh_token', 'code': self._refresh_token, } try: r = self._session.post(self.PTC_LOGIN_OAUTH, data=data, timeout=self.timeout) except Timeout: raise AuthTimeoutException('Auth POST timed out.') except RequestException as e: raise AuthException('Caught RequestException: {}'.format(e)) token_data = parse_qs(r.text) access_token = token_data.get('access_token') if access_token is not None: self._access_token = access_token[0] # set expiration to an hour less than value received because Pokemon OAuth # login servers return an access token with an explicit expiry time of # three hours, however, the token stops being valid after two hours. # See issue #86 expires = int(token_data.get('expires', [0])[0]) - 3600 if expires > 0: self._access_token_expiry = expires + get_time() else: self._access_token_expiry = 0 self._login = True self.log.info('PTC Access Token successfully retrieved.') self.log.debug('PTC Access Token: {}'.format( self._access_token)) else: self._access_token = None self._login = False if force_refresh: self.log.info( 'Reauthenticating with refresh token failed, using credentials instead.' ) return self.user_login(retry=False) raise AuthException("Could not retrieve a PTC Access Token")
def user_login(self, username=None, password=None, retry=True): self._username = username or self._username self._password = password or self._password if not isinstance(self._username, string_types) or not isinstance( self._password, string_types): raise InvalidCredentialsException( "Username/password not correctly specified") self.log.info('PTC User Login for: {}'.format(self._username)) self._session.cookies.clear() now = get_time() try: r = self._session.get(self.PTC_LOGIN_URL1, timeout=self.timeout) except Timeout: raise AuthTimeoutException('Auth GET timed out.') except RequestException as e: raise AuthException('Caught RequestException: {}'.format(e)) try: data = r.json() data.update({ '_eventId': 'submit', 'username': self._username, 'password': self._password, }) except (ValueError, AttributeError) as e: self.log.error( 'PTC User Login Error - invalid JSON response: {}'.format(e)) raise AuthException('Invalid JSON response: {}'.format(e)) try: r = self._session.post(self.PTC_LOGIN_URL2, data=data, timeout=self.timeout, allow_redirects=False) except Timeout: raise AuthTimeoutException('Auth POST timed out.') except RequestException as e: raise AuthException('Caught RequestException: {}'.format(e)) try: qs = parse_qs(urlsplit(r.headers['Location'])[3]) self._refresh_token = qs.get('ticket')[0] except Exception as e: raise AuthException('Could not retrieve token! {}'.format(e)) self._access_token = self._session.cookies.get('CASTGC') if self._access_token: self._login = True self._access_token_expiry = int(now) + 7200 self.log.info('PTC User Login successful.') elif self._refresh_token and retry: self.get_access_token() else: self._login = False raise AuthException("Could not retrieve a PTC Access Token") return self._login
def get_access_token(self, force_refresh=False): token_validity = self.check_access_token() if token_validity is True and force_refresh is False: self.log.debug('Using cached PTC Access Token') return self._access_token else: if force_refresh: self.log.info('Forced request of PTC Access Token!') else: self.log.info('Request PTC Access Token...') data = { 'client_id': 'mobile-app_pokemon-go', 'redirect_uri': 'https://www.nianticlabs.com/pokemongo/error', 'client_secret': self.PTC_LOGIN_CLIENT_SECRET, 'grant_type': 'refresh_token', 'code': self._refresh_token, } try: r = self._session.post(self.PTC_LOGIN_OAUTH, data=data, timeout=self.timeout) except Timeout: raise AuthTimeoutException('Auth POST timed out.') except RequestException as e: raise AuthException('Caught RequestException: {}'.format(e)) token_data = parse_qs(r.text) access_token = token_data.get('access_token') if access_token is not None: self._access_token = access_token[0] # set expiration to an hour less than value received because Pokemon OAuth # login servers return an access token with an explicit expiry time of # three hours, however, the token stops being valid after two hours. # See issue #86 expires = int(token_data.get('expires', [0])[0]) - 3600 if expires > 0: self._access_token_expiry = expires + get_time() else: self._access_token_expiry = 0 self._login = True self.log.info('PTC Access Token successfully retrieved.') self.log.debug('PTC Access Token: {}'.format(self._access_token)) else: self._access_token = None self._login = False if force_refresh: self.log.info('Reauthenticating with refresh token failed, using credentials instead.') return self.user_login(retry=False) raise AuthException("Could not retrieve a PTC Access Token")
def user_login(self, username=None, password=None, retry=True): self._username = username or self._username self._password = password or self._password if not isinstance(self._username, string_types) or not isinstance(self._password, string_types): raise InvalidCredentialsException("Username/password not correctly specified") self.log.info('PTC User Login for: {}'.format(self._username)) self._session.cookies.clear() now = get_time() try: r = self._session.get(self.PTC_LOGIN_URL1, timeout=self.timeout) except Timeout: raise AuthTimeoutException('Auth GET timed out.') except RequestException as e: raise AuthException('Caught RequestException: {}'.format(e)) try: data = r.json() data.update({ '_eventId': 'submit', 'username': self._username, 'password': self._password, }) except (ValueError, AttributeError) as e: self.log.error('PTC User Login Error - invalid JSON response: {}'.format(e)) raise AuthException('Invalid JSON response: {}'.format(e)) try: r = self._session.post(self.PTC_LOGIN_URL2, data=data, timeout=self.timeout, allow_redirects=False) except Timeout: raise AuthTimeoutException('Auth POST timed out.') except RequestException as e: raise AuthException('Caught RequestException: {}'.format(e)) try: qs = parse_qs(urlsplit(r.headers['Location'])[3]) self._refresh_token = qs.get('ticket')[0] except Exception as e: raise AuthException('Could not retrieve token! {}'.format(e)) self._access_token = self._session.cookies.get('CASTGC') if self._access_token: self._login = True self._access_token_expiry = int(now) + 7200 self.log.info('PTC User Login successful.') elif self._refresh_token and retry: self.get_access_token() else: self._login = False raise AuthException("Could not retrieve a PTC Access Token") return self._login
def check_authentication(self, expire_timestamp_ms, start, end): if self._auth_provider.is_new_ticket(expire_timestamp_ms): had_ticket = self._auth_provider.has_ticket() self._auth_provider.set_ticket([expire_timestamp_ms, start, end]) now_ms = get_time(ms=True) h, m, s = get_format_time_diff(now_ms, expire_timestamp_ms, True) if had_ticket: self.log.debug('Replacing old Session Ticket with new one valid for %02d:%02d:%02d hours (%s < %s)', h, m, s, now_ms, expire_timestamp_ms) else: self.log.debug('Received Session Ticket valid for %02d:%02d:%02d hours (%s < %s)', h, m, s, now_ms, expire_timestamp_ms)
def check_ticket(self): if self.has_ticket(): now_ms = get_time(ms = True) if now_ms < (self._ticket_expire - 10000): h, m, s = get_format_time_diff(now_ms, self._ticket_expire, True) self.log.debug('Session Ticket still valid for further %02d:%02d:%02d hours (%s < %s)', h, m, s, now_ms, self._ticket_expire) return True else: self.log.debug('Removed expired Session Ticket (%s < %s)', now_ms, self._ticket_expire) self._ticket_expire, self._ticket_start, self._ticket_end = (None, None, None) return False else: return False
def check_authentication(self, expire_timestamp_ms, start, end): if self._auth_provider.is_new_ticket(expire_timestamp_ms): had_ticket = self._auth_provider.has_ticket() self._auth_provider.set_ticket([expire_timestamp_ms, start, end]) now_ms = get_time(ms=True) h, m, s = get_format_time_diff(now_ms, expire_timestamp_ms, True) if had_ticket: self.log.debug('Replacing old Session Ticket with new one valid for %02d:%02d:%02d hours (%s < %s)', h, m, s, now_ms, expire_timestamp_ms) else: self.log.debug('Received Session Ticket valid for %02d:%02d:%02d hours (%s < %s)', h, m, s, now_ms, expire_timestamp_ms)
def check_ticket(self): if self.has_ticket(): now_ms = get_time(ms=True) if now_ms < (self._ticket_expire - 10000): h, m, s = get_format_time_diff(now_ms, self._ticket_expire, True) self.log.debug('Session Ticket still valid for further %02d:%02d:%02d hours (%s < %s)', h, m, s, now_ms, self._ticket_expire) return True else: self.log.debug('Removed expired Session Ticket (%s < %s)', now_ms, self._ticket_expire) self._ticket_expire, self._ticket_start, self._ticket_end = (None, None, None) return False else: return False
def __init__(self, provider=None, oauth2_refresh_token=None, username=None, password=None, position_lat=None, position_lng=None, position_alt=None, proxy_config=None, device_info=None): self.RPC_ID_LOW = 1 self.RPC_ID_HIGH = 1 self.START_TIME = get_time(ms=True) - random.randint(6000, 10000) self.set_logger() self.log.info('%s v%s - %s', __title__, __version__, __copyright__) self._auth_provider = None if provider is not None and ( (username is not None and password is not None) or (oauth2_refresh_token is not None)): self.set_authentication(provider, oauth2_refresh_token, username, password, proxy_config) self.set_api_endpoint('pgorelease.nianticlabs.com/plfe') self._position_lat = position_lat self._position_lng = position_lng self._position_alt = position_alt self._hash_server_token = None self._session = requests.session() # requests' Session calls .default_headers() in init, which # makes it set a bunch of default headers, including # 'Connection': 'keep-alive', so we overwrite all of them. self._session.headers = { 'User-Agent': 'Niantic App', 'Content-Type': 'application/binary', 'Accept-Encoding': 'identity, gzip' } self._session.verify = True if proxy_config is not None: self._session.proxies = proxy_config self.device_info = device_info self.state = RpcState()
def get_access_token(self, force_refresh=False): token_validity = self.check_access_token() if token_validity is True and force_refresh is False: self.log.debug('Using cached PTC Access Token') return self._access_token else: if force_refresh: self.log.info('Forced request of PTC Access Token!') else: self.log.info('Request PTC Access Token...') data1 = { 'client_id': 'mobile-app_pokemon-go', 'redirect_uri': 'https://www.nianticlabs.com/pokemongo/error', 'client_secret': self.PTC_LOGIN_CLIENT_SECRET, 'grant_type': 'refresh_token', 'code': self._refresh_token, } r2 = self._session.post(self.PTC_LOGIN_OAUTH, data=data1) qs = r2.content.decode('utf-8') token_data = parse_qs(qs) access_token = token_data.get('access_token', None) if access_token is not None: self._access_token = access_token[0] now_s = get_time() # set expiration to an hour less than value received because Pokemon OAuth # login servers return an access token with an explicit expiry time of # three hours, however, the token stops being valid after two hours. # See issue #86 expires = int(token_data.get('expires', [0])[0]) - 3600 if expires > 0: self._access_token_expiry = expires + now_s else: self._access_token_expiry = 0 self._login = True self.log.info('PTC Access Token successfully retrieved.') self.log.debug('PTC Access Token: %s...', self._access_token[:25]) else: self._access_token = None self._login = False raise AuthException("Could not retrieve a PTC Access Token")
def get_access_token(self, force_refresh = False): token_validity = self.check_access_token() if token_validity is True and force_refresh is False: self.log.debug('Using cached PTC Access Token') return self._access_token else: if force_refresh: self.log.info('Forced request of PTC Access Token!') else: self.log.info('Request PTC Access Token...') data1 = { 'client_id': 'mobile-app_pokemon-go', 'redirect_uri': 'https://www.nianticlabs.com/pokemongo/error', 'client_secret': self.PTC_LOGIN_CLIENT_SECRET, 'grant_type': 'refresh_token', 'code': self._refresh_token, } r2 = self._session.post(self.PTC_LOGIN_OAUTH, data=data1, headers=self.HEADERS) qs = r2.content.decode('utf-8') token_data = parse_qs(qs) access_token = token_data.get('access_token', None) if access_token is not None: self._access_token = access_token[0] now_s = get_time() # set expiration to an hour less than value received because Pokemon OAuth # login servers return an access token with an explicit expiry time of # three hours, however, the token stops being valid after two hours. # See issue #86 expires = int(token_data.get('expires', [0])[0]) - 3600 if expires > 0: self._access_token_expiry = expires + now_s else: self._access_token_expiry = 0 self._login = True self.log.info('PTC Access Token successfully retrieved.') self.log.debug('PTC Access Token: %s...', self._access_token[:25]) else: self._access_token = None self._login = False raise AuthException("Could not retrieve a PTC Access Token")
def __init__(self, auth_provider): self.log = logging.getLogger(__name__) self._auth_provider = auth_provider """ mystic unknown6 - revolved by PokemonGoDev """ self._signature_gen = False self._signature_lib = None if RpcApi.START_TIME == 0: RpcApi.START_TIME = get_time(ms=True) if RpcApi.RPC_ID == 0: RpcApi.RPC_ID = int(random.random() * 10 ** 18) self.log.debug('Generated new random RPC Request id: %s', RpcApi.RPC_ID)
async def get_access_token(self, force_refresh = False): token_validity = self.check_access_token() if token_validity is True and force_refresh is False: self.log.debug('Using cached PTC Access Token') return self._access_token else: if force_refresh: self.log.info('Forced request of PTC Access Token!') else: self.log.info('Request PTC Access Token...') data1 = { 'client_id': 'mobile-app_pokemon-go', 'redirect_uri': 'https://www.nianticlabs.com/pokemongo/error', 'client_secret': self.PTC_LOGIN_CLIENT_SECRET, 'grant_type': 'refresh_token', 'code': self._refresh_token, } async with aiohttp.ClientSession() as session: async with session.post( self.PTC_LOGIN_OAUTH, data=data1, ) as r2: qs = await r2.text() token_data = parse_qs(qs) access_token = token_data.get('access_token', None) if access_token is not None: self._access_token = access_token[0] now_s = get_time() expires = int(token_data.get('expires', [0])[0]) if expires > 0: self._access_token_expiry = expires + now_s else: self._access_token_expiry = 0 self._login = True self.log.info('PTC Access Token successfully retrieved.') self.log.debug('PTC Access Token: %s...', self._access_token[:25]) else: self._access_token = None self._login = False raise AuthException("Could not retrieve a PTC Access Token")
def get_access_token(self, force_refresh=False): token_validity = self.check_access_token() if token_validity is True and force_refresh is False: self.log.debug('Using cached PTC Access Token') return self._access_token else: if force_refresh: self.log.info('Forced request of PTC Access Token!') else: self.log.info('Request PTC Access Token...') data1 = { 'client_id': 'mobile-app_pokemon-go', 'redirect_uri': 'https://www.nianticlabs.com/pokemongo/error', 'client_secret': self.PTC_LOGIN_CLIENT_SECRET, 'grant_type': 'refresh_token', 'code': self._refresh_token, } r2 = self._session.post(self.PTC_LOGIN_OAUTH, data=data1) qs = r2.content.decode('utf-8') token_data = parse_qs(qs) access_token = token_data.get('access_token', None) if access_token is not None: self._access_token = access_token[0] now_s = get_time() expires = int(token_data.get('expires', [0])[0]) if expires > 0: self._access_token_expiry = expires + now_s else: self._access_token_expiry = 0 self._login = True self.log.info('PTC Access Token successfully retrieved.') self.log.debug('PTC Access Token: %s...', self._access_token[:25]) else: self._access_token = None self._login = False raise AuthException("Could not retrieve a PTC Access Token")
def check_authentication(self, response_dict): if isinstance(response_dict, dict) and ('auth_ticket' in response_dict) and \ ('expire_timestamp_ms' in response_dict['auth_ticket']) and \ (self._auth_provider.is_new_ticket(response_dict['auth_ticket']['expire_timestamp_ms'])): had_ticket = self._auth_provider.has_ticket() auth_ticket = response_dict['auth_ticket'] self._auth_provider.set_ticket( [auth_ticket['expire_timestamp_ms'], base64.standard_b64decode(auth_ticket['start']), base64.standard_b64decode(auth_ticket['end'])]) now_ms = get_time(ms=True) h, m, s = get_format_time_diff(now_ms, auth_ticket['expire_timestamp_ms'], True) if had_ticket: self.log.debug('Replacing old Session Ticket with new one valid for %02d:%02d:%02d hours (%s < %s)', h, m, s, now_ms, auth_ticket['expire_timestamp_ms']) else: self.log.debug('Received Session Ticket valid for %02d:%02d:%02d hours (%s < %s)', h, m, s, now_ms, auth_ticket['expire_timestamp_ms'])
def __init__(self, auth_provider, proxy_config=None): self.log = logging.getLogger(__name__) if proxy_config is not None: self._session.proxies = proxy_config self._auth_provider = auth_provider """ mystic unknown6 - revolved by PokemonGoDev """ self._signature_gen = False self._signature_lib = None if RpcApi.START_TIME == 0: RpcApi.START_TIME = get_time(ms=True) if RpcApi.RPC_ID == 0: RpcApi.RPC_ID = int(random.random() * 10**18) self.log.debug('Generated new random RPC Request id: %s', RpcApi.RPC_ID)
def __init__(self, auth_provider, device_info): self.log = logging.getLogger(__name__) self._auth_provider = auth_provider # mystical unknown6 - resolved by PokemonGoDev self._signal_agglom_gen = False self._signature_lib = None if RpcApi.START_TIME == 0: RpcApi.START_TIME = get_time(ms=True) # data fields for SignalAgglom self.session_hash = os.urandom(16) self.token2 = random.randint(1,59) self.course = random.uniform(0, 360) self.device_info = device_info
def __init__(self, auth_provider, device_info): self.log = logging.getLogger(__name__) self._auth_provider = auth_provider # mystical unknown6 - resolved by PokemonGoDev self._hash_engine = None self.request_proto = None if RpcApi.START_TIME == 0: RpcApi.START_TIME = get_time(ms=True) # data fields for SignalAgglom self.session_hash = os.urandom(16) self.token2 = random.randint(1, 59) self.course = random.uniform(0, 360) self.device_info = device_info
def __init__(self, auth_provider, device_info): self.log = logging.getLogger(__name__) self._auth_provider = auth_provider """ mystic unknown6 - revolved by PokemonGoDev """ self._signature_gen = False self._signature_lib = None if RpcApi.START_TIME == 0: RpcApi.START_TIME = get_time(ms=True) if RpcApi.RPC_ID == 0: RpcApi.RPC_ID = int(random.random() * 10**18) self.log.debug('Generated new random RPC Request id: %s', RpcApi.RPC_ID) """ data fields for unknown6 """ self.session_hash = os.urandom(32) self.device_info = device_info
def __init__(self, auth_provider): self.log = logging.getLogger(__name__) self._session = requests.session() self._session.headers.update({'User-Agent': 'Niantic App'}) self._session.verify = True self._auth_provider = auth_provider """ mystic unknown6 - revolved by PokemonGoDev """ self._signature_gen = False self._signature_lib = None if RpcApi.START_TIME == 0: RpcApi.START_TIME = get_time(ms=True) if RpcApi.RPC_ID == 0: RpcApi.RPC_ID = int(random.random() * 10 ** 18) self.log.debug('Generated new random RPC Request id: %s', RpcApi.RPC_ID)
def __init__(self, provider=None, oauth2_refresh_token=None, username=None, password=None, position_lat=None, position_lng=None, position_alt=None, proxy_config=None, device_info=None): self.RPC_ID_LOW = 1 self.RPC_ID_HIGH = 1 self.START_TIME = get_time(ms=True) self.set_logger() self.log.info('%s v%s - %s', __title__, __version__, __copyright__) self._auth_provider = None if provider is not None and ( (username is not None and password is not None) or (oauth2_refresh_token is not None)): self.set_authentication(provider, oauth2_refresh_token, username, password, proxy_config) self.set_api_endpoint("pgorelease.nianticlabs.com/plfe") self._position_lat = position_lat self._position_lng = position_lng self._position_alt = position_alt self._hash_server_token = None self._session = requests.session() self._session.headers.update({'User-Agent': 'Niantic App'}) self._session.verify = True if proxy_config is not None: self._session.proxies = proxy_config self.device_info = device_info self.state = RpcState()
def check_access_token(self): """ Add few seconds to now so the token get refreshed before it invalidates in the middle of the request """ now_s = get_time() + 120 if self._access_token is not None: if self._access_token_expiry == 0: self.log.debug('No Access Token Expiry found - assuming it is still valid!') return True elif self._access_token_expiry > now_s: h, m, s = get_format_time_diff(now_s, self._access_token_expiry, False) self.log.debug('Access Token still valid for further %02d:%02d:%02d hours (%s < %s)', h, m, s, now_s, self._access_token_expiry) return True else: self.log.info('Access Token expired!') return False else: self.log.debug('No Access Token available!') return False
def __init__(self, auth_provider, proxy_config=None): self.log = logging.getLogger(__name__) self._session = requests.session() if proxy_config is not None: self._session.proxies = proxy_config self._session.headers.update({'User-Agent': 'Niantic App'}) self._session.verify = True self._auth_provider = auth_provider """ mystic unknown6 - revolved by PokemonGoDev """ self._signature_gen = False self._signature_lib = None if RpcApi.START_TIME == 0: RpcApi.START_TIME = get_time(ms=True) if RpcApi.RPC_ID == 0: RpcApi.RPC_ID = int(random.random() * 10 ** 18) self.log.debug('Generated new random RPC Request id: %s', RpcApi.RPC_ID)
def __init__(self, auth_provider, device_info): self.log = logging.getLogger(__name__) self._auth_provider = auth_provider # mystical unknown6 - resolved by PokemonGoDev self._signal_agglom_gen = False self._signature_lib = None if RpcApi.START_TIME == 0: RpcApi.START_TIME = get_time(ms=True) if RpcApi.RPC_ID == 0: RpcApi.RPC_ID = int(random.random() * 10**18) self.log.debug('Generated new random RPC Request id: %s', RpcApi.RPC_ID) # data fields for SignalAgglom self.session_hash = os.urandom(16) self.token2 = random.randint(1, 59) self.course = random.uniform(0, 360) self.device_info = device_info
def _build_main_request(self, subrequests, platforms, player_position=None): self.log.debug('Generating main RPC request...') request = RequestEnvelope() request.status_code = 2 request.request_id = self.get_rpc_id() request.accuracy = random.choice((5, 5, 5, 5, 10, 10, 10, 30, 30, 50, 65, random.uniform(66,80))) if player_position: request.latitude, request.longitude, altitude = player_position # generate sub requests before Signature generation request = self._build_sub_requests(request, subrequests) request = self._build_platform_requests(request, platforms) ticket = self._auth_provider.get_ticket() if ticket: self.log.debug('Found Session Ticket - using this instead of oauth token') request.auth_ticket.expire_timestamp_ms, request.auth_ticket.start, request.auth_ticket.end = ticket ticket_serialized = request.auth_ticket.SerializeToString() else: self.log.debug('No Session Ticket found - using OAUTH Access Token') request.auth_info.provider = self._auth_provider.get_name() request.auth_info.token.contents = self._auth_provider.get_access_token() request.auth_info.token.unknown2 = self.token2 ticket_serialized = request.auth_info.SerializeToString() #Sig uses this when no auth_ticket available sig = Signature() sig.session_hash = self.session_hash sig.timestamp = get_time(ms=True) sig.timestamp_since_start = get_time(ms=True) - RpcApi.START_TIME if sig.timestamp_since_start < 5000: sig.timestamp_since_start = random.randint(5000, 8000) self._hash_engine.hash(sig.timestamp, request.latitude, request.longitude, request.accuracy, ticket_serialized, sig.session_hash, request.requests) sig.location_hash1 = self._hash_engine.get_location_auth_hash() sig.location_hash2 = self._hash_engine.get_location_hash() for req_hash in self._hash_engine.get_request_hashes(): sig.request_hash.append(ctypes.c_uint64(req_hash).value) loc = sig.location_fix.add() sen = sig.sensor_info.add() sen.timestamp_snapshot = random.randint(sig.timestamp_since_start - 5000, sig.timestamp_since_start - 100) loc.timestamp_snapshot = random.randint(sig.timestamp_since_start - 5000, sig.timestamp_since_start - 1000) loc.provider = random.choice(('network', 'network', 'network', 'network', 'fused')) loc.latitude = request.latitude loc.longitude = request.longitude loc.altitude = altitude or random.triangular(300, 400, 350) if random.random() > .95: # no reading for roughly 1 in 20 updates loc.course = -1 loc.speed = -1 else: self.course = random.triangular(0, 360, self.course) loc.course = self.course loc.speed = random.triangular(0.2, 4.25, 1) loc.provider_status = 3 loc.location_type = 1 if request.accuracy >= 65: loc.vertical_accuracy = random.triangular(35, 100, 65) loc.horizontal_accuracy = random.choice((request.accuracy, 65, 65, random.uniform(66,80), 200)) else: if request.accuracy > 10: loc.vertical_accuracy = random.choice((24, 32, 48, 48, 64, 64, 96, 128)) else: loc.vertical_accuracy = random.choice((3, 4, 6, 6, 8, 12, 24)) loc.horizontal_accuracy = request.accuracy sen.linear_acceleration_x = random.triangular(-3, 1, 0) sen.linear_acceleration_y = random.triangular(-2, 3, 0) sen.linear_acceleration_z = random.triangular(-4, 2, 0) sen.magnetic_field_x = random.triangular(-50, 50, 0) sen.magnetic_field_y = random.triangular(-60, 50, -5) sen.magnetic_field_z = random.triangular(-60, 40, -30) sen.magnetic_field_accuracy = random.choice((-1, 1, 1, 2, 2, 2, 2)) sen.attitude_pitch = random.triangular(-1.5, 1.5, 0.2) sen.attitude_yaw = random.uniform(-3, 3) sen.attitude_roll = random.triangular(-2.8, 2.5, 0.25) sen.rotation_rate_x = random.triangular(-6, 4, 0) sen.rotation_rate_y = random.triangular(-5.5, 5, 0) sen.rotation_rate_z = random.triangular(-5, 3, 0) sen.gravity_x = random.triangular(-1, 1, 0.15) sen.gravity_y = random.triangular(-1, 1, -.2) sen.gravity_z = random.triangular(-1, .7, -0.8) sen.status = 3 sig.unknown25 = 4500779412463383546 if self.device_info: for key in self.device_info: setattr(sig.device_info, key, self.device_info[key]) if self.device_info['device_brand'] == 'Apple': sig.activity_status.stationary = True else: sig.activity_status.stationary = True signature_proto = sig.SerializeToString() if self._needsPtr8(subrequests): plat_eight = UnknownPtr8Request() plat_eight.message = '15c79df0558009a4242518d2ab65de2a59e09499' plat8 = request.platform_requests.add() plat8.type = 8 plat8.request_message = plat_eight.SerializeToString() sig_request = SendEncryptedSignatureRequest() sig_request.encrypted_signature = pycrypt(signature_proto, sig.timestamp_since_start) plat = request.platform_requests.add() plat.type = 6 plat.request_message = sig_request.SerializeToString() request.ms_since_last_locationfix = int(random.triangular(300, 30000, 10000)) self.log.debug('Generated protobuf request: \n\r%s', request) return request
def _build_main_request(self, subrequests, player_position=None): self.log.debug('Generating main RPC request...') request = RequestEnvelope() request.status_code = 2 request.request_id = self.get_rpc_id() request.accuracy = random.choice((5, 5, 5, 5, 10, 10, 10, 30, 30, 50, 65, random.uniform(66,80))) if player_position: request.latitude, request.longitude, altitude = player_position # generate sub requests before SignalAgglomUpdates generation request = self._build_sub_requests(request, subrequests) ticket = self._auth_provider.get_ticket() if ticket: self.log.debug('Found Session Ticket - using this instead of oauth token') request.auth_ticket.expire_timestamp_ms, request.auth_ticket.start, request.auth_ticket.end = ticket ticket_serialized = request.auth_ticket.SerializeToString() else: self.log.debug('No Session Ticket found - using OAUTH Access Token') request.auth_info.provider = self._auth_provider.get_name() request.auth_info.token.contents = self._auth_provider.get_access_token() request.auth_info.token.unknown2 = self.token2 ticket_serialized = request.auth_info.SerializeToString() #Sig uses this when no auth_ticket available if self._signal_agglom_gen: sig = SignalAgglomUpdates() sig.location_hash_by_token_seed = self._hash_engine.generate_location_hash_by_seed(ticket_serialized, request.latitude, request.longitude, request.accuracy) sig.location_hash = self._hash_engine.generate_location_hash(request.latitude, request.longitude, request.accuracy) for req in request.requests: hash = self._hash_engine.generate_request_hash(ticket_serialized, req.SerializeToString()) sig.request_hashes.append(hash) sig.field22 = self.session_hash sig.epoch_timestamp_ms = get_time(ms=True) sig.timestamp_ms_since_start = get_time(ms=True) - RpcApi.START_TIME if sig.timestamp_ms_since_start < 5000: sig.timestamp_ms_since_start = random.randint(5000, 8000) loc = sig.location_updates.add() sen = sig.sensor_updates.add() sen.timestamp = random.randint(sig.timestamp_ms_since_start - 5000, sig.timestamp_ms_since_start - 100) loc.timestamp_ms = random.randint(sig.timestamp_ms_since_start - 30000, sig.timestamp_ms_since_start - 1000) loc.name = random.choice(('network', 'network', 'network', 'network', 'fused')) loc.latitude = request.latitude loc.longitude = request.longitude if not altitude: loc.altitude = random.triangular(300, 400, 350) else: loc.altitude = altitude if random.random() > .95: # no reading for roughly 1 in 20 updates loc.device_course = -1 loc.device_speed = -1 else: self.course = random.triangular(0, 360, self.course) loc.device_course = self.course loc.device_speed = random.triangular(0.2, 4.25, 1) loc.provider_status = 3 loc.location_type = 1 if request.accuracy >= 65: loc.vertical_accuracy = random.triangular(35, 100, 65) loc.horizontal_accuracy = random.choice((request.accuracy, 65, 65, random.uniform(66,80), 200)) else: if request.accuracy > 10: loc.vertical_accuracy = random.choice((24, 32, 48, 48, 64, 64, 96, 128)) else: loc.vertical_accuracy = random.choice((3, 4, 6, 6, 8, 12, 24)) loc.horizontal_accuracy = request.accuracy sen.acceleration_x = random.triangular(-3, 1, 0) sen.acceleration_y = random.triangular(-2, 3, 0) sen.acceleration_z = random.triangular(-4, 2, 0) sen.magnetic_field_x = random.triangular(-50, 50, 0) sen.magnetic_field_y = random.triangular(-60, 50, -5) sen.magnetic_field_z = random.triangular(-60, 40, -30) sen.magnetic_field_accuracy = random.choice((-1, 1, 1, 2, 2, 2, 2)) sen.attitude_pitch = random.triangular(-1.5, 1.5, 0.2) sen.attitude_yaw = random.uniform(-3, 3) sen.attitude_roll = random.triangular(-2.8, 2.5, 0.25) sen.rotation_rate_x = random.triangular(-6, 4, 0) sen.rotation_rate_y = random.triangular(-5.5, 5, 0) sen.rotation_rate_z = random.triangular(-5, 3, 0) sen.gravity_x = random.triangular(-1, 1, 0.15) sen.gravity_y = random.triangular(-1, 1, -.2) sen.gravity_z = random.triangular(-1, .7, -0.8) sen.status = 3 sig.field25 = ctypes.c_uint64(-8408506833887075802).value if self.device_info: for key in self.device_info: setattr(sig.device_info, key, self.device_info[key]) if self.device_info['device_brand'] == 'Apple': sig.ios_device_info.bool5 = True else: sig.ios_device_info.bool5 = True signal_agglom_proto = sig.SerializeToString() sig_request = SendEncryptedSignatureRequest() sig_request.encrypted_signature = self._generate_signature(signal_agglom_proto, sig.timestamp_ms_since_start) plat = request.platform_requests.add() plat.type = 6 plat.request_message = sig_request.SerializeToString() request.ms_since_last_locationfix = int(random.triangular(300, 30000, 10000)) self.log.debug('Generated protobuf request: \n\r%s', request) return request
def _build_main_request(self, subrequests, platforms, player_position=None): self.log.debug('Generating main RPC request...') request = RequestEnvelope() request.status_code = 2 request.request_id = self.get_rpc_id() request.accuracy = random.choice((5, 5, 5, 5, 10, 10, 10, 30, 30, 50, 65, random.uniform(66,80))) if player_position: request.latitude, request.longitude, altitude = player_position # generate sub requests before Signature generation request = self._build_sub_requests(request, subrequests) request = self._build_platform_requests(request, platforms) ticket = self._auth_provider.get_ticket() if ticket: self.log.debug('Found Session Ticket - using this instead of oauth token') request.auth_ticket.expire_timestamp_ms, request.auth_ticket.start, request.auth_ticket.end = ticket ticket_serialized = request.auth_ticket.SerializeToString() else: self.log.debug('No Session Ticket found - using OAUTH Access Token') request.auth_info.provider = self._auth_provider.get_name() request.auth_info.token.contents = self._auth_provider.get_access_token() request.auth_info.token.unknown2 = self.token2 ticket_serialized = request.auth_info.SerializeToString() #Sig uses this when no auth_ticket available sig = Signature() sig.session_hash = self.session_hash sig.timestamp = get_time(ms=True) sig.timestamp_since_start = get_time(ms=True) - RpcApi.START_TIME if sig.timestamp_since_start < 5000: sig.timestamp_since_start = random.randint(5000, 8000) self._hash_engine.hash(sig.timestamp, request.latitude, request.longitude, request.accuracy, ticket_serialized, sig.session_hash, request.requests) sig.location_hash1 = self._hash_engine.get_location_auth_hash() sig.location_hash2 = self._hash_engine.get_location_hash() for req_hash in self._hash_engine.get_request_hashes(): sig.request_hash.append(ctypes.c_uint64(req_hash).value) loc = sig.location_fix.add() sen = sig.sensor_info.add() sen.timestamp_snapshot = random.randint(sig.timestamp_since_start - 5000, sig.timestamp_since_start - 100) loc.timestamp_snapshot = random.randint(sig.timestamp_since_start - 5000, sig.timestamp_since_start - 1000) loc.provider = random.choice(('network', 'network', 'network', 'network', 'fused')) loc.latitude = request.latitude loc.longitude = request.longitude loc.altitude = altitude or random.triangular(300, 400, 350) if random.random() > .95: # no reading for roughly 1 in 20 updates loc.course = -1 loc.speed = -1 else: self.course = random.triangular(0, 360, self.course) loc.course = self.course loc.speed = random.triangular(0.2, 4.25, 1) loc.provider_status = 3 loc.location_type = 1 if request.accuracy >= 65: loc.vertical_accuracy = random.triangular(35, 100, 65) loc.horizontal_accuracy = random.choice((request.accuracy, 65, 65, random.uniform(66,80), 200)) else: if request.accuracy > 10: loc.vertical_accuracy = random.choice((24, 32, 48, 48, 64, 64, 96, 128)) else: loc.vertical_accuracy = random.choice((3, 4, 6, 6, 8, 12, 24)) loc.horizontal_accuracy = request.accuracy sen.linear_acceleration_x = random.triangular(-3, 1, 0) sen.linear_acceleration_y = random.triangular(-2, 3, 0) sen.linear_acceleration_z = random.triangular(-4, 2, 0) sen.magnetic_field_x = random.triangular(-50, 50, 0) sen.magnetic_field_y = random.triangular(-60, 50, -5) sen.magnetic_field_z = random.triangular(-60, 40, -30) sen.magnetic_field_accuracy = random.choice((-1, 1, 1, 2, 2, 2, 2)) sen.attitude_pitch = random.triangular(-1.5, 1.5, 0.2) sen.attitude_yaw = random.uniform(-3, 3) sen.attitude_roll = random.triangular(-2.8, 2.5, 0.25) sen.rotation_rate_x = random.triangular(-6, 4, 0) sen.rotation_rate_y = random.triangular(-5.5, 5, 0) sen.rotation_rate_z = random.triangular(-5, 3, 0) sen.gravity_x = random.triangular(-1, 1, 0.15) sen.gravity_y = random.triangular(-1, 1, -.2) sen.gravity_z = random.triangular(-1, .7, -0.8) sen.status = 3 sig.unknown25 = -782790124105039914 if self.device_info: for key in self.device_info: setattr(sig.device_info, key, self.device_info[key]) if self.device_info['device_brand'] == 'Apple': sig.activity_status.stationary = True else: sig.activity_status.stationary = True signature_proto = sig.SerializeToString() if self._needsPtr8(subrequests): plat_eight = UnknownPtr8Request() plat_eight.message = '15c79df0558009a4242518d2ab65de2a59e09499' plat8 = request.platform_requests.add() plat8.type = 8 plat8.request_message = plat_eight.SerializeToString() sig_request = SendEncryptedSignatureRequest() sig_request.encrypted_signature = pycrypt(signature_proto, sig.timestamp_since_start) plat = request.platform_requests.add() plat.type = 6 plat.request_message = sig_request.SerializeToString() request.ms_since_last_locationfix = int(random.triangular(300, 30000, 10000)) self.log.debug('Generated protobuf request: \n\r%s', request) return request
def user_login(self, username=None, password=None, retry=True): self._username = username or self._username self._password = password or self._password if not isinstance(self._username, string_types) or not isinstance( self._password, string_types): raise InvalidCredentialsException( "Username/password not correctly specified") self.log.info('PTC User Login for: {}'.format(self._username)) self._session.cookies.clear() now = get_time() get_params = { 'client_id': 'mobile-app_pokemon-go', 'redirect_uri': 'https://www.nianticlabs.com/pokemongo/error', 'locale': self.locale } try: r = self._session.get(self.PTC_LOGIN_URL1_GET, params=get_params, timeout=self.timeout) except Timeout: raise AuthTimeoutException('Auth GET timed out.') except RequestException as e: raise AuthException('Caught RequestException: {}'.format(e)) try: # Consumes response, so connection is released to pool. data = r.json() data.update({ '_eventId': 'submit', 'username': self._username, 'password': self._password, }) except (ValueError, AttributeError) as e: self.log.error( 'PTC User Login Error - invalid JSON response: {}'.format(e)) raise AuthException('Invalid JSON response: {}'.format(e)) post_params = { 'locale': self.locale, 'service': 'http://sso.pokemon.com/sso/oauth2.0/callbackAuthorize' } post_headers = {'Content-Type': 'application/x-www-form-urlencoded'} try: r = self._session.post(self.PTC_LOGIN_URL2_POST, data=data, params=post_params, headers=post_headers, timeout=self.timeout, allow_redirects=False) except Timeout: raise AuthTimeoutException('Auth POST timed out.') except RequestException as e: raise AuthException('Caught RequestException: {}'.format(e)) try: qs = parse_qs(urlsplit(r.headers['Location'])[3]) self._refresh_token = qs.get('ticket')[0] except Exception as e: raise AuthException('Could not retrieve token! {}'.format(e)) # We don't consume the response, so explicitly release connection. r.close() self._access_token = self._session.cookies.get('CASTGC') if self._access_token: self._login = True self._access_token_expiry = int(now) + 7200 self.log.info('PTC User Login successful.') elif self._refresh_token and retry: self.get_access_token() else: self._login = False raise AuthException("Could not retrieve a PTC Access Token") return self._login
def _build_main_request(self, subrequests, platforms, player_position=None): self.log.debug('Generating main RPC request...') request = RequestEnvelope() request.status_code = 2 request.request_id = self.request_id # 5: 43%, 10: 30%, 30: 5%, 50: 4%, 65: 10%, 200: 1%, float: 7% request.accuracy = weighted_choice([(5, 43), (10, 30), (30, 5), (50, 4), (65, 10), (200, 1), (random.uniform(65, 200), 7)]) if player_position: request.latitude, request.longitude, altitude = player_position # generate sub requests before Signature generation request = self._build_sub_requests(request, subrequests) request = self._build_platform_requests(request, platforms) ticket = self._auth_provider.get_ticket() if ticket: self.log.debug( 'Found Session Ticket - using this instead of oauth token') request.auth_ticket.expire_timestamp_ms, request.auth_ticket.start, request.auth_ticket.end = ticket ticket_serialized = request.auth_ticket.SerializeToString() else: self.log.debug( 'No Session Ticket found - using OAUTH Access Token') auth_provider = self._auth_provider request.auth_info.provider = auth_provider.get_name() request.auth_info.token.contents = auth_provider.get_access_token() request.auth_info.token.unknown2 = self.token2 # Sig uses this when no auth_ticket available. ticket_serialized = request.auth_info.SerializeToString() sig = Signature() sig.session_hash = self.state.session_hash sig.timestamp = get_time(ms=True) sig.timestamp_since_start = get_time(ms=True) - self.start_time self._hash_engine.hash(sig.timestamp, request.latitude, request.longitude, request.accuracy, ticket_serialized, sig.session_hash, request.requests) sig.location_hash1 = self._hash_engine.get_location_auth_hash() sig.location_hash2 = self._hash_engine.get_location_hash() for req_hash in self._hash_engine.get_request_hashes(): sig.request_hash.append(ctypes.c_uint64(req_hash).value) loc = sig.location_fix.add() sen = sig.sensor_info.add() sen.timestamp_snapshot = sig.timestamp_since_start - int( random.triangular(93, 4900, 3000)) loc.timestamp_snapshot = sig.timestamp_since_start - int( random.triangular(320, 3000, 1000)) loc.provider = 'fused' loc.latitude = request.latitude loc.longitude = request.longitude loc.altitude = altitude or random.uniform(150, 250) if random.random() > .85: # no reading for roughly 1 in 7 updates loc.course = -1 loc.speed = -1 else: loc.course = self.state.course loc.speed = random.triangular(0.25, 9.7, 8.2) loc.provider_status = 3 loc.location_type = 1 if isinstance(request.accuracy, float): loc.horizontal_accuracy = weighted_choice([(request.accuracy, 50), (65, 40), (200, 10)]) loc.vertical_accuracy = weighted_choice([(random.uniform(10, 96), 50), (10, 34), (12, 5), (16, 3), (24, 4), (32, 2), (48, 1), (96, 1)]) else: loc.horizontal_accuracy = request.accuracy if request.accuracy >= 10: loc.vertical_accuracy = weighted_choice([(6, 4), (8, 34), (10, 35), (12, 11), (16, 4), (24, 8), (32, 3), (48, 1)]) else: loc.vertical_accuracy = weighted_choice([(3, 15), (4, 39), (6, 14), (8, 13), (10, 14), (12, 5)]) sen.magnetic_field_accuracy = weighted_choice([(-1, 8), (0, 2), (1, 42), (2, 48)]) if sen.magnetic_field_accuracy == -1: sen.magnetic_field_x = 0 sen.magnetic_field_y = 0 sen.magnetic_field_z = 0 else: sen.magnetic_field_x = self.state.magnetic_field_x sen.magnetic_field_y = self.state.magnetic_field_y sen.magnetic_field_z = self.state.magnetic_field_z sen.linear_acceleration_x = random.triangular(-1.5, 2.5, 0) sen.linear_acceleration_y = random.triangular(-1.2, 1.4, 0) sen.linear_acceleration_z = random.triangular(-1.4, .9, 0) sen.attitude_pitch = random.triangular(-1.56, 1.57, 0.475) sen.attitude_yaw = random.triangular(-1.56, 3.14, .1) sen.attitude_roll = random.triangular(-3.14, 3.14, 0) sen.rotation_rate_x = random.triangular(-3.2, 3.52, 0) sen.rotation_rate_y = random.triangular(-3.1, 4.88, 0) sen.rotation_rate_z = random.triangular(-6, 3.7, 0) sen.gravity_x = random.triangular(-1, 1, 0.01) sen.gravity_y = random.triangular(-1, 1, -.4) sen.gravity_z = random.triangular(-1, 1, -.4) sen.status = 3 sig.unknown25 = 0x4AE22D4661C83701 if self.device_info: for key in self.device_info: setattr(sig.device_info, key, self.device_info[key]) if self.device_info['device_brand'] == 'Apple': sig.activity_status.stationary = True else: sig.activity_status.stationary = True signature_proto = sig.SerializeToString() if self._needsPtr8(subrequests): plat_eight = UnknownPtr8Request() plat_eight.message = '15c79df0558009a4242518d2ab65de2a59e09499' plat8 = request.platform_requests.add() plat8.type = 8 plat8.request_message = plat_eight.SerializeToString() sig_request = SendEncryptedSignatureRequest() sig_request.encrypted_signature = pycrypt(signature_proto, sig.timestamp_since_start) plat = request.platform_requests.add() plat.type = 6 plat.request_message = sig_request.SerializeToString() request.ms_since_last_locationfix = sig.timestamp_since_start - loc.timestamp_snapshot self.log.debug('Generated protobuf request: \n\r%s', request) return request
def _build_main_request(self, subrequests, player_position=None): self.log.debug('Generating main RPC request...') request = RequestEnvelope() request.status_code = 2 request.request_id = self.get_rpc_id() request.accuracy = random.choice((5, 5, 5, 5, 10, 10, 10, 30, 30, 50, 65, random.uniform(66,80))) if player_position: request.latitude, request.longitude, altitude = player_position # generate sub requests before SignalAgglomUpdates generation request = self._build_sub_requests(request, subrequests) ticket = self._auth_provider.get_ticket() if ticket: self.log.debug('Found Session Ticket - using this instead of oauth token') request.auth_ticket.expire_timestamp_ms, request.auth_ticket.start, request.auth_ticket.end = ticket ticket_serialized = request.auth_ticket.SerializeToString() else: self.log.debug('No Session Ticket found - using OAUTH Access Token') request.auth_info.provider = self._auth_provider.get_name() request.auth_info.token.contents = self._auth_provider.get_access_token() request.auth_info.token.unknown2 = self.token2 ticket_serialized = request.auth_info.SerializeToString() #Sig uses this when no auth_ticket available if self._signal_agglom_gen: sig = SignalAgglomUpdates() sig.location_hash_by_token_seed = generate_location_hash_by_seed(ticket_serialized, request.latitude, request.longitude, request.accuracy) sig.location_hash = generate_location_hash(request.latitude, request.longitude, request.accuracy) for req in request.requests: hash = generate_request_hash(ticket_serialized, req.SerializeToString()) sig.request_hashes.append(hash) sig.field22 = self.session_hash sig.epoch_timestamp_ms = get_time(ms=True) sig.timestamp_ms_since_start = get_time(ms=True) - RpcApi.START_TIME if sig.timestamp_ms_since_start < 5000: sig.timestamp_ms_since_start = random.randint(5000, 8000) loc = sig.location_updates.add() sen = sig.sensor_updates.add() sen.timestamp = random.randint(sig.timestamp_ms_since_start - 5000, sig.timestamp_ms_since_start - 100) loc.timestamp_ms = random.randint(sig.timestamp_ms_since_start - 30000, sig.timestamp_ms_since_start - 1000) loc.name = random.choice(('network', 'network', 'network', 'network', 'fused')) loc.latitude = request.latitude loc.longitude = request.longitude if not altitude: loc.altitude = random.triangular(300, 400, 350) else: loc.altitude = altitude if random.random() > .95: # no reading for roughly 1 in 20 updates loc.device_course = -1 loc.device_speed = -1 else: self.course = random.triangular(0, 360, self.course) loc.device_course = self.course loc.device_speed = random.triangular(0.2, 4.25, 1) loc.provider_status = 3 loc.location_type = 1 if request.accuracy >= 65: loc.vertical_accuracy = random.triangular(35, 100, 65) loc.horizontal_accuracy = random.choice((request.accuracy, 65, 65, random.uniform(66,80), 200)) else: if request.accuracy > 10: loc.vertical_accuracy = random.choice((24, 32, 48, 48, 64, 64, 96, 128)) else: loc.vertical_accuracy = random.choice((3, 4, 6, 6, 8, 12, 24)) loc.horizontal_accuracy = request.accuracy sen.acceleration_x = random.triangular(-3, 1, 0) sen.acceleration_y = random.triangular(-2, 3, 0) sen.acceleration_z = random.triangular(-4, 2, 0) sen.magnetic_field_x = random.triangular(-50, 50, 0) sen.magnetic_field_y = random.triangular(-60, 50, -5) sen.magnetic_field_z = random.triangular(-60, 40, -30) sen.magnetic_field_accuracy = random.choice((-1, 1, 1, 2, 2, 2, 2)) sen.attitude_pitch = random.triangular(-1.5, 1.5, 0.2) sen.attitude_yaw = random.uniform(-3, 3) sen.attitude_roll = random.triangular(-2.8, 2.5, 0.25) sen.rotation_rate_x = random.triangular(-6, 4, 0) sen.rotation_rate_y = random.triangular(-5.5, 5, 0) sen.rotation_rate_z = random.triangular(-5, 3, 0) sen.gravity_x = random.triangular(-1, 1, 0.15) sen.gravity_y = random.triangular(-1, 1, -.2) sen.gravity_z = random.triangular(-1, .7, -0.8) sen.status = 3 sig.field25 = 7363665268261373700 if self.device_info: for key in self.device_info: setattr(sig.device_info, key, self.device_info[key]) if self.device_info['device_brand'] == 'Apple': sig.ios_device_info.bool5 = True else: sig.ios_device_info.bool5 = True signal_agglom_proto = sig.SerializeToString() sig_request = SendEncryptedSignatureRequest() sig_request.encrypted_signature = self._generate_signature(signal_agglom_proto) plat = request.platform_requests.add() plat.type = 6 plat.request_message = sig_request.SerializeToString() request.ms_since_last_locationfix = int(random.triangular(300, 30000, 10000)) self.log.debug('Generated protobuf request: \n\r%s', request) return request