Пример #1
0
    def __getattr__(self, func):
    
        def function(**kwargs):
            request = self.create_request()
            getattr(request, func)( _call_direct = True, **kwargs )
            return request.call()

        if func.upper() in  RequestType.keys():
            return function
        else:
            print func.upper()
            print RequestType.keys()
            raise AttributeError
Пример #2
0
    def __getattr__(self, func):
        def function(**kwargs):

            if '_call_direct' in kwargs:
                del kwargs['_call_direct']
                self.log.info('Creating a new direct request...')
            elif not self._req_method_list:
                self.log.info('Creating a new request...')

            name = func.upper()
            if kwargs:
                self._req_method_list.append({RequestType.Value(name): kwargs})
                self.log.info("Adding '%s' to RPC request including arguments",
                              name)
                self.log.debug("Arguments of '%s': \n\r%s", name, kwargs)
            else:
                self._req_method_list.append(RequestType.Value(name))
                self.log.info("Adding '%s' to RPC request", name)

            return self

        if func.upper() in RequestType.keys():
            return function
        else:
            raise AttributeError
Пример #3
0
        def function(**kwargs):

            if not self._req_method_list:
                self.log.info('Create new request...')

            name = func.upper()
            if kwargs:
                self._req_method_list.append({RequestType.Value(name): kwargs})
                self.log.info("Adding '%s' to RPC request including arguments",
                              name)
                self.log.debug("Arguments of '%s': \n\r%s", name, kwargs)
            else:
                self._req_method_list.append(RequestType.Value(name))
                self.log.info("Adding '%s' to RPC request", name)

            return self
Пример #4
0
        def function(**kwargs):
            name = func.upper()

            position = kwargs.pop('position')
            callback = kwargs.pop('callback')

            if kwargs:
                method = {RequestType.Value(name): kwargs}
                self.log.debug(
                    "Adding '%s' to RPC request including arguments", name)
                self.log.debug("Arguments of '%s': \n\r%s", name, kwargs)
            else:
                method = RequestType.Value(name)
                self.log.debug("Adding '%s' to RPC request", name)

            self.call_method(method, position, callback)
Пример #5
0
    def _build_sub_requests(self, mainrequest, subrequest_list):
        self.log.debug('Generating sub RPC requests...')

        for entry in subrequest_list:
            if isinstance(entry, dict):

                entry_id = list(entry.items())[0][0]
                entry_content = entry[entry_id]

                entry_name = RequestType.Name(entry_id)

                proto_name = to_camel_case(entry_name.lower()) + 'Message'
                proto_classname = 'POGOProtos.Networking.Requests.Messages_pb2.' + proto_name
                subrequest_extension = self.get_class(proto_classname)()

                self.log.debug("Subrequest class: %s", proto_classname)

                for (key, value) in entry_content.items():
                    if isinstance(value, list):
                        self.log.debug("Found list: %s - trying as repeated", key)
                        for i in value:
                            try:
                                self.log.debug("%s -> %s", key, i)
                                r = getattr(subrequest_extension, key)
                                r.append(i)
                            except Exception as e:
                                self.log.warning('Argument %s with value %s unknown inside %s (Exception: %s)', key, i, proto_name, e)
                    elif isinstance(value, dict):
                        for k in value.keys():
                            try:
                                r = getattr(subrequest_extension, key)
                                setattr(r, k, value[k])
                            except Exception as e:
                                self.log.warning('Argument %s with value %s unknown inside %s (Exception: %s)', key, str(value), proto_name, e)
                    else:
                        try:
                            setattr(subrequest_extension, key, value)
                        except Exception as e:
                            try:
                                self.log.debug("%s -> %s", key, value)
                                r = getattr(subrequest_extension, key)
                                r.append(value)
                            except Exception as e:
                                self.log.warning('Argument %s with value %s unknown inside %s (Exception: %s)', key, value, proto_name, e)

                subrequest = mainrequest.requests.add()
                subrequest.request_type = entry_id
                subrequest.request_message = subrequest_extension.SerializeToString()

            elif isinstance(entry, int):
                subrequest = mainrequest.requests.add()
                subrequest.request_type = entry
            else:
                raise Exception('Unknown value in request list')

        return mainrequest
