Ejemplo n.º 1
0
    def test_get_cells_no_response():
        account = test_account_name()
        config = create_core_test_config({
            "login": {
                "username": account
            },
            "mapping": {
                "cell_radius": 500
            }
        })
        api_wrapper = create_mock_api_wrapper(config)
        google_maps = Mock(spec=Client)
        logger = Mock()
        logger.log = Mock(return_value=None)
        mapper = Mapper(config, api_wrapper, google_maps, logger)

        api_wrapper.set_position(51.5044524, -0.0752479, 10)

        pgo = api_wrapper.get_api()
        pgo.set_response("get_map_objects", {})
        api_wrapper.call = Mock(return_value=None)

        # Clean up any old location logs
        if os.path.isfile('data/last-location-' + account + '.json'):
            os.unlink('data/last-location-' + account + '.json')

        cells = mapper.get_cells(51.5044524, -0.0752479)

        assert len(cells) == 0
Ejemplo n.º 2
0
    def test_find_location_with_coordinates():
        config = create_core_test_config()
        api_wrapper = create_mock_api_wrapper(config)
        google_maps = Mock(spec=Client)
        google_maps.elevation = Mock(return_value=[{'elevation': 10.1}])
        logger = Mock()
        logger.log = Mock(return_value=None)
        mapper = Mapper(config, api_wrapper, google_maps, logger)

        lat, lng, alt = mapper.find_location('51.5044524, -0.0752479')

        assert lat == 51.5044524
        assert lng == -0.0752479
        assert alt == 10.1
Ejemplo n.º 3
0
    def start(self):
        self._setup_logging()
        self._init_plugins()
        self._setup_api()
        random.seed()

        self.stepper = Stepper(self)
        self.mapper = Mapper(self)

        if self.config.navigator == 'fort':
            self.navigator = FortNavigator(self)  # pylint: disable=redefined-variable-type
        elif self.config.navigator == 'waypoint':
            self.navigator = WaypointNavigator(self)  # pylint: disable=redefined-variable-type
        elif self.config.navigator == 'camper':
            self.navigator = CamperNavigator(self)  # pylint: disable=redefined-variable-type
Ejemplo n.º 4
0
    def test_init():
        logger = Mock()
        logger.log = Mock(return_value=None)

        config_namespace = create_core_test_config()
        api_wrapper = create_mock_api_wrapper(config_namespace)
        event_manager = EventManager()
        player_service = Player(api_wrapper, event_manager, logger)
        pokemon_service = PokemonService(api_wrapper)
        mapper = Mapper(config_namespace, api_wrapper, Mock(), logger)
        path_finder = DirectPathFinder(config_namespace)
        stepper = Stepper(config_namespace, api_wrapper, path_finder, logger)
        navigator = FortNavigator(config_namespace, api_wrapper)

        bot = PokemonGoBot(config_namespace, api_wrapper, player_service,
                           pokemon_service, event_manager, mapper, stepper,
                           navigator, logger)

        assert len(bot.pokemon_list) == 151
        assert len(bot.item_list) == 30
        assert bot.position == (0, 0, 0)

        assert bot.config is config_namespace
        assert bot.api_wrapper is api_wrapper
        assert bot.player_service is player_service
        assert bot.pokemon_service is pokemon_service
        assert bot.event_manager is event_manager
        assert bot.mapper is mapper
        assert bot.stepper is stepper
        assert bot.navigator is navigator
        assert bot.logger is logger
Ejemplo n.º 5
0
    def start(self):
        self._setup_logging()
        self._init_plugins()
        self._setup_api()
        random.seed()

        self.stepper = Stepper(self)
        self.mapper = Mapper(self)

        if self.config.navigator == 'fort':
            self.navigator = FortNavigator(self)  # pylint: disable=redefined-variable-type
        elif self.config.navigator == 'waypoint':
            self.navigator = WaypointNavigator(self)  # pylint: disable=redefined-variable-type
        elif self.config.navigator == 'camper':
            self.navigator = CamperNavigator(self)  # pylint: disable=redefined-variable-type

        self.fire('bot_initialized')

        if self.config.initial_transfer:
            self.fire("pokemon_bag_full")

        if self.config.recycle_items:
            self.fire("item_bag_full")

        logger.log('[#]')
        self.update_player_and_inventory()
