예제 #1
0
    def _parse_responses(self, responses):
        for response_type in responses.keys():
            response = responses[response_type]

            if response_type == 'GET_INBOX':
                self._parse_inbox_response(response)
                del responses[response_type]

            elif response_type == 'GET_HOLO_INVENTORY':
                api_inventory = response

                # Set an (empty) inventory if necessary
                if self.inventory is None:
                    self.inventory = {}

                # Update inventory (balls, items)
                self._parse_inventory_delta(api_inventory)
                self._update_inventory_totals()

                # Update last timestamp for inventory requests
                self._last_timestamp_ms = api_inventory.inventory_delta.new_timestamp_ms

                # Clean up
                del responses[response_type]

            # Get settings hash from response for future calls
            elif response_type == 'DOWNLOAD_SETTINGS':
                if response.hash:
                    self._download_settings_hash = response.hash
                # TODO: Check forced client version and exit program if different

                # Clean up
                del responses[response_type]

            elif response_type == 'GET_PLAYER':
                self._player_state = {
                    'tutorial_state': response.player_data.tutorial_state,
                    'buddy': response.player_data.buddy_pokemon.id,
                    'warn': response.warn,
                    'banned': response.banned
                }

                # Clean up
                del responses[response_type]

                if self._player_state['banned']:
                    self.log_warning("GET_PLAYER has the 'banned' flag set.")
                    raise BannedAccountException

            # Check for captcha
            elif response_type == 'CHECK_CHALLENGE':
                self.captcha_url = response.challenge_url

                # Clean up
                del responses[response_type]

                if self.has_captcha() and self.cfg['exception_on_captcha']:
                    raise CaptchaException

            elif response_type == 'GET_MAP_OBJECTS':
                if is_rareless_scan(response):
                    if self.rareless_scans is None:
                        self.rareless_scans = 1
                    else:
                        self.rareless_scans += 1
                else:
                    self.rareless_scans = 0

            elif response_type == 'GET_HATCHED_EGGS':
                if self.callback_egg_hatched and response.success and len(
                        response.hatched_pokemon) > 0:
                    for i in range(0, len(response.pokemon_id)):
                        hatched_egg = {
                            'experience_awarded':
                            response.experience_awarded[i],
                            'candy_awarded': response.candy_awarded[i],
                            'stardust_awarded': response.stardust_awarded[i],
                            'egg_km_walked': response.egg_km_walked[i],
                            'hatched_pokemon': response.hatched_pokemon[i]
                        }
                        self.callback_egg_hatched(self, hatched_egg)
