Beispiel #1
0
    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
Beispiel #2
0
    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
Beispiel #3
0
    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)
Beispiel #4
0
    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
Beispiel #5
0
    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'])
Beispiel #7
0
    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")
Beispiel #8
0
    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
Beispiel #9
0
    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")
Beispiel #10
0
    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
Beispiel #11
0
    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)
Beispiel #12
0
 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
Beispiel #13
0
    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)
Beispiel #14
0
 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
Beispiel #15
0
    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()
Beispiel #16
0
    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")
Beispiel #17
0
    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")
Beispiel #18
0
    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)
Beispiel #19
0
    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")
Beispiel #20
0
    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")
Beispiel #21
0
    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'])
Beispiel #22
0
    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)
Beispiel #23
0
    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
Beispiel #24
0
    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
Beispiel #25
0
    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
Beispiel #26
0
    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)
Beispiel #27
0
    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()
Beispiel #28
0
    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
Beispiel #29
0
    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)
Beispiel #30
0
    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
Beispiel #31
0
    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
Beispiel #32
0
    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
Beispiel #33
0
    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
Beispiel #34
0
    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
Beispiel #35
0
    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
Beispiel #36
0
    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