Ejemplo n.º 6
0
    def test_get_cells(self):
        account = test_account_name()
        config = create_core_test_config({
            "debug": True,
            "login": {
                "username": account,
            },
            "mapping": {
                "cell_radius": 500
            }
        })
        api_wrapper = create_mock_api_wrapper(config)
        google_maps = Mock(spec=Client)
        logger = Mock()
        logger.log = Mock(return_value=None)
        mapper = Mapper(config, api_wrapper, google_maps, logger)

        api_wrapper.set_position(51.5044524, -0.0752479, 10)

        pgo = api_wrapper.get_api()
        pgo.set_response(
            "get_map_objects", {
                "map_cells": [
                    self._create_map_cell(1),
                    self._create_map_cell(2),
                    self._create_map_cell(3),
                    self._create_map_cell(4),
                    self._create_map_cell(5)
                ]
            })

        # Clean up any old location logs
        if os.path.isfile('data/last-location-' + account + '.json'):
            os.unlink('data/last-location-' + account + '.json')

        cells = mapper.get_cells(51.5044524, -0.0752479)

        assert len(cells) == 5

        assert bool(
            os.path.isfile('data/last-location-' + account + '.json')) is True
        with open('data/last-location-' + account + '.json') as data_file:
            data = json.load(data_file)
            assert data["lat"] == 51.5044524
            assert data["lng"] == -0.0752479

        os.unlink('data/last-location-' + account + '.json')
Ejemplo n.º 7
0
    def test_find_location_with_coordinates_invalid_response():
        config = create_core_test_config()
        api_wrapper = create_mock_api_wrapper(config)
        google_maps = Mock(spec=Client)
        google_maps.elevation = Mock(return_value=None)
        location = Mock()
        location.latitude = 51.5044524
        location.longitude = -0.0752479
        location.altitude = 10.1
        google_maps.geocode = Mock(return_value=location)
        logger = Mock()
        logger.log = Mock(return_value=None)
        mapper = Mapper(config, api_wrapper, google_maps, logger)

        lat, lng, alt = mapper.find_location('51.5044524, -0.0752479')

        assert lat == 51.5044524
        assert lng == -0.0752479
        assert alt == 10.1
Ejemplo n.º 8
0
    def test_init():
        config = create_core_test_config()
        api_wrapper = create_mock_api_wrapper(config)
        google_maps = Mock(spec=Client)
        logger = Mock()
        logger.log = Mock(return_value=None)
        mapper = Mapper(config, api_wrapper, google_maps, logger)

        assert mapper.config == config
        assert mapper.api_wrapper == api_wrapper
        assert mapper.google_maps == google_maps
Ejemplo n.º 9
0
    def start(self):
        self._setup_logging()
        self._init_plugins()
        self._setup_api()
        random.seed()

        self.stepper = Stepper(self)
        self.mapper = Mapper(self)

        if self.config.navigator == 'fort':
            self.navigator = FortNavigator(self)  # pylint: disable=redefined-variable-type
        elif self.config.navigator == 'waypoint':
            self.navigator = WaypointNavigator(self)  # pylint: disable=redefined-variable-type
        elif self.config.navigator == 'camper':
            self.navigator = CamperNavigator(self)  # pylint: disable=redefined-variable-type
Ejemplo n.º 10
0
    def _create_generic_bot(config):
        logger = Mock()
        logger.log = Mock()
        config_namespace = create_core_test_config(config)
        api_wrapper = create_mock_api_wrapper(config_namespace)
        event_manager = Mock()
        player_service = Player(api_wrapper, event_manager, logger)
        pokemon_service = PokemonService(api_wrapper)
        mapper = Mapper(config_namespace, api_wrapper, Mock(), logger)
        path_finder = DirectPathFinder(config_namespace)
        stepper = Stepper(config_namespace, api_wrapper, path_finder, logger)
        navigator = FortNavigator(config_namespace, api_wrapper)

        return PokemonGoBot(config_namespace, api_wrapper, player_service,
                            pokemon_service, event_manager, mapper, stepper,
                            navigator, logger)