Пример #6
0
    def _parse_sub_responses(self, response_proto, subrequests_list,
                             response_proto_dict):
        self.log.debug('Parsing sub RPC responses...')
        response_proto_dict['responses'] = {}

        if response_proto_dict.get('status_code', 1) == 53:
            exception = ServerApiEndpointRedirectException()
            exception.set_redirected_endpoint(response_proto_dict['api_url'])
            raise exception

        if 'returns' in response_proto_dict:
            del response_proto_dict['returns']

        list_len = len(subrequests_list) - 1
        i = 0
        for subresponse in response_proto.returns:
            if i > list_len:
                self.log.info("Error - something strange happend...")

            request_entry = subrequests_list[i]
            if isinstance(request_entry, int):
                entry_id = request_entry
            else:
                entry_id = list(request_entry.items())[0][0]

            entry_name = RequestType.Name(entry_id)
            proto_name = to_camel_case(entry_name.lower()) + 'Response'
            proto_classname = 'POGOProtos.Networking.Responses_pb2.' + proto_name

            self.log.debug("Parsing class: %s", proto_classname)

            subresponse_return = None
            try:
                subresponse_extension = self.get_class(proto_classname)()
            except Exception as e:
                subresponse_extension = None
                error = 'Protobuf definition for {} not found'.format(
                    proto_classname)
                subresponse_return = error
                self.log.debug(error)

            if subresponse_extension:
                try:
                    subresponse_extension.ParseFromString(subresponse)
                    subresponse_return = protobuf_to_dict(
                        subresponse_extension)
                except:
                    error = "Protobuf definition for {} seems not to match".format(
                        proto_classname)
                    subresponse_return = error
                    self.log.debug(error)

            response_proto_dict['responses'][entry_name] = subresponse_return
            i += 1

        return response_proto_dict
Пример #7
0
    def __getattr__(self, func):
        def function(**kwargs):
            request = self.create_request()
            getattr(request, func)(_call_direct=True, **kwargs)
            return request.call()

        if func.upper() in RequestType.keys():
            return function
        else:
            raise AttributeError
Пример #8
0
    def __getattr__(self, func):
        def function(**kwargs):

            if not self._req_method_list:
                self.log.info('Create new request...')

            name = func.upper()
            if kwargs:
                self._req_method_list.append( { RequestType.Value(name): kwargs } )
                self.log.info("Adding '%s' to RPC request including arguments", name)
                self.log.debug("Arguments of '%s': \n\r%s", name, kwargs)
            else:
                self._req_method_list.append( RequestType.Value(name) )
                self.log.info("Adding '%s' to RPC request", name)

            return self

        if func.upper() in RequestType.keys():
            return function
        else:
            raise AttributeError
Пример #9
0
    def __getattr__(self, func):
        def function(**kwargs):
            name = func.upper()

            position = kwargs.pop('position')
            callback = kwargs.pop('callback')

            if kwargs:
                method = {RequestType.Value(name): kwargs}
                self.log.debug(
                   "Adding '%s' to RPC request including arguments", name)
                self.log.debug("Arguments of '%s': \n\r%s", name, kwargs)
            else:
                method = RequestType.Value(name)
                self.log.debug("Adding '%s' to RPC request", name)

            self.call_method(method, position, callback)

        if func.upper() in RequestType.keys():
            return function
        else:
            raise AttributeError
Пример #10
0
    def __getattr__(self, func):
        def function(**kwargs):
            name = func.upper()

            position = kwargs.pop('position')
            callback = kwargs.pop('callback')

            if kwargs:
                method = {RequestType.Value(name): kwargs}
                self.log.debug(
                    "Adding '%s' to RPC request including arguments", name)
                self.log.debug("Arguments of '%s': \n\r%s", name, kwargs)
            else:
                method = RequestType.Value(name)
                self.log.debug("Adding '%s' to RPC request", name)

            self.call_method(method, position, callback)

        if func.upper() in RequestType.keys():
            return function
        else:
            raise AttributeError
Пример #11
0
 def list_curr_methods(self):
     for i in self._req_method_list:
         print("{} ({})".format(RequestType.Name(i), i))