예제 #2
0
def search_worker(args, scheduler, enc_list):
    #scheduler = Scheduler(args)
    details = account_queue.get()
    initial_location = scheduler.next_item(details)
    #log.info(str(initial_location))
    details['latitude'] = initial_location[0]
    details['longitude'] = initial_location[1]
    try:
        api = create_api(args, details, initial_location)
        #api.log_info('Setting up at {}, {}.'.format(initial_location[0],
        # initial_location[1]))
        last_action = datetime.utcnow()
        #log.info('Setting last action')
        rareless_scan_count = 0
        #log.info('Setting rareless scans count')
        if not api.is_logged_in():
            log.error('Account {} not logged in.'.format(api.username))
            return

        if api.is_banned():
            log.error('Account {} banned.'.format(api.username))
            return

        if api.has_captcha():
            log.error('Account {} CAPTCHA\'d.'.format(api.username))
            return

        api.log_info('Level: {} ({} / {} XP), Pokestops spun: {}, Pokemon '
                     'caught: {}, KM Walked: {}'.format(
                         api.get_stats('level', 1),
                         api.get_stats('experience', 0),
                         api.get_stats('next_level_xp', 0),
                         api.get_stats('poke_stop_visits', 0),
                         api.get_stats('pokemons_captured', 0),
                         api.get_stats('km_walked', 0.)))
    except Exception as e:
        log.error(repr(e))
        return

    while True:
        #log.info('Pulling location')
        loc = scheduler.next_item(details)
        #log.info('Pulled location')
        #log.info(str(loc))
        gp = geopy.Point(loc[0], loc[1])
        now_date = datetime.utcnow()
        meters = geopy.distance.vincenty(loc, (api.latitude, api.longitude))\
            .meters
        secs_to_arrival = meters / float(args.kph) * 3.6
        secs_waited = (now_date - last_action).total_seconds()
        secs_to_arrival = max(secs_to_arrival - secs_waited, 0)
        api.log_info('Moving to {} (will take {} seconds to travel)'.format(
            gp.format_decimal(), round(secs_to_arrival, 2)))
        #log.info('{} seconds to arrive'.format(secs_to_arrival))
        sleep(secs_to_arrival)
        api.set_position(loc[0], loc[1], 0)
        details['latitude'] = loc[0]
        details['longitude'] = loc[1]
        gmo = api.req_get_map_objects()['GET_MAP_OBJECTS']

        try:
            weather_info = gmo.client_weather[0]

            # NONE (0)
            # CLEAR (1)
            # RAINY (2)
            # PARTLY_CLOUDY (3)
            # OVERCAST (4)
            # WINDY (5)
            # SNOW (6)
            # FOG (7)
            condition = weather_info.gameplay_weather.gameplay_condition
        except Exception:
            condition = 0

        cells = gmo.map_cells
        rareless = is_rareless_scan(gmo)
        if rareless:
            rareless_scan_count += 1

        if not rareless:
            rareless_scan_count = 0

        if rareless_scan_count > 10:
            log.warning(
                'Account {} may be shadowbanned. {} scans without rare '
                'Pokemon.'.format(api.username, rareless_scan_count))

        if rareless_scan_count >= 25:
            # Die.
            log.error(
                'Account {} is shadowbanned. {} scans without rare Pokemon. Exiting.'
                .format(api.username, rareless_scan_count))
            return

        last_action = datetime.utcnow()
        counts = {'pokemon': 0, 'nearby': 0, 'raids': 0, 'forts': 0}

        for cell in cells:
            counts['nearby'] += len(cell.nearby_pokemons)

            for f in cell.forts:
                counts['forts'] += 1
                if f.raid_info.raid_level != 0:
                    counts['raids'] += 1
                    raid = f.raid_info
                    if raid.raid_battle_ms > now_ms():
                        dbq.put((Raid, {
                            'raid_seed':
                            raid.raid_seed,
                            'gym_id':
                            f.id,
                            'spawn':
                            datetime.fromtimestamp(raid.raid_spawn_ms / 1000),
                            'start':
                            datetime.fromtimestamp(raid.raid_battle_ms / 1000),
                            'end':
                            datetime.fromtimestamp(raid.raid_end_ms / 1000),
                            'level':
                            raid.raid_level,
                            'pokemon_id':
                            None,
                            'cp':
                            None,
                            'move_1':
                            None,
                            'move_2':
                            None,
                            'latitude':
                            f.latitude,
                            'longitude':
                            f.longitude
                        }))
                    else:
                        dbq.put((Raid, {
                            'raid_seed':
                            raid.raid_seed,
                            'gym_id':
                            f.id,
                            'spawn':
                            datetime.fromtimestamp(raid.raid_spawn_ms / 1000),
                            'start':
                            datetime.fromtimestamp(raid.raid_battle_ms / 1000),
                            'end':
                            datetime.fromtimestamp(raid.raid_end_ms / 1000),
                            'level':
                            raid.raid_level,
                            'pokemon_id':
                            raid.raid_pokemon.pokemon_id,
                            'cp':
                            raid.raid_pokemon.cp,
                            'move_1':
                            raid.raid_pokemon.move_1,
                            'move_2':
                            raid.raid_pokemon.move_2,
                            'latitude':
                            f.latitude,
                            'longitude':
                            f.longitude
                        }))

            for p in cell.wild_pokemons:
                counts['pokemon'] += 1
                spawn = SpawnPoint.find_spawn(p.spawn_point_id, p.latitude,
                                              p.longitude)
                disappear = calculate_disappear(p, spawn)

                if p.pokemon_data.pokemon_id in DITTO_IDS and args.ditto_detection:
                    api.log_info('Trying to check a Ditto at {}, {}.'.format(
                        p.latitude, p.longitude))

                    enc = api.req_encounter(encounter_id=p.encounter_id,
                                            spawn_point_id=p.spawn_point_id,
                                            latitude=p.latitude,
                                            longitude=p.longitude)['ENCOUNTER']

                    if enc.status == 1:
                        i = 0
                        while i < 5:
                            api.log_info('Catch attempt #{}.'.format(i + 1))
                            catch = api.req_catch_pokemon(
                                encounter_id=p.encounter_id,
                                spawn_point_id=p.spawn_point_id,
                                normalized_reticle_size=1.95,
                                spin_modifier=1.,
                                ball=1)['CATCH_POKEMON']

                            if catch.status == 1:
                                api.log_info(
                                    'Pokemon caught. (ID: {}, CP: {}, IV: {})'.
                                    format(
                                        api.last_caught_pokemon['pokemon_id'],
                                        api.last_caught_pokemon['cp'],
                                        get_iv(api.last_caught_pokemon)))
                                if api.last_caught_pokemon[
                                        'pokemon_id'] == 132:
                                    api.log_info(
                                        'Ditto found at {}, {}!'.format(
                                            p.latitude, p.longitude))
                                    try:
                                        dbq.put((Pokemon, {
                                            'encounter_id':
                                            b64_e(p.encounter_id),
                                            'spawnpoint_id':
                                            p.spawn_point_id,
                                            'pokemon_id':
                                            132,
                                            'latitude':
                                            p.latitude,
                                            'longitude':
                                            p.longitude,
                                            'disappear_time':
                                            disappear,
                                            'gender':
                                            api.last_caught_pokemon['gender'],
                                            'form':
                                            api.last_caught_pokemon['form'],
                                            'disguise':
                                            p.pokemon_data.pokemon_id,
                                            'weather':
                                            condition
                                        }))
                                    except Exception as e:
                                        log.error(repr(e))
                                    break

                                else:
                                    api.log_info('Not a Ditto.')
                                    try:
                                        dbq.put((Pokemon, {
                                            'encounter_id':
                                            b64_e(p.encounter_id),
                                            'spawnpoint_id':
                                            p.spawn_point_id,
                                            'pokemon_id':
                                            p.pokemon_data.pokemon_id,
                                            'latitude':
                                            p.latitude,
                                            'longitude':
                                            p.longitude,
                                            'disappear_time':
                                            disappear,
                                            'gender':
                                            p.pokemon_data.pokemon_display.
                                            gender,
                                            'form':
                                            p.pokemon_data.pokemon_display.
                                            form,
                                            'weather':
                                            condition
                                        }))
                                    except Exception as e:
                                        log.error(repr(e))

                                    break

                            elif catch.status == 3:
                                try:
                                    dbq.put((Pokemon, {
                                        'encounter_id':
                                        b64_e(p.encounter_id),
                                        'spawnpoint_id':
                                        p.spawn_point_id,
                                        'pokemon_id':
                                        p.pokemon_data.pokemon_id,
                                        'latitude':
                                        p.latitude,
                                        'longitude':
                                        p.longitude,
                                        'disappear_time':
                                        disappear,
                                        'gender':
                                        p.pokemon_data.pokemon_display.gender,
                                        'form':
                                        p.pokemon_data.pokemon_display.form,
                                        'weather':
                                        condition
                                    }))
                                except Exception as e:
                                    log.error(repr(e))
                                break

                            elif catch.status not in [1, 3]:
                                sleep(0.1)
                                i += 1
                                if i > 5:
                                    break

                if p.pokemon_data.pokemon_id in enc_list:
                    scout = pgscout_encounter(p, args)
                    try:
                        dbq.put((Pokemon, {
                            'encounter_id':
                            b64_e(p.encounter_id),
                            'spawnpoint_id':
                            p.spawn_point_id,
                            'pokemon_id':
                            p.pokemon_data.pokemon_id,
                            'latitude':
                            p.latitude,
                            'longitude':
                            p.longitude,
                            'disappear_time':
                            disappear,
                            'gender':
                            p.pokemon_data.pokemon_display.gender,
                            'form':
                            p.pokemon_data.pokemon_display.form,
                            'iv_attack':
                            scout.get('iv_attack', None),
                            'iv_defense':
                            scout.get('iv_defense', None),
                            'iv_stamina':
                            scout.get('iv_stamina', None),
                            'move_1':
                            scout.get('move_1', None),
                            'move_2':
                            scout.get('move_2', None),
                            'cp':
                            scout.get('cp', None),
                            'cp_multiplier':
                            scout.get('cp_multiplier', None),
                            'level':
                            scout.get('level', None),
                            'height':
                            scout.get('height', None),
                            'weight':
                            scout.get('weight', None),
                            'weather':
                            condition
                        }))
                    except Exception as e:
                        log.error(repr(e))
                else:
                    try:
                        dbq.put((Pokemon, {
                            'encounter_id': b64_e(p.encounter_id),
                            'spawnpoint_id': p.spawn_point_id,
                            'pokemon_id': p.pokemon_data.pokemon_id,
                            'latitude': p.latitude,
                            'longitude': p.longitude,
                            'disappear_time': disappear,
                            'gender': p.pokemon_data.pokemon_display.gender,
                            'form': p.pokemon_data.pokemon_display.form,
                            'weather': condition
                        }))
                    except Exception as e:
                        log.error(repr(e))

            for f in cell.forts:
                dist = geopy.distance.vincenty(
                    (api.latitude, api.longitude),
                    (f.latitude, f.longitude)).kilometers
                if dist <= 0.04 and f.type == 1 and f.enabled and args.spin_pokestops:
                    api.log_info('Spinning a Pokestop at {}, {}.'.format(
                        f.latitude, f.longitude))
                    api.seq_spin_pokestop(f.id, f.latitude, f.longitude,
                                          api.latitude, api.longitude)

                # DON'T LET NIANTIC THROTTLE. *SWEATING*
                sleep(random.random())

        api.log_info(
            'Parse at {} returned {} Pokemon ({} nearby), {} forts and {} raids.'
            .format(gp.format_decimal(), counts['pokemon'], counts['nearby'],
                    counts['forts'], counts['raids']))
        # Other shit.
        # details['inventory_ts'] = api._item_templates_time
        # details['ds_hash'] = api._download_settings_hash
        scheduler.item_done(loc)