Ejemplo n.º 11
0
def create_mock_bot(user_config=None):
    config_namespace = create_core_test_config(user_config)

    event_manager = EventManager()
    logger = Logger(event_manager)
    api_wrapper = create_mock_api_wrapper(config_namespace)
    player_service = Player(api_wrapper, event_manager, logger)
    pokemon_service = Pokemon(api_wrapper)
    mapper = Mapper(config_namespace, api_wrapper, Mock(), logger)
    path_finder = DirectPathFinder(config_namespace)
    stepper = Stepper(config_namespace, api_wrapper, path_finder, logger)
    navigator = FortNavigator(config_namespace, api_wrapper)

    bot = PokemonGoBot(config_namespace, api_wrapper, player_service,
                       pokemon_service, event_manager, mapper, stepper,
                       navigator, logger)

    return bot
Ejemplo n.º 12
0
class PokemonGoBot(object):
    process_ignored_pokemon = False

    def __init__(self, config):
        self.config = config
        self.pokemon_list = json.load(open('data/pokemon.json'))
        self.item_list = {}
        for item_id, item_name in json.load(open('data/items.json')).items():
            self.item_list[int(item_id)] = item_name

        self.log = None
        self.api_wrapper = None
        self.ignores = []
        self.position = (0, 0, 0)
        self.plugin_manager = None
        self.last_session_check = time.gmtime()
        self.stepper = None
        self.navigator = None
        self.mapper = None

    def _init_plugins(self):
        # create a plugin manager
        self.plugin_manager = PluginManager('./plugins')

        # load all plugin modules
        for plugin in self.plugin_manager.get_available_plugins():
            if plugin not in self.config.exclude_plugins:
                self.plugin_manager.load_plugin(plugin)
            else:
                logger.log("Not loading plugin \"{}\"".format(plugin), color="red", prefix="Plugins")

        loaded_plugins = sorted(self.plugin_manager.get_loaded_plugins().keys())
        sleep(2)
        logger.log("Plugins loaded: {}".format(loaded_plugins), color="green", prefix="Plugins")
        logger.log("Events available: {}".format(manager.get_registered_events()), color="green", prefix="Events")

    def start(self):
        self._setup_logging()
        self._init_plugins()
        self._setup_api()
        random.seed()

        self.stepper = Stepper(self)
        self.mapper = Mapper(self)

        if self.config.navigator == 'fort':
            self.navigator = FortNavigator(self)  # pylint: disable=redefined-variable-type
        elif self.config.navigator == 'waypoint':
            self.navigator = WaypointNavigator(self)  # pylint: disable=redefined-variable-type
        elif self.config.navigator == 'camper':
            self.navigator = CamperNavigator(self)  # pylint: disable=redefined-variable-type

    def fire(self, event, *args, **kwargs):
        # type: (str, *Any, **Any) -> None
        manager.fire_with_context(event, self, *args, **kwargs)

    def run(self):
        map_cells = self.mapper.get_cells_at_current_position()

        # Work on all the initial cells
        self.work_on_cells(map_cells)
        self.navigator.navigate(map_cells)

    def work_on_cells(self, map_cells):
        # type: (Cell, bool) -> None
        for cell in map_cells:
            self.fire("pokemon_found", encounters=cell.catchable_pokemon + cell.wild_pokemon)
            self.fire("pokestops_found", pokestops=cell.pokestops)

    def _setup_logging(self):
        self.log = logging.getLogger(__name__)
        # log settings
        # log format
        logging.basicConfig(
            level=logging.DEBUG,
            format='%(asctime)s [%(module)10s] [%(levelname)5s] %(message)s')

        if self.config.debug:
            logging.getLogger("requests").setLevel(logging.DEBUG)
            logging.getLogger("pgoapi").setLevel(logging.DEBUG)
            logging.getLogger("rpc_api").setLevel(logging.DEBUG)
        else:
            logging.getLogger("requests").setLevel(logging.ERROR)
            logging.getLogger("pgoapi").setLevel(logging.ERROR)
            logging.getLogger("rpc_api").setLevel(logging.ERROR)

    def _setup_api(self):
        # instantiate api
        self.api_wrapper = PoGoApi(provider=self.config.auth_service, username=self.config.username,
                                   password=self.config.password)
        # provide player position on the earth

        self._set_starting_position()

        while not self.api_wrapper.login():
            logger.log('Login Error, server busy', 'red')
            logger.log('Waiting 15 seconds before trying again...')
            time.sleep(15)

        logger.log('[+] Login to Pokemon Go successful.', 'green')

        # chain subrequests (methods) into one RPC call

        # get player profile call
        # ----------------------
        response_dict = self.update_player_and_inventory()

        if response_dict is not None:
            player = response_dict['player']
            inventory = response_dict['inventory']
            pokemon = response_dict['pokemon']
            creation_date = player.get_creation_date()

            balls_stock = self.pokeball_inventory()

            pokecoins = player.pokecoin
            stardust = player.stardust

            logger.log('[#]')
            logger.log('[#] Username: {}'.format(player.username))
            logger.log('[#] Acccount Creation: {}'.format(creation_date))
            logger.log('[#] Bag Storage: {}/{}'.format(inventory["count"], player.max_item_storage))
            logger.log('[#] Pokemon Storage: {}/{}'.format(len(pokemon), player.max_pokemon_storage))
            logger.log('[#] Stardust: {}'.format(stardust))
            logger.log('[#] Pokecoins: {}'.format(pokecoins))
            logger.log('[#] PokeBalls: {}'.format(balls_stock[1]))
            logger.log('[#] GreatBalls: {}'.format(balls_stock[2]))
            logger.log('[#] UltraBalls: {}'.format(balls_stock[3]))
            logger.log('[#] -- Level: {}'.format(player.level))
            logger.log('[#] -- Experience: {}'.format(player.experience))
            logger.log('[#] -- Experience until next level: {}'.format(player.next_level_xp - player.experience))
            logger.log('[#] -- Pokemon Captured: {}'.format(player.pokemons_captured))
            logger.log('[#] -- Pokestops Visited: {}'.format(player.poke_stop_visits))
        # Testing
        # self.drop_item(Item.ITEM_POTION.value,1)
        # exit(0)

        if self.config.initial_transfer:
            self.fire("pokemon_bag_full")

        if self.config.recycle_items:
            self.fire("item_bag_full")

        logger.log('[#]')
        self.update_player_and_inventory()

    def update_player_and_inventory(self):
        # type: () -> Dict[str, object]
        self.api_wrapper.get_player().get_inventory()
        return self.api_wrapper.call()

    def pokeball_inventory(self):
        balls_stock = {Item.ITEM_POKE_BALL.value: 0,
                       Item.ITEM_GREAT_BALL.value: 0,
                       Item.ITEM_ULTRA_BALL.value: 0,
                       Item.ITEM_MASTER_BALL.value: 0}

        result = self.api_wrapper.get_inventory().call()
        if result is None:
            return balls_stock

        inventory_list = result["inventory"]

        for item_id in inventory_list:
            if item_id in balls_stock:
                balls_stock[item_id] = inventory_list[item_id]
        return balls_stock

    def _set_starting_position(self):

        if self.config.test:
            return

        if self.config.location_cache:
            try:
                #
                # save location flag used to pull the last known location from
                # the location.json
                with open('data/last-location-%s.json' % self.config.username) as last_location_file:
                    location_json = json.load(last_location_file)

                    self.position = (location_json['lat'], location_json['lng'], 0.0)
                    self.api_wrapper.set_position(*self.position)

                    logger.log('')
                    logger.log('[x] Last location flag used. Overriding passed in location')
                    logger.log('[x] Last in-game location was set as: {}'.format(self.position))
                    logger.log('')

                    return
            except IOError:
                if not self.config.location:
                    sys.exit("No cached Location. Please specify initial location.")
                else:
                    self._read_config_location()
        else:
            self._read_config_location()

        logger.log('[x] Position in-game set as: {}'.format(self.position))
        logger.log('')

    def _read_config_location(self):
        self.position = self._get_pos_by_name(self.config.location)
        self.api_wrapper.set_position(*self.position)
        logger.log('')
        logger.log(u'[x] Address found: {}'.format(self.config.location))

    def _get_pos_by_name(self, location_name):
        # type: (str) -> Tuple[float, float, float]
        if location_name.count(',') == 1:
            try:
                logger.log("[x] Fetching altitude from google")
                parts = location_name.split(',')

                pos_lat = float(parts[0])
                pos_lng = float(parts[1])

                # we need to ask google for the altitude
                gmaps = googlemaps.Client(key=self.config.gmapkey)
                response = gmaps.elevation((pos_lat, pos_lng))

                if len(response) and "elevation" in response[0]:
                    return pos_lat, pos_lng, response[0]["elevation"]
                else:
                    raise ValueError
            except ApiError:
                logger.log("[x] Could not fetch altitude from google. Trying geolocator.")
            except ValueError:
                logger.log("[x] Location was not Lat/Lng.")

        # Fallback to geolocation if no Lat/Lng can be found
        geolocator = GoogleV3(api_key=self.config.gmapkey)
        loc = geolocator.geocode(location_name, timeout=10)

        # self.log.info('Your given location: %s', loc.address.encode('utf-8'))
        # self.log.info('lat/long/alt: %s %s %s', loc.latitude, loc.longitude, loc.altitude)

        return loc.latitude, loc.longitude, loc.altitude

    def heartbeat(self):
        self.api_wrapper.get_player()
        self.api_wrapper.get_hatched_eggs()
        self.api_wrapper.get_inventory()
        self.api_wrapper.check_awarded_badges()
        self.api_wrapper.call()

    def get_pokemon_count(self):
        # type: () -> int
        response_dict = self.update_player_and_inventory()
        if response_dict is None:
            return 0
        return len(response_dict["pokemon"])

    def get_item_count(self):
        # type: () -> int
        response_dict = self.update_player_and_inventory()
        if response_dict is None:
            return 0
        return response_dict["inventory"]["count"]
