Esempio n. 1
0
    def test_start():
        config = create_core_test_config({"movement": {
            "walk_speed": 4.16,
        }})
        api_wrapper = create_mock_api_wrapper(config)
        path_finder = DirectPathFinder(config)
        logger = Mock()
        logger.log = Mock(return_value=None)
        stepper = Stepper(config, api_wrapper, path_finder, logger)

        stepper.start(51.5044524, -0.0752479, 10)

        assert stepper.origin_lat == 51.5044524
        assert stepper.origin_lng == -0.0752479
        assert stepper.origin_alt == 10

        assert stepper.current_lat == 51.5044524
        assert stepper.current_lng == -0.0752479
        assert stepper.current_alt == 10

        pgo = api_wrapper.get_api()
        lat, lng, alt = pgo.get_position()

        assert lat == 51.5044524
        assert lng == -0.0752479
        assert alt == 10
Esempio n. 2
0
    def test_start():
        config = create_core_test_config({
            "movement": {
                "walk_speed": 4.16,
            }
        })
        api_wrapper = create_mock_api_wrapper(config)
        path_finder = DirectPathFinder(config)
        logger = Mock()
        logger.log = Mock(return_value=None)
        stepper = Stepper(config, api_wrapper, path_finder, logger)

        stepper.start(51.5044524, -0.0752479, 10)

        assert stepper.origin_lat == 51.5044524
        assert stepper.origin_lng == -0.0752479
        assert stepper.origin_alt == 10

        assert stepper.current_lat == 51.5044524
        assert stepper.current_lng == -0.0752479
        assert stepper.current_alt == 10

        pgo = api_wrapper.get_api()
        lat, lng, alt = pgo.get_position()

        assert lat == 51.5044524
        assert lng == -0.0752479
        assert alt == 10
Esempio n. 3
0
    def test_snap_to_over_distance():
        config = create_core_test_config({
            "movement": {
                "walk_speed": 5,
            }
        })
        api_wrapper = create_mock_api_wrapper(config)
        path_finder = DirectPathFinder(config)
        logger = Mock()
        logger.log = Mock(return_value=None)
        stepper = Stepper(config, api_wrapper, path_finder, logger)
        stepper.start(51.50451, -0.07607, 10)

        # pre-calculated distance is 17.8 meters
        stepper.snap_to(51.50436, -0.07616, 11)

        pgo = api_wrapper.get_api()
        lat, lng, alt = pgo.get_position()

        assert stepper.current_lat == 51.50451
        assert stepper.current_lng == -0.07607
        assert stepper.current_alt == 10
        assert lat == 51.50451
        assert lng == -0.07607
        assert alt == 10
Esempio n. 4
0
    def test_step():
        config = create_core_test_config({
            "movement": {
                "walk_speed": 5,
                "path_finder": "direct",
                "distance_unit": "m"
            }
        })
        api_wrapper = create_mock_api_wrapper(config)
        path_finder = DirectPathFinder(config)
        logger = Mock()
        logger.log = Mock(return_value=None)
        stepper = Stepper(config, api_wrapper, path_finder, logger)
        stepper.start(51.50451, -0.07607, 10)

        destination = Destination(51.506000,
                                  -0.075049,
                                  11,
                                  name="Test Destination",
                                  exact_location=False)
        steps = [(51.504778, -0.075838, 10), (51.505092, -0.075650, 11),
                 (51.505436, -0.075446, 11)]
        destination.set_steps(steps)

        pgo = api_wrapper.get_api()

        # This route is being walked: http://www.darrinward.com/lat-long/?id=2163411
        # pre-calculated distance is 17.8 meters
        pointer = 0
        for _ in stepper.step(destination):
            target_lat, target_lng, target_alt = steps[pointer]
            assert stepper.current_lat == target_lat
            assert stepper.current_lng == target_lng
            assert stepper.current_alt == target_alt

            bot_lat, bot_lng, bot_alt = pgo.get_position()
            assert bot_lat == target_lat
            assert bot_lng == target_lng
            assert bot_alt == target_alt

            pointer += 1

        assert pointer == 3

        bot_lat, bot_lng, bot_alt = pgo.get_position()
        assert bot_lat == 51.505436
        assert bot_lng == -0.075446
        assert bot_alt == 11
        assert stepper.current_lat == 51.505436
        assert stepper.current_lng == -0.075446
        assert stepper.current_alt == 11
Esempio n. 5
0
    def test_step():
        config = create_core_test_config({
            "movement": {
                "walk_speed": 5,
                "path_finder": "direct",
                "distance_unit": "m"
            }
        })
        api_wrapper = create_mock_api_wrapper(config)
        path_finder = DirectPathFinder(config)
        logger = Mock()
        logger.log = Mock(return_value=None)
        stepper = Stepper(config, api_wrapper, path_finder, logger)
        stepper.start(51.50451, -0.07607, 10)

        destination = Destination(51.506000, -0.075049, 11, name="Test Destination", exact_location=False)
        steps = [
            (51.504778, -0.075838, 10),
            (51.505092, -0.075650, 11),
            (51.505436, -0.075446, 11)
        ]
        destination.set_steps(steps)

        pgo = api_wrapper.get_api()

        # This route is being walked: http://www.darrinward.com/lat-long/?id=2163411
        # pre-calculated distance is 17.8 meters
        pointer = 0
        for _ in stepper.step(destination):
            target_lat, target_lng, target_alt = steps[pointer]
            assert stepper.current_lat == target_lat
            assert stepper.current_lng == target_lng
            assert stepper.current_alt == target_alt

            bot_lat, bot_lng, bot_alt = pgo.get_position()
            assert bot_lat == target_lat
            assert bot_lng == target_lng
            assert bot_alt == target_alt

            pointer += 1

        assert pointer == 3

        bot_lat, bot_lng, bot_alt = pgo.get_position()
        assert bot_lat == 51.505436
        assert bot_lng == -0.075446
        assert bot_alt == 11
        assert stepper.current_lat == 51.505436
        assert stepper.current_lng == -0.075446
        assert stepper.current_alt == 11
Esempio n. 6
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
Esempio n. 7
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
Esempio n. 8
0
 def start(self):
     self._setup_logging()
     self._setup_api()
     self._setup_ignored_pokemon()
     self._init_plugins()
     self.stepper = Stepper(self)
     random.seed()