Пример #12
0
class PGoApiWorker(Thread):
    THROTTLE_TIME = 10.0
    # In case the server returns a status code 3, this has to be requested
    SC_3_REQUESTS = [RequestType.Value("GET_PLAYER")]

    def __init__(self, signature_lib_path, work_queue, auth_queue):
        Thread.__init__(self)
        self.log = logging.getLogger(__name__)
        self._running = True

        self._work_queue = work_queue
        self._auth_queue = auth_queue
        self.rpc_api = RpcApi(None)
        self.rpc_api.activate_signature(signature_lib_path)

    def _get_auth_provider(self):
        while True:  # Maybe change this loop to something more beautiful?
            next_call, auth_provider = self._auth_queue.get()
            if (time.time() + self.THROTTLE_TIME < next_call):
                # Probably one of the sidelined auth providers, skip it
                self._auth_queue.put((next_call, auth_provider))
            else:
                # Sleep until the auth provider is ready
                if (time.time() < next_call):  # Kind of a side effect -> bad
                    time.sleep(max(next_call - time.time(), 0))
                return (next_call, auth_provider)

    def run(self):
        while self._running:
            method, position, callback = self._work_queue.get()
            if not self._running:
                self._work_queue.put((method, position, callback))
                self._work_queue.task_done()
                continue

            next_call, auth_provider = self._get_auth_provider()
            if not self._running:
                self._auth_queue.put((next_call, auth_provider))
                self._work_queue.put((method, position, callback))
                self._work_queue.task_done()
                continue

            # Let's do this.
            self.rpc_api._auth_provider = auth_provider
            try:
                response = self.call(auth_provider, [method], position)
                next_call = time.time() + self.THROTTLE_TIME
            except Exception as e:
                # Too many login retries lead to an AuthException
                # So let us sideline this auth provider for 5 minutes
                if isinstance(e, AuthException):
                    self.log.error(
                        "AuthException in worker thread. Username: {}".format(
                            auth_provider.username))
                    next_call = time.time() + 5 * 60
                else:
                    self.log.error(
                        "Error in worker thread. Returning empty response. Error: {}"
                        .format(e))
                    next_call = time.time() + self.THROTTLE_TIME

                self._work_queue.put((method, position, callback))
                response = {}

            self._work_queue.task_done()
            self.rpc_api._auth_provider = None
            self._auth_queue.put((next_call, auth_provider))
            callback(response)

    def stop(self):
        self._running = False

    def call(self, auth_provider, req_method_list, position):
        if not req_method_list:
            raise EmptySubrequestChainException()

        lat, lng, alt = position
        if (lat is None) or (lng is None) or (alt is None):
            raise NoPlayerPositionSetException()

        self.log.debug('Execution of RPC')
        response = None

        again = True  # Status code 53 or not logged in?
        retries = 5
        while again:
            self._login_if_necessary(auth_provider, position)

            try:
                response = self.rpc_api.request(
                    auth_provider.get_api_endpoint(), req_method_list,
                    position)
                if not response:
                    raise ValueError(
                        'Request returned problematic response: {}'.format(
                            response))
            except NotLoggedInException:
                pass  # Trying again will call _login_if_necessary
            except ServerApiEndpointRedirectException as e:
                auth_provider.set_api_endpoint('https://{}/rpc'.format(
                    e.get_redirected_endpoint()))
            except Exception as e:  # Never crash the worker
                if isinstance(e, ServerBusyOrOfflineException):
                    self.log.info('Server seems to be busy or offline!')
                else:
                    self.log.info(
                        'Unexpected error during request: {}'.format(e))
                if retries == 0:
                    return {}
                retries -= 1
            else:
                if 'api_url' in response:
                    auth_provider.set_api_endpoint('https://{}/rpc'.format(
                        response['api_url']))

                if 'status_code' in response and response['status_code'] == 3:
                    self.log.info(
                        "Status code 3 returned. Performing get_player request."
                    )
                    req_method_list = self.SC_3_REQUESTS + req_method_list
                if 'responses' in response and not response['responses']:
                    self.log.info(
                        "Received empty map_object response. Logging out and retrying."
                    )
                    auth_provider._ticket_expire = time.time(
                    )  # this will trigger a login in _login_if_necessary
                else:
                    again = False

        return response

    def _login(self, auth_provider, position):
        self.log.info('Attempting login: {}'.format(auth_provider.username))
        consecutive_fails = 0

        while not auth_provider.user_login():
            sleep_t = min(math.exp(consecutive_fails / 1.7), 5 * 60)
            self.log.info(
                'Login failed, retrying in {:.2f} seconds'.format(sleep_t))
            consecutive_fails += 1
            time.sleep(sleep_t)
            if consecutive_fails == 5:
                raise AuthException('Login failed five times.')

        self.log.info('Login successful: {}'.format(auth_provider.username))

    def _login_if_necessary(self, auth_provider, position):
        if auth_provider._ticket_expire:
            remaining_time = auth_provider._ticket_expire / 1000 - time.time()

            if remaining_time < 60:
                self.log.info("Login for {} has or is about to expire".format(
                    auth_provider.username))
                self._login(auth_provider, position)
        else:
            self._login(auth_provider, position)