Ejemplo n.º 13
0
class PokemonGoBot(object):
    process_ignored_pokemon = False

    def __init__(self, config):
        self.config = config
        self.pokemon_list = json.load(open('data/pokemon.json'))
        self.item_list = {}
        for item_id, item_name in json.load(open('data/items.json')).items():
            self.item_list[int(item_id)] = item_name

        self.log = None
        self.api_wrapper = None
        self.ignores = []
        self.position = (0, 0, 0)
        self.plugin_manager = None
        self.last_session_check = time.gmtime()
        self.stepper = None
        self.navigator = None
        self.mapper = None

    def _init_plugins(self):
        # create a plugin manager
        self.plugin_manager = PluginManager('./plugins')

        # load all plugin modules
        for plugin in self.plugin_manager.get_available_plugins():
            if plugin not in self.config.exclude_plugins:
                self.plugin_manager.load_plugin(plugin)
            else:
                logger.log("Not loading plugin \"{}\"".format(plugin), color="red", prefix="Plugins")

        loaded_plugins = sorted(self.plugin_manager.get_loaded_plugins().keys())
        sleep(2)
        logger.log("Plugins loaded: {}".format(loaded_plugins), color="green", prefix="Plugins")
        logger.log("Events available: {}".format(manager.get_registered_events()), color="green", prefix="Events")

    def start(self):
        self._setup_logging()
        self._init_plugins()
        self._setup_api()
        random.seed()

        self.stepper = Stepper(self)
        self.mapper = Mapper(self)

        if self.config.navigator == 'fort':
            self.navigator = FortNavigator(self)  # pylint: disable=redefined-variable-type
        elif self.config.navigator == 'waypoint':
            self.navigator = WaypointNavigator(self)  # pylint: disable=redefined-variable-type
        elif self.config.navigator == 'camper':
            self.navigator = CamperNavigator(self)  # pylint: disable=redefined-variable-type

    def fire(self, event, *args, **kwargs):
        # type: (str, *Any, **Any) -> None
        manager.fire_with_context(event, self, *args, **kwargs)

    def run(self):
        map_cells = self.mapper.get_cells_at_current_position()

        # Work on all the initial cells
        self.work_on_cells(map_cells)

        position_lat = self.stepper.current_lat
        position_lng = self.stepper.current_lng

        for destination in self.navigator.navigate(map_cells):
            destination.set_steps(
                self.stepper.get_route_between(position_lat, position_lng, destination.target_lat, destination.target_lng, destination.target_alt)
            )

            for _ in self.stepper.step(destination):
                self.work_on_cells(
                    self.mapper.get_cells_at_current_position()
                )

            position_lat = destination.target_lat
            position_lng = destination.target_lng

    def work_on_cells(self, map_cells):
        # type: (Cell, bool) -> None
        encounters = []
        pokestops = []
        for cell in map_cells:
            encounters += cell.catchable_pokemon + cell.wild_pokemon
            pokestops += cell.pokestops

        if len(encounters):
            self.fire("pokemon_found", encounters=encounters)
        if len(pokestops):
            self.fire("pokestops_found", pokestops=pokestops)

    def _setup_logging(self):
        self.log = logging.getLogger(__name__)
        # log settings
        # log format
        logging.basicConfig(
            level=logging.DEBUG,
            format='%(asctime)s [%(module)10s] [%(levelname)5s] %(message)s')

        if self.config.debug:
            logging.getLogger("requests").setLevel(logging.DEBUG)
            logging.getLogger("pgoapi").setLevel(logging.DEBUG)
            logging.getLogger("rpc_api").setLevel(logging.DEBUG)
        else:
            logging.getLogger("requests").setLevel(logging.ERROR)
            logging.getLogger("pgoapi").setLevel(logging.ERROR)
            logging.getLogger("rpc_api").setLevel(logging.ERROR)

    def _setup_api(self):
        # instantiate api
        self.api_wrapper = PoGoApi(provider=self.config.auth_service, username=self.config.username,
                                   password=self.config.password)
        # provide player position on the earth

        self._set_starting_position()

        while not self.api_wrapper.login():
            logger.log('Login Error, server busy', 'red')
            logger.log('Waiting 15 seconds before trying again...')
            time.sleep(15)

        logger.log('[+] Login to Pokemon Go successful.', 'green')

        # chain subrequests (methods) into one RPC call

        # get player profile call
        # ----------------------
        response_dict = self.update_player_and_inventory()

        if response_dict is not None:
            player = response_dict['player']
            inventory = response_dict['inventory']
            pokemon = response_dict['pokemon']
            creation_date = player.get_creation_date()

            balls_stock = self.pokeball_inventory()

            pokecoins = player.pokecoin
            stardust = player.stardust

            logger.log('[#]')
            logger.log('[#] Username: {}'.format(player.username))
            logger.log('[#] Acccount Creation: {}'.format(creation_date))
            logger.log('[#] Bag Storage: {}/{}'.format(inventory["count"], player.max_item_storage))
            logger.log('[#] Pokemon Storage: {}/{}'.format(len(pokemon), player.max_pokemon_storage))
            logger.log('[#] Stardust: {}'.format(stardust))
            logger.log('[#] Pokecoins: {}'.format(pokecoins))
            logger.log('[#] PokeBalls: {}'.format(balls_stock[1]))
            logger.log('[#] GreatBalls: {}'.format(balls_stock[2]))
            logger.log('[#] UltraBalls: {}'.format(balls_stock[3]))
            logger.log('[#] -- Level: {}'.format(player.level))
            logger.log('[#] -- Experience: {}'.format(player.experience))
            logger.log('[#] -- Experience until next level: {}'.format(player.next_level_xp - player.experience))
            logger.log('[#] -- Pokemon Captured: {}'.format(player.pokemons_captured))
            logger.log('[#] -- Pokestops Visited: {}'.format(player.poke_stop_visits))
        # Testing
        # self.drop_item(Item.ITEM_POTION.value,1)
        # exit(0)

        if self.config.initial_transfer:
            self.fire("pokemon_bag_full")

        if self.config.recycle_items:
            self.fire("item_bag_full")

        logger.log('[#]')
        self.update_player_and_inventory()

    def update_player_and_inventory(self):
        # type: () -> Dict[str, object]
        self.api_wrapper.get_player().get_inventory()
        return self.api_wrapper.call()

    def pokeball_inventory(self):
        balls_stock = {Item.ITEM_POKE_BALL.value: 0,
                       Item.ITEM_GREAT_BALL.value: 0,
                       Item.ITEM_ULTRA_BALL.value: 0,
                       Item.ITEM_MASTER_BALL.value: 0}

        result = self.api_wrapper.get_inventory().call()
        if result is None:
            return balls_stock

        inventory_list = result["inventory"]

        for item_id in inventory_list:
            if item_id in balls_stock:
                balls_stock[item_id] = inventory_list[item_id]
        return balls_stock

    def _set_starting_position(self):

        if self.config.test:
            return

        if self.config.location_cache:
            try:
                #
                # save location flag used to pull the last known location from
                # the location.json
                with open('data/last-location-%s.json' % self.config.username) as last_location_file:
                    location_json = json.load(last_location_file)

                    self.position = (location_json['lat'], location_json['lng'], 0.0)
                    self.api_wrapper.set_position(*self.position)

                    logger.log('')
                    logger.log('[x] Last location flag used. Overriding passed in location')
                    logger.log('[x] Last in-game location was set as: {}'.format(self.position))
                    logger.log('')

                    return
            except IOError:
                if not self.config.location:
                    sys.exit("No cached Location. Please specify initial location.")
                else:
                    self._read_config_location()
        else:
            self._read_config_location()

        logger.log('[x] Position in-game set as: {}'.format(self.position))
        logger.log('')

    def _read_config_location(self):
        self.position = self._get_pos_by_name(self.config.location)
        self.api_wrapper.set_position(*self.position)
        logger.log('')
        logger.log(u'[x] Address found: {}'.format(self.config.location))

    def _get_pos_by_name(self, location_name):
        # type: (str) -> Tuple[float, float, float]
        if location_name.count(',') == 1:
            try:
                logger.log("[x] Fetching altitude from google")
                parts = location_name.split(',')

                pos_lat = float(parts[0])
                pos_lng = float(parts[1])

                # we need to ask google for the altitude
                gmaps = googlemaps.Client(key=self.config.gmapkey)
                response = gmaps.elevation((pos_lat, pos_lng))

                if len(response) and "elevation" in response[0]:
                    return pos_lat, pos_lng, response[0]["elevation"]
                else:
                    raise ValueError
            except ApiError:
                logger.log("[x] Could not fetch altitude from google. Trying geolocator.")
            except ValueError:
                logger.log("[x] Location was not Lat/Lng.")

        # Fallback to geolocation if no Lat/Lng can be found
        geolocator = GoogleV3(api_key=self.config.gmapkey)
        loc = geolocator.geocode(location_name, timeout=10)

        # self.log.info('Your given location: %s', loc.address.encode('utf-8'))
        # self.log.info('lat/long/alt: %s %s %s', loc.latitude, loc.longitude, loc.altitude)

        return loc.latitude, loc.longitude, loc.altitude

    def heartbeat(self):
        self.api_wrapper.get_player()
        self.api_wrapper.get_hatched_eggs()
        self.api_wrapper.get_inventory()
        self.api_wrapper.check_awarded_badges()
        self.api_wrapper.call()

    def get_pokemon_count(self):
        # type: () -> int
        response_dict = self.update_player_and_inventory()
        if response_dict is None:
            return 0
        return len(response_dict["pokemon"])

    def get_item_count(self):
        # type: () -> int
        response_dict = self.update_player_and_inventory()
        if response_dict is None:
            return 0
        return response_dict["inventory"]["count"]