Esempio 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

        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()
Esempio n. 10
0
    def test_step_already_near_fort():
        calls = []
        config = create_core_test_config({
            "movement": {
                "walk_speed": 5,
                "path_finder": "direct",
                "distance_unit": "m"
            }
        })
        api_wrapper = create_mock_api_wrapper(config)
        path_finder = DirectPathFinder(config)

        destination = Destination(51.50436,
                                  -0.07616,
                                  11,
                                  name="Test Destination",
                                  exact_location=False)
        steps = [(51.50442, -0.07612, 10), (51.50448, -0.07609, 11),
                 (51.50436, -0.07616, 11)]
        destination.set_steps(steps)

        logger = Mock()
        logger.log = Mock(return_value=None)
        stepper = Stepper(config, api_wrapper, path_finder, logger)
        stepper.start(51.50451, -0.07607, 10)

        pgo = api_wrapper.get_api()

        # This route is being walked: http://www.darrinward.com/lat-long/?id=2163408
        calls.append(call("walking_started", coords=(51.50436, -0.07616, 11)))
        pointer = 0
        for _ in stepper.step(destination):
            pointer += 1

        assert pointer == 0

        bot_lat, bot_lng, bot_alt = pgo.get_position()
        assert bot_lat == 51.50451
        assert bot_lng == -0.07607
        assert bot_alt == 10
        assert stepper.current_lat == 51.50451
        assert stepper.current_lng == -0.07607
        assert stepper.current_alt == 10
Esempio n. 11
0
    def test_step_already_near_fort():
        calls = []
        config = create_core_test_config({
            "movement": {
                "walk_speed": 5,
                "path_finder": "direct",
                "distance_unit": "m"
            }
        })
        api_wrapper = create_mock_api_wrapper(config)
        path_finder = DirectPathFinder(config)

        destination = Destination(51.50436, -0.07616, 11, name="Test Destination", exact_location=False)
        steps = [
            (51.50442, -0.07612, 10),
            (51.50448, -0.07609, 11),
            (51.50436, -0.07616, 11)
        ]
        destination.set_steps(steps)

        logger = Mock()
        logger.log = Mock(return_value=None)
        stepper = Stepper(config, api_wrapper, path_finder, logger)
        stepper.start(51.50451, -0.07607, 10)

        pgo = api_wrapper.get_api()

        # This route is being walked: http://www.darrinward.com/lat-long/?id=2163408
        calls.append(call("walking_started", coords=(51.50436, -0.07616, 11)))
        pointer = 0
        for _ in stepper.step(destination):
            pointer += 1

        assert pointer == 0

        bot_lat, bot_lng, bot_alt = pgo.get_position()
        assert bot_lat == 51.50451
        assert bot_lng == -0.07607
        assert bot_alt == 10
        assert stepper.current_lat == 51.50451
        assert stepper.current_lng == -0.07607
        assert stepper.current_alt == 10
Esempio n. 12
0
    def test_init_path_finder_direct():
        config = create_core_test_config({"movement": {
            "walk_speed": 4.16,
        }})
        api_wrapper = create_mock_api_wrapper(config)
        path_finder = DirectPathFinder(config)
        logger = Mock()
        logger.log = Mock(return_value=None)
        stepper = Stepper(config, api_wrapper, path_finder, logger)

        assert isinstance(stepper.path_finder, DirectPathFinder)
Esempio n. 13
0
    def test_init_negative_walk():
        config = create_core_test_config({"movement": {
            "walk_speed": -5,
        }})
        api_wrapper = create_mock_api_wrapper(config)
        path_finder = Mock()
        logger = Mock()
        logger.log = Mock(return_value=None)
        stepper = Stepper(config, api_wrapper, path_finder, logger)

        assert stepper.speed == 4.16
Esempio n. 14
0
    def test_get_route_between():
        config = create_core_test_config({"movement": {
            "walk_speed": 5,
        }})
        api_wrapper = create_mock_api_wrapper(config)
        path_finder = DirectPathFinder(config)
        logger = Mock()
        logger.log = Mock(return_value=None)
        stepper = Stepper(config, api_wrapper, path_finder, logger)
        stepper.start(51.5044524, -0.0752479, 10)

        # pre-calculated distance is 205.5 meters
        # expected steps is 205.5 / (0.6 * 5) = 68.5 (which rounds to 69)
        steps = stepper.get_route_between(51.5044524, -0.0752479, 51.5062939,
                                          -0.0750065, 10)

        assert len(steps) == 69

        for step in steps:
            assert len(step) == 3
Esempio n. 15
0
    def test_get_route_between():
        config = create_core_test_config({
            "movement": {
                "walk_speed": 5,
            }
        })
        api_wrapper = create_mock_api_wrapper(config)
        path_finder = DirectPathFinder(config)
        logger = Mock()
        logger.log = Mock(return_value=None)
        stepper = Stepper(config, api_wrapper, path_finder, logger)
        stepper.start(51.5044524, -0.0752479, 10)

        # pre-calculated distance is 205.5 meters
        # expected steps is 205.5 / (0.6 * 5) = 68.5 (which rounds to 69)
        steps = stepper.get_route_between(51.5044524, -0.0752479, 51.5062939, -0.0750065, 10)

        assert len(steps) == 69

        for step in steps:
            assert len(step) == 3
Esempio n. 16
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)
Esempio n. 17
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
Esempio n. 18
0
    def test_init():
        config = create_core_test_config({"movement": {
            "walk_speed": 13.37,
        }})
        api_wrapper = create_mock_api_wrapper(config)
        path_finder = Mock()

        logger = Mock()
        logger.log = Mock(return_value=None)
        stepper = Stepper(config, api_wrapper, path_finder, logger)

        assert stepper.origin_lat is None
        assert stepper.origin_lng is None
        assert stepper.origin_alt is None

        assert stepper.current_lat is None
        assert stepper.current_lng is None
        assert stepper.current_alt is None

        assert stepper.speed == 13.37
Esempio n. 19
0
    def test_snap_to_over_distance():
        config = create_core_test_config({"movement": {
            "walk_speed": 5,
        }})
        api_wrapper = create_mock_api_wrapper(config)
        path_finder = DirectPathFinder(config)
        logger = Mock()
        logger.log = Mock(return_value=None)
        stepper = Stepper(config, api_wrapper, path_finder, logger)
        stepper.start(51.50451, -0.07607, 10)

        # pre-calculated distance is 17.8 meters
        stepper.snap_to(51.50436, -0.07616, 11)

        pgo = api_wrapper.get_api()
        lat, lng, alt = pgo.get_position()

        assert stepper.current_lat == 51.50451
        assert stepper.current_lng == -0.07607
        assert stepper.current_alt == 10
        assert lat == 51.50451
        assert lng == -0.07607
        assert alt == 10
Esempio n. 20
0
class PokemonGoBot(object):
    process_ignored_pokemon = False

    def __init__(self, config):
        self.config = config
        self.item_list = json.load(open('data/items.json'))
        self.pokemon_list = json.load(open('data/pokemon.json'))

        self.log = None
        self.stepper = None
        self.api = None
        self.inventory = []
        self.ignores = []
        self.position = (0, 0, 0)
        self.plugin_manager = None

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

        # 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))

    def start(self):
        self._setup_logging()
        self._setup_api()
        self._setup_ignored_pokemon()
        self._init_plugins()
        self.stepper = Stepper(self)
        random.seed()

    def fire(self, event, *args, **kwargs):
        manager.fire_with_context(event, self, *args, **kwargs)

    def take_step(self):
        self.stepper.take_step()

    def work_on_cell(self, cell, include_fort_on_path):
        self._remove_ignored_pokemon(cell)

        if (self.config.mode == "all" or self.config.mode == "poke") and 'catchable_pokemons' in cell and len(cell['catchable_pokemons']) > 0:
            logger.log('[#] Something rustles nearby!')
            # Sort all by distance from current pos- eventually this should
            # build graph & A* it
            cell['catchable_pokemons'].sort(key=lambda x: distance(self.position[0], self.position[1], x['latitude'], x['longitude']))

            user_web_catchable = 'web/catchable-%s.json' % (self.config.username)
            for pokemon in cell['catchable_pokemons']:
                with open(user_web_catchable, 'w') as outfile:
                    json.dump(pokemon, outfile)

                if self.catch_pokemon(pokemon) == PokemonCatchWorker.NO_POKEBALLS:
                    break
                with open(user_web_catchable, 'w') as outfile:
                    json.dump({}, outfile)

        if (self.config.mode == "all" or self.config.mode == "poke") and 'wild_pokemons' in cell and len(cell['wild_pokemons']) > 0:
            # Sort all by distance from current pos- eventually this should
            # build graph & A* it
            cell['wild_pokemons'].sort(key=lambda x: distance(self.position[0], self.position[1], x['latitude'], x['longitude']))
            for pokemon in cell['wild_pokemons']:
                if self.catch_pokemon(pokemon) == PokemonCatchWorker.NO_POKEBALLS:
                    break
        if include_fort_on_path:
            if 'forts' in cell:
                # Only include those with a lat/long
                forts = [fort for fort in cell['forts'] if 'latitude' in fort and 'type' in fort]
                # gyms = [gym for gym in cell['forts'] if 'gym_points' in gym]

                # Sort all by distance from current pos- eventually this should
                # build graph & A* it
                forts.sort(key=lambda x: distance(self.position[0], self.position[1], x['latitude'], x['longitude']))
                for fort in forts:
                    walk_worker = WalkTowardsFortWorker(fort, self)
                    walk_worker.work()

                    if self.config.mode == "all" or self.config.mode == "farm":
                        spinner_worker = SeenFortWorker(fort, self)
                        spinner_worker.work()

    def catch_pokemon(self, pokemon):
        catch_worker = PokemonCatchWorker(pokemon, self)
        return_value = catch_worker.work()

        if return_value == PokemonCatchWorker.BAG_FULL:
            transfer_worker = InitialTransferWorker(self)
            transfer_worker.work()

        return return_value

    def _work_on_forts(self, position, map_cells):
        forts = filtered_forts(position[0], position[1], sum([cell.get("forts", []) for cell in map_cells], []))
        if forts:
            walk_worker = WalkTowardsFortWorker(forts[0], self)
            walk_worker.work()

            spinner_worker = SeenFortWorker(forts[0], self)
            spinner_worker.work()

    def _remove_ignored_pokemon(self, map_cells):
        if self.process_ignored_pokemon:
            try:
                for cell in map_cells:
                    for pokemon in cell['wild_pokemons'][:]:
                        pokemon_id = pokemon['pokemon_data']['pokemon_id']
                        pokemon_name = [x for x in self.pokemon_list if int(x.get('Number')) == pokemon_id][0]['Name']

                        if pokemon_name in self.ignores:
                            cell['wild_pokemons'].remove(pokemon)
            except KeyError:
                pass

            try:
                for cell in map_cells:
                    for pokemon in cell['catchable_pokemons'][:]:
                        pokemon_id = pokemon['pokemon_id']
                        pokemon_name = [x for x in self.pokemon_list if int(x.get('Number')) == pokemon_id][0]['Name']

                        if pokemon_name in self.ignores:
                            cell['catchable_pokemons'].remove(pokemon)
            except KeyError:
                pass

    def _work_on_catchable_pokemon(self, map_cells):
        for cell in map_cells:
            if 'catchable_pokemons' in cell and len(cell['catchable_pokemons']) > 0:
                logger.log('[#] Something rustles nearby!')
                # Sort all by distance from current pos- eventually this should
                # build graph & A* it
                cell['catchable_pokemons'].sort(
                    key=lambda x: distance(self.position[0], self.position[1], x['latitude'], x['longitude']))
                for pokemon in cell['catchable_pokemons']:
                    with open('web/catchable-%s.json' % (self.config.username), 'w') as outfile:
                        json.dump(pokemon, outfile)
                    worker = PokemonCatchWorker(pokemon, self)
                    if worker.work() == -1:
                        break
                    with open('web/catchable-%s.json' % (self.config.username), 'w') as outfile:
                        json.dump({}, outfile)

    def _work_on_wild_pokemon(self, map_cells):
        for cell in map_cells:
            if 'wild_pokemons' in cell and len(cell['wild_pokemons']) > 0:
                # Sort all by distance from current pos- eventually this should
                # build graph & A* it
                cell['wild_pokemons'].sort(
                    key=lambda x: distance(self.position[0], self.position[1], x['latitude'], x['longitude']))
                for pokemon in cell['wild_pokemons']:
                    worker = PokemonCatchWorker(pokemon, self)
                    if worker.work() == -1:
                        break

    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 pgoapi
        self.api = PGoApi()
        # provide player position on the earth

        self._set_starting_position()

        if not self.api.login(self.config.auth_service,
                              str(self.config.username),
                              str(self.config.password)):
            logger.log('Login Error, server busy', 'red')
            exit(0)

        # chain subrequests (methods) into one RPC call

        # get player profile call
        # ----------------------
        self.api.get_player()

        response_dict = self.api.call()
        if response_dict is not None:
            # print('Response dictionary: \n\r{}'.format(json.dumps(response_dict, indent=2)))

            player = response_dict['responses']['GET_PLAYER']['player_data']

            # @@@ TODO: Convert this to d/m/Y H:M:S
            creation_date = datetime.datetime.fromtimestamp(
                player['creation_timestamp_ms'] / 1e3)

            balls_stock = self.pokeball_inventory()

            pokecoins = player['currencies'][0].get('amount', '0')
            stardust = player['currencies'][1].get('amount', '0')

            logger.log('[#]')
            logger.log('[#] Username: {username}'.format(**player))
            logger.log('[#] Acccount Creation: {}'.format(creation_date))
            logger.log('[#] Bag Storage: {}/{}'.format(
                self.get_inventory_count('item'), player['max_item_storage']))
            logger.log('[#] Pokemon Storage: {}/{}'.format(
                self.get_inventory_count('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]))
        # Testing
        # self.drop_item(Item.ITEM_POTION.value,1)
        # exit(0)
        self.get_player_info()

        if self.config.initial_transfer:
            worker = InitialTransferWorker(self)
            worker.work()

        if self.config.recycle_items:
            recycle_worker = RecycleItemsWorker(self)
            recycle_worker.work()

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

    def _setup_ignored_pokemon(self):
        pass
        # try:
        #     with open("./data/catch-ignore.yml", 'r') as ignore_file:
        #         self.ignores = yaml.load(ignore_file)['ignore']
        #         if len(self.ignores) > 0:
        #             self.process_ignored_pokemon = True
        # except Exception:
        #     pass

    def drop_item(self, item_id, count):
        self.api.recycle_inventory_item(item_id=item_id, count=count)
        self.api.call()

    def update_inventory(self):
        self.api.get_inventory()
        response = self.api.call()
        self.inventory = list()
        try:
            inventory_items = response['responses']['GET_INVENTORY']['inventory_delta']['inventory_items']
            for item in inventory_items:
                try:
                    item_data = item['inventory_item_data']['item']
                    if 'item_id' not in item_data or 'count' not in item_data:
                        continue
                    self.inventory.append(item_data)
                except KeyError:
                    pass
        except KeyError:
            pass

    def pokeball_inventory(self):
        self.api.get_player().get_inventory()

        inventory_req = self.api.call()
        inventory_list = convert_to_utf8(inventory_req['responses']['GET_INVENTORY']['inventory_delta']['inventory_items'])
        with open('web/inventory-{}.json'.format(self.config.username), 'w') as outfile:
            json.dump(inventory_list, outfile)

        # get player balls stock
        # ----------------------
        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}

        for item in inventory_list:
            try:
                item_id = int(item['inventory_item_data']['item']['item_id'])
                item_count = int(item['inventory_item_data']['item']['count'])
                if item_id in balls_stock:
                    balls_stock[item_id] = item_count
            except KeyError:
                continue
        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.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 Exception:
                if not self.config.location:
                    sys.exit("No cached Location. Please specify initial location.")
                else:
                    pass
        else:
            # this will fail if the location.json isn't there or not valid.
            # Still runs if location is set.
            self.position = self._get_pos_by_name(self.config.location)
            self.api.set_position(*self.position)
            logger.log('')
            logger.log(u'[x] Address found: {}'.format(self.config.location))

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

    def _get_pos_by_name(self, location_name):
        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.get_player()
        self.api.get_hatched_eggs()
        self.api.get_inventory()
        self.api.check_awarded_badges()
        self.api.call()

    def get_inventory_count(self, what):
        self.api.get_inventory()
        response_dict = self.api.call()

        if response_dict is None:
            return 0
        pokecount = 0
        itemcount = 1
        try:
            inventory_items = response_dict['responses']['GET_INVENTORY']['inventory_delta']['inventory_items']
            for item in inventory_items:
                # print('item {}'.format(item))
                if 'inventory_item_data' in item:
                    item_data = item['inventory_item_data']
                    if 'pokemon_data' in item_data:
                        pokecount += 1
                    if 'item' in item_data and 'count' in item_data['item']:
                        itemcount += item_data['item']['count']
        except KeyError:
            pass

        if 'pokemon' in what:
            return pokecount
        if 'item' in what:
            return itemcount
        return 0

    def get_player_info(self):
        self.api.get_inventory()
        response_dict = self.api.call()
        if response_dict is None:
            logger.log("Couldn't get player info!", "red")
            return
        try:
            inventory_items = response_dict['responses']['GET_INVENTORY']['inventory_delta']['inventory_items']
            for item in inventory_items:
                # print('item {}'.format(item))
                try:
                    player_stats = item['inventory_item_data']['player_stats']

                    if 'experience' not in player_stats:
                        player_stats['experience'] = 0

                    if 'level' in player_stats:
                        logger.log('[#] -- Level: {level}'.format(**player_stats))

                    if 'next_level_xp' in player_stats:
                        nextlvlxp = int(player_stats['next_level_xp']) - int(player_stats['experience'])
                        logger.log('[#] -- Experience: {experience}'.format(**player_stats))
                        logger.log('[#] -- Experience until next level: {}'.format(nextlvlxp))

                    if 'pokemons_captured' in player_stats:
                        logger.log('[#] -- Pokemon Captured: {pokemons_captured}'.format(**player_stats))

                    if 'poke_stop_visits' in player_stats:
                        logger.log('[#] -- Pokestops Visited: {poke_stop_visits}'.format(**player_stats))
                except KeyError:
                    pass
        except KeyError:
            pass
Esempio n. 21
0
class PokemonGoBot(object):
    process_ignored_pokemon = False

    def __init__(self, config):
        self.config = config
        self.item_list = json.load(open('data/items.json'))
        self.pokemon_list = json.load(open('data/pokemon.json'))

        self.log = None
        self.stepper = None
        self.api = None
        self.inventory = []
        self.ignores = []
        self.position = (0, 0, 0)
        self.plugin_manager = None
        self.last_session_check = time.gmtime()

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

        # 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))

    def start(self):
        self._setup_logging()
        self._setup_api()
        self._setup_ignored_pokemon()
        self._init_plugins()
        self.stepper = Stepper(self)
        random.seed()

    def fire(self, event, *args, **kwargs):
        manager.fire_with_context(event, self, *args, **kwargs)

    def take_step(self):
        self.stepper.take_step()

    def work_on_cell(self, cell, include_fort_on_path):
        # check if token session has expired
        self.check_session()

        self._remove_ignored_pokemon(cell)

        if (self.config.mode == "all" or self.config.mode == "poke") and 'catchable_pokemons' in cell and len(cell['catchable_pokemons']) > 0:
            logger.log('[#] Something rustles nearby!')
            # Sort all by distance from current pos- eventually this should
            # build graph & A* it
            cell['catchable_pokemons'].sort(key=lambda x: distance(self.position[0], self.position[1], x['latitude'], x['longitude']))

            user_web_catchable = 'web/catchable-%s.json' % self.config.username
            for pokemon in cell['catchable_pokemons']:
                with open(user_web_catchable, 'w') as outfile:
                    json.dump(pokemon, outfile)

                if self.catch_pokemon(pokemon) == PokemonCatchWorker.NO_POKEBALLS:
                    break
                with open(user_web_catchable, 'w') as outfile:
                    json.dump({}, outfile)

        if (self.config.mode == "all" or self.config.mode == "poke") and 'wild_pokemons' in cell and len(cell['wild_pokemons']) > 0:
            # Sort all by distance from current pos- eventually this should
            # build graph & A* it
            cell['wild_pokemons'].sort(key=lambda x: distance(self.position[0], self.position[1], x['latitude'], x['longitude']))
            for pokemon in cell['wild_pokemons']:
                if self.catch_pokemon(pokemon) == PokemonCatchWorker.NO_POKEBALLS:
                    break
        if include_fort_on_path:
            if 'forts' in cell:
                # Only include those with a lat/long
                forts = [fort for fort in cell['forts'] if 'latitude' in fort and 'type' in fort]
                # gyms = [gym for gym in cell['forts'] if 'gym_points' in gym]

                # Sort all by distance from current pos- eventually this should
                # build graph & A* it
                forts.sort(key=lambda x: distance(self.position[0], self.position[1], x['latitude'], x['longitude']))
                for fort in forts:
                    walk_worker = WalkTowardsFortWorker(fort, self)
                    walk_worker.work()

                    if self.config.mode == "all" or self.config.mode == "farm":
                        spinner_worker = SeenFortWorker(fort, self)
                        spinner_worker.work()

    def catch_pokemon(self, pokemon):
        catch_worker = PokemonCatchWorker(pokemon, self)
        return_value = catch_worker.work()

        if return_value == PokemonCatchWorker.BAG_FULL:
            transfer_worker = InitialTransferWorker(self)
            transfer_worker.work()

        return return_value

    def _work_on_forts(self, position, map_cells):
        forts = filtered_forts(position[0], position[1], sum([cell.get("forts", []) for cell in map_cells], []))
        if forts:
            walk_worker = WalkTowardsFortWorker(forts[0], self)
            walk_worker.work()

            spinner_worker = SeenFortWorker(forts[0], self)
            spinner_worker.work()

    def _remove_ignored_pokemon(self, map_cells):
        if self.process_ignored_pokemon:
            for cell in map_cells:
                wild_pokemons = cell.get('wild_pokemons')
                catchable_pokemons = cell.get('catchable_pokemons')
                if wild_pokemons is not None:
                    for pokemon in wild_pokemons[:]:
                        pokemon_id = pokemon['pokemon_data']['pokemon_id']
                        pokemon_name = [x for x in self.pokemon_list if int(x.get('Number')) == pokemon_id][0]['Name']

                        if pokemon_name in self.ignores:
                            wild_pokemons.remove(pokemon)
                if catchable_pokemons is not None:
                    for pokemon in catchable_pokemons[:]:
                        pokemon_id = pokemon['pokemon_id']
                        pokemon_name = [x for x in self.pokemon_list if int(x.get('Number')) == pokemon_id][0]['Name']

                        if pokemon_name in self.ignores:
                            catchable_pokemons.remove(pokemon)

    def _work_on_catchable_pokemon(self, map_cells):
        for cell in map_cells:
            if 'catchable_pokemons' in cell and len(cell['catchable_pokemons']) > 0:
                logger.log('[#] Something rustles nearby!')
                # Sort all by distance from current pos- eventually this should
                # build graph & A* it
                cell['catchable_pokemons'].sort(
                    key=lambda x: distance(self.position[0], self.position[1], x['latitude'], x['longitude']))
                for pokemon in cell['catchable_pokemons']:
                    with open('web/catchable-%s.json' % self.config.username, 'w') as outfile:
                        json.dump(pokemon, outfile)
                    worker = PokemonCatchWorker(pokemon, self)
                    if worker.work() == -1:
                        break
                    with open('web/catchable-%s.json' % self.config.username, 'w') as outfile:
                        json.dump({}, outfile)

    def _work_on_wild_pokemon(self, map_cells):
        for cell in map_cells:
            if 'wild_pokemons' in cell and len(cell['wild_pokemons']) > 0:
                # Sort all by distance from current pos- eventually this should
                # build graph & A* it
                cell['wild_pokemons'].sort(
                    key=lambda x: distance(self.position[0], self.position[1], x['latitude'], x['longitude']))
                for pokemon in cell['wild_pokemons']:
                    worker = PokemonCatchWorker(pokemon, self)
                    if worker.work() == -1:
                        break

    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)

    @staticmethod
    def same_minute(current_time, last_time):

        # Time Structure
        # (tm_year=2016, tm_mon=7, tm_mday=28, tm_hour=9, tm_min=26, tm_sec=57, tm_wday=3, tm_yday=210, tm_isdst=0)

        current_time_list = [
            current_time.tm_year,
            current_time.tm_mon,
            current_time.tm_mday,
            current_time.tm_hour,
            current_time.tm_min
        ]

        last_time_list = [
            last_time.tm_year,
            last_time.tm_mon,
            last_time.tm_mday,
            last_time.tm_hour,
            last_time.tm_min
        ]
        return bool(current_time_list == last_time_list)

    # noinspection PyProtectedMember
    def check_session(self):
        # Check session expiry
        remaining_time = None
        current = time.gmtime()

        # pylint: disable=protected-access
        if self.api._auth_provider and self.api._auth_provider._ticket_expire:
            remaining_time = self.api._auth_provider._ticket_expire / 1000 - time.time()
        if remaining_time is not None and remaining_time < 30:
            logger.log("[X] Session stale, re-logging in", 'red')
            self.login()

        if not self.same_minute(current, self.last_session_check):
            self.last_session_check = current
            remaining_time_string = str(datetime.timedelta(seconds=remaining_time))
            logger.log("[#] Remaining Session Time: %s" % remaining_time_string, 'yellow')

    def login(self):
        logger.log('[#] Attempting login to Pokemon Go.', 'white')
        self.api.set_position(*self.position)

        while not self.api.login(self.config.auth_service, str(self.config.username), str(self.config.password)):
            logger.log('[X] Login Error, server busy', 'red')
            logger.log('[X] Waiting 10 seconds to try again', 'red')
            time.sleep(10)

        logger.log('[+] Login to Pokemon Go successful.', 'green')
        self.api.get_player()
        response_dict = self.api.call()
        try:
            player = response_dict['responses']['GET_PLAYER']['player_data']
            self.print_player_data(player)
            self.get_player_info()
        except TypeError:
            logger.log("[X] Unable to parse player object from API", 'red')
            logger.log("Forced Exit!", 'red')
            exit(1)

    def _setup_api(self):
        # instantiate pgoapi
        self.api = PGoApi()
        # provide player position on the earth

        self._set_starting_position()

        if not self.api.login(self.config.auth_service,
                              str(self.config.username),
                              str(self.config.password)):
            logger.log('Login Error, server busy', 'red')
            exit(0)

        # chain subrequests (methods) into one RPC call

        # get player profile call
        # ----------------------
        self.api.get_player()

        response_dict = self.api.call()
        if response_dict is not None:
            # print('Response dictionary: \n\r{}'.format(json.dumps(response_dict, indent=2)))
            try:
                player = response_dict['responses']['GET_PLAYER']['player_data']
                self.print_player_data(player)
                self.get_player_info()
            except TypeError:
                logger.log("[X] Unable to parse player object from API: %s", 'red')
                logger.log("Forced Exit!", 'red')
                exit(1)
        # Testing
        # self.drop_item(Item.ITEM_POTION.value,1)
        # exit(0)

        if self.config.initial_transfer:
            worker = InitialTransferWorker(self)
            worker.work()

        if self.config.recycle_items:
            recycle_worker = RecycleItemsWorker(self)
            recycle_worker.work()

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

    def print_player_data(self, player):
        # @@@ TODO: Convert this to d/m/Y H:M:S
        creation_date = datetime.datetime.fromtimestamp(
            player['creation_timestamp_ms'] / 1e3)

        balls_stock = self.pokeball_inventory()

        pokecoins = player['currencies'][0].get('amount', '0')
        stardust = player['currencies'][1].get('amount', '0')

        logger.log('[#]')
        logger.log('[#] Username: {username}'.format(**player))
        logger.log('[#] Account Creation: {}'.format(creation_date))
        logger.log('[#] Bag Storage: {}/{}'.format(
            self.get_inventory_count('item'),
            player['max_item_storage']))
        logger.log('[#] Pokemon Storage: {}/{}'.format(
            self.get_inventory_count('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]))

    def _setup_ignored_pokemon(self):
        pass
        # try:
        #     with open("./data/catch-ignore.yml", 'r') as ignore_file:
        #         self.ignores = yaml.load(ignore_file)['ignore']
        #         if len(self.ignores) > 0:
        #             self.process_ignored_pokemon = True
        # except Exception:
        #     pass

    def drop_item(self, item_id, count):
        self.api.recycle_inventory_item(item_id=item_id, count=count)
        self.api.call()

    def update_inventory(self):
        self.api.get_inventory()
        response = self.api.call()
        self.inventory = list()
        inventory_items = response.get('responses', {}).get('GET_INVENTORY', {}).get('inventory_delta', {}).get('inventory_items')
        if inventory_items is None:
            return
        for item in inventory_items:
            item_data = item.get('inventory_item_data', {}).get('item')
            if item_data is None or 'item_id' not in item_data or 'count' not in item_data:
                continue
            self.inventory.append(item_data)

    def pokeball_inventory(self):
        self.api.get_player().get_inventory()

        inventory_req = self.api.call()
        inventory_list = convert_to_utf8(inventory_req['responses']['GET_INVENTORY']['inventory_delta']['inventory_items'])
        with open('web/inventory-{}.json'.format(self.config.username), 'w') as outfile:
            json.dump(inventory_list, outfile)

        # get player balls stock
        # ----------------------
        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}

        for item in inventory_list:
            item_data = item.get('inventory_item_data', {}).get('item')
            if item_data is None:
                continue
            if "item_id" in item_data and "count" in item_data:
                item_id = int(item_data['item_id'])
                item_count = int(item_data['count'])
                if item_id in balls_stock:
                    balls_stock[item_id] = item_count
        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.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.set_position(*self.position)
        logger.log('')
        logger.log(u'[x] Address found: {}'.format(self.config.location))

    def _get_pos_by_name(self, location_name):
        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.get_player()
        self.api.get_hatched_eggs()
        self.api.get_inventory()
        self.api.check_awarded_badges()
        self.api.call()

    def get_inventory_count(self, what):
        self.api.get_inventory()
        response_dict = self.api.call()

        if response_dict is None:
            return 0
        pokecount = 0
        itemcount = 1
        inventory_items = response_dict.get('responses', {}).get('GET_INVENTORY', {}).get('inventory_delta', {}).get('inventory_items')
        if inventory_items is None:
            return 0
        for item in inventory_items:
            if 'inventory_item_data' in item:
                item_data = item['inventory_item_data']
                if 'pokemon_data' in item_data:
                    pokecount += 1
                if 'item' in item_data and 'count' in item_data['item']:
                    itemcount += item_data['item']['count']

        if 'pokemon' in what:
            return pokecount
        if 'item' in what:
            return itemcount
        return 0

    def get_player_info(self):
        self.api.get_inventory()
        response_dict = self.api.call()
        if response_dict is None:
            logger.log("Couldn't get player info!", "red")
            return
        inventory_items = inventory_items = response_dict.get('responses', {}).get('GET_INVENTORY', {}).get('inventory_delta', {}).get('inventory_items')
        if inventory_items is None:
            return
        for item in inventory_items:
            if item.get("inventory_item_data", {}).get("player_stats") is None:
                continue
            player_stats = item['inventory_item_data']['player_stats']

            if 'experience' not in player_stats:
                player_stats['experience'] = 0

            if 'level' in player_stats:
                logger.log('[#] -- Level: {level}'.format(**player_stats))

            if 'next_level_xp' in player_stats:
                nextlvlxp = int(player_stats['next_level_xp']) - int(player_stats['experience'])
                logger.log('[#] -- Experience: {experience}'.format(**player_stats))
                logger.log('[#] -- Experience until next level: {}'.format(nextlvlxp))

            if 'pokemons_captured' in player_stats:
                logger.log('[#] -- Pokemon Captured: {pokemons_captured}'.format(**player_stats))

            if 'poke_stop_visits' in player_stats:
                logger.log('[#] -- Pokestops Visited: {poke_stop_visits}'.format(**player_stats))
Esempio n. 22
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"]
Esempio n. 23
0
class PokemonGoBot(object):
    process_ignored_pokemon = False

    def __init__(self, config):
        self.config = config
        self.item_list = json.load(open('data/items.json'))
        self.pokemon_list = json.load(open('data/pokemon.json'))

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

    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))

    def start(self):
        self._setup_logging()
        self._init_plugins()
        self._setup_api()
        self._setup_ignored_pokemon()
        self.stepper = Stepper(self)
        random.seed()

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

    def take_step(self):
        self.stepper.take_step()

    def work_on_cell(self, cell, include_fort_on_path):
        # type: (Cell, bool) -> None

        self.fire("pokemon_found", pokemon=cell.catchable_pokemon + cell.wild_pokemon)

        self._remove_ignored_pokemon(cell)

        if self.config.mode in ["all", "poke"]:
            pass

        if (self.config.mode == "all" or self.config.mode == "poke") and len(cell.catchable_pokemon) > 0:
            logger.log('[#] Something rustles nearby!')
            # Sort all by distance from current pos- eventually this should
            # build graph & A* it
            cell.catchable_pokemon.sort(key=lambda x: x.get("time_until_hidden_ms", 0))
            for pokemon in cell.catchable_pokemon:
                if self.catch_pokemon(pokemon) == PokemonCatchWorker.NO_POKEBALLS:
                    break

        if (self.config.mode == "all" or self.config.mode == "poke") and len(cell.wild_pokemon) > 0:
            # Sort all by distance from current pos- eventually this should
            # build graph & A* it
            # cell.wild_pokemon.sort(key=lambda x: distance(self.position[0], self.position[1], x['latitude'], x['longitude']))
            cell.wild_pokemon.sort(key=lambda x: x.get("time_until_hidden_ms", 0))
            for pokemon in cell.wild_pokemon:
                if self.catch_pokemon(pokemon) == PokemonCatchWorker.NO_POKEBALLS:
                    break
        if include_fort_on_path:
            # Only include those with a lat/long
            pokestops = [pokestop for pokestop in cell.pokestops if
                         pokestop.latitude is not None and pokestop.longitude is not None]
            # gyms = [gym for gym in cell['forts'] if 'gym_points' in gym]

            # Sort all by distance from current pos- eventually this should
            # build graph & A* it
            pokestops.sort(key=lambda x: distance(self.position[0], self.position[1], x.latitude, x.longitude))
            for pokestop in pokestops:
                walk_worker = WalkTowardsFortWorker(pokestop, self)
                walk_worker.work()

                if self.config.mode == "all" or self.config.mode == "farm":
                    spinner_worker = SeenFortWorker(pokestop, self)
                    spinner_worker.work()

    def catch_pokemon(self, pokemon):
        # type: (Pokemon) -> str
        catch_worker = PokemonCatchWorker(pokemon, self)
        return_value = catch_worker.work()

        if return_value == PokemonCatchWorker.BAG_FULL:
            self.fire("pokemon_bag_full")

        return return_value

    def _work_on_forts(self, position, map_cells):
        # type: (Tuple[float, float], List[Cell]) -> None
        forts = filtered_forts(position[0], position[1], sum([cell.pokestops for cell in map_cells], []))
        if forts:
            walk_worker = WalkTowardsFortWorker(forts[0], self)
            walk_worker.work()

            spinner_worker = SeenFortWorker(forts[0], self)
            spinner_worker.work()

    def _remove_ignored_pokemon(self, cell):
        # type: (Cell) -> None
        if self.process_ignored_pokemon:
            wild_pokemons = cell.wild_pokemon
            catchable_pokemons = cell.catchable_pokemon
            for pokemon in wild_pokemons[:]:
                pokemon_id = pokemon['pokemon_data']['pokemon_id']
                pokemon_name = [x for x in self.pokemon_list if int(x.get('Number')) == pokemon_id][0]['Name']

                if pokemon_name in self.ignores:
                    wild_pokemons.remove(pokemon)

            for pokemon in catchable_pokemons[:]:
                pokemon_id = pokemon['pokemon_id']
                pokemon_name = [x for x in self.pokemon_list if int(x.get('Number')) == pokemon_id][0]['Name']

                if pokemon_name in self.ignores:
                    catchable_pokemons.remove(pokemon)

    def _work_on_catchable_pokemon(self, map_cells):
        # type: (List[Cell]) -> None
        for cell in map_cells:
            catchable_pokemon = cell.catchable_pokemon
            if len(catchable_pokemon) > 0:
                logger.log('[#] Something rustles nearby!')
                # Sort all by distance from current pos- eventually this should
                # build graph & A* it
                catchable_pokemon.sort(
                    key=lambda x: distance(self.position[0], self.position[1], x['latitude'], x['longitude']))
                for pokemon in catchable_pokemon:
                    with open('web/catchable-%s.json' % self.config.username, 'w') as outfile:
                        json.dump(pokemon, outfile)
                    worker = PokemonCatchWorker(pokemon, self)
                    if worker.work() == -1:
                        break
                    with open('web/catchable-%s.json' % self.config.username, 'w') as outfile:
                        json.dump({}, outfile)

    def _work_on_wild_pokemon(self, map_cells):
        for cell in map_cells:
            if 'wild_pokemons' in cell and len(cell['wild_pokemons']) > 0:
                # Sort all by distance from current pos- eventually this should
                # build graph & A* it
                cell['wild_pokemons'].sort(
                    key=lambda x: distance(self.position[0], self.position[1], x['latitude'], x['longitude']))
                for pokemon in cell['wild_pokemons']:
                    worker = PokemonCatchWorker(pokemon, self)
                    if worker.work() == -1:
                        break

    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)

    @staticmethod
    def same_minute(current_time, last_time):

        # Time Structure
        # (tm_year=2016, tm_mon=7, tm_mday=28, tm_hour=9, tm_min=26, tm_sec=57, tm_wday=3, tm_yday=210, tm_isdst=0)

        current_time_list = [
            current_time.tm_year,
            current_time.tm_mon,
            current_time.tm_mday,
            current_time.tm_hour,
            current_time.tm_min
        ]

        last_time_list = [
            last_time.tm_year,
            last_time.tm_mon,
            last_time.tm_mday,
            last_time.tm_hour,
            last_time.tm_min
        ]
        return bool(current_time_list == last_time_list)

    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(len(inventory), 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:
            recycle_worker = RecycleItemsWorker(self)
            recycle_worker.work()

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

    def _setup_ignored_pokemon(self):
        pass
        # try:
        #     with open("./data/catch-ignore.yml", 'r') as ignore_file:
        #         self.ignores = yaml.load(ignore_file)['ignore']
        #         if len(self.ignores) > 0:
        #             self.process_ignored_pokemon = True
        # except Exception:
        #     pass

    def drop_item(self, item_id, count):
        self.api_wrapper.recycle_inventory_item(item_id=item_id, count=count)
        self.api_wrapper.call()

    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 len(response_dict["inventory"])
Esempio n. 24
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.inventory = []
        self.candies = {}
        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")
        if self.config.print_events:
            logger.log("Events available: {}".format(manager.get_registered_events()), color="green", prefix="Events")
            manager.print_all_event_pipelines()

    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()

    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)

        for destination in self.navigator.navigate(map_cells):
            position_lat = self.stepper.current_lat
            position_lng = self.stepper.current_lng

            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()
                )

    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, shared_lib=self.config.load_library)
        # 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']
            self.candies = response_dict['candy']
            pokemon = response_dict['pokemon']
            eggs = response_dict['eggs']
            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) + len(eggs), player.max_pokemon_storage))
            logger.log('[#] Stardust: {:,}'.format(stardust))
            logger.log('[#] Pokecoins: {}'.format(pokecoins))
            logger.log('[#] Poke Balls: {}'.format(balls_stock[1]))
            logger.log('[#] Great Balls: {}'.format(balls_stock[2]))
            logger.log('[#] Ultra Balls: {}'.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)

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

    def add_candies(self, name=None, pokemon_candies=None):
        for pokemon in self.pokemon_list:
            if pokemon['Name'] is not name:
                continue
            else:
                previous_evolutions = pokemon.get("Previous evolution(s)", [])
                if previous_evolutions:
                    candy_name = previous_evolutions[0]['Number']
                else:
                    candy_name = pokemon.get("Number")

                if self.candies.get(candy_name, None) is not None:
                    self.candies[candy_name] += pokemon_candies
                else:
                    self.candies[candy_name] = pokemon_candies
                logger.log("[#] Added {} candies for {}".format(pokemon_candies,
                                                                self.pokemon_list[int(candy_name) - 1]['Name']), 'green')
                break

    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"]

    def get_username(self):
        # type: () -> str
        response_dict = self.update_player_and_inventory()
        if response_dict is None:
            return "Unknown"
        return response_dict["player"].username

    def get_position(self):
        return self.position
Esempio n. 25
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.stepper = None
        self.api_wrapper = None
        self.ignores = []
        self.position = (0, 0, 0)
        self.plugin_manager = None
        self.last_session_check = time.gmtime()

    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))

        loaded_plugins = sorted(self.plugin_manager.get_loaded_plugins().keys())
        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()
        self._setup_ignored_pokemon()
        self.stepper = Stepper(self)
        random.seed()

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

    def take_step(self):
        self.stepper.take_step()

    def work_on_cell(self, cell):
        # type: (Cell, bool) -> None

        self.fire("pokemon_found", encounters=cell.catchable_pokemon + cell.wild_pokemon)

        # TODO: Refactor WalkTowardsFortWorker
        # self.fire("pokestops_found", pokestops=cell.pokestops)

        pokestops = filtered_forts(self.position[0], self.position[1], cell.pokestops)

        for pokestop in pokestops:
            walk_worker = WalkTowardsFortWorker(pokestop, self)
            walk_worker.work()

            self.fire("pokestop_arrived", pokestop=pokestop)

    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)

    @staticmethod
    def same_minute(current_time, last_time):

        # Time Structure
        # (tm_year=2016, tm_mon=7, tm_mday=28, tm_hour=9, tm_min=26, tm_sec=57, tm_wday=3, tm_yday=210, tm_isdst=0)

        current_time_list = [
            current_time.tm_year,
            current_time.tm_mon,
            current_time.tm_mday,
            current_time.tm_hour,
            current_time.tm_min
        ]

        last_time_list = [
            last_time.tm_year,
            last_time.tm_mon,
            last_time.tm_mday,
            last_time.tm_hour,
            last_time.tm_min
        ]
        return bool(current_time_list == last_time_list)

    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 _setup_ignored_pokemon(self):
        pass
        # try:
        #     with open("./data/catch-ignore.yml", 'r') as ignore_file:
        #         self.ignores = yaml.load(ignore_file)['ignore']
        #         if len(self.ignores) > 0:
        #             self.process_ignored_pokemon = True
        # except Exception:
        #     pass

    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"]