def load_pgpool_accounts(count, reuse=False): addl_text = " Reusing previous accounts." if reuse else "" log.info("Trying to load {} accounts from PGPool.{}".format( count, addl_text)) if count == 1: accounts = {} else: accounts = [] for x in range(count): if (not 'auth_service' in load_pgpool_accounts.PreviousAccount) or ( load_pgpool_accounts.AccUsed >= 3): request = { 'system_id': cfg_get('pgpool_system_id'), 'count': 1, 'min_level': cfg_get('level'), 'reuse': reuse } r = requests.get("{}/account/request".format( cfg_get('pgpool_url')), params=request) load_pgpool_accounts.PreviousAccount = r.json() load_pgpool_accounts.AccUsed = 0 accounts.append(r.json()) else: load_pgpool_accounts.AccUsed += 1 accounts.append(load_pgpool_accounts.PreviousAccount) return accounts
def load_accounts(jobs): accounts_file = cfg_get('accounts_file') accounts = [] if accounts_file: log.info("Loading accounts from file {}.".format(accounts_file)) with open(accounts_file, 'r') as f: for num, line in enumerate(f, 1): fields = line.split(",") fields = map(str.strip, fields) accounts.append( ScoutGuard(fields[0], fields[1], fields[2], jobs)) elif cfg_get('pgpool_url') and cfg_get( 'pgpool_system_id') and cfg_get('pgpool_num_accounts') > 0: acc_json = load_pgpool_accounts(cfg_get('pgpool_num_accounts'), reuse=True) if isinstance(acc_json, dict): acc_json = [acc_json] if len(acc_json) > 0: log.info("Loaded {} accounts from PGPool.".format(len(acc_json))) for acc in acc_json: accounts.append( ScoutGuard(acc['auth_service'], acc['username'], acc['password'], jobs)) if len(accounts) == 0: log.error("Could not load any accounts. Nothing to do. Exiting.") sys.exit(1) return accounts
def get_iv(): if not app_state.accept_new_requests: return reject('Not accepting new requests.') if not have_active_scouts(): return reject('No active scout available. All banned?') pokemon_id = request.args["pokemon_id"] pokemon_name = get_pokemon_name(pokemon_id) forced = request.args.get('forced') prio = PRIO_HIGH if forced is not None else get_pokemon_prio(pokemon_id) cache_enable = cfg_get('cache_timer') > 0 max_queued_jobs = cfg_get('max_queued_jobs') num_jobs = jobs.qsize() if max_queued_jobs and num_jobs >= max_queued_jobs and prio == PRIO_LOW: return reject( "Job queue full ({} items). Rejecting encounter with priority '{}'." .format(num_jobs, PRIO_NAMES[prio])) lat = request.args["latitude"] lng = request.args["longitude"] weather = request.args.get("weather", "unknown") encounter_id = normalize_encounter_id(request.args.get("encounter_id")) # Spawn point ID is assumed to be a hex string spawn_point_id = request.args.get("spawn_point_id") despawn_time = request.args.get("despawn_time") if cache_enable: # Check cache cache_key = "{}-{}".format( encounter_id, weather) if encounter_id else "{}-{}-{}".format( pokemon_id, lat, lng) result = get_cached_encounter(cache_key) if result: log.info( u"Returning cached result: {:.1f}% level {} {} with {} CP". format(result['iv_percent'], result['level'], pokemon_name, result['cp'])) return jsonify(result) # Create a ScoutJob job = ScoutJob(pokemon_id, encounter_id, spawn_point_id, lat, lng, despawn_time=despawn_time) # Enqueue and wait for job to be processed jobs.put((prio, time.time(), job)) while not job.processed: time.sleep(1) # Cache successful jobs and return result if cache_enable and job.result['success']: cache_encounter(cache_key, job.result) return jsonify(job.result)
def run(self): self.log_info("Waiting for job...") while True: (prio, t, job) = self.job_queue.get() try: if job.expired(): self.log_warning( u"Scout job for {} at {}, {} expired. Rejecting.".format(job.pokemon_name, job.lat, job.lng)) job.result = self.scout_error(self.last_msg) continue self.log_info(u"Scouting a {} at {}, {} with {} priority".format(job.pokemon_name, job.lat, job.lng, PRIO_NAMES[prio])) # Initialize API (lat, lng) = jitter_location(job.lat, job.lng) self.set_position(lat, lng, job.altitude) if not self.check_login(): job.result = self.scout_error(self.last_msg) if self.is_banned() or self.has_captcha(): if cfg_get('discord_webhook'): self.post_discord_webhook(banned=True) break else: continue if job.encounter_id and job.spawn_point_id: job.result = self.scout_by_encounter_id(job) else: if self.find_pokemon(job): time.sleep(2) job.result = self.scout_by_encounter_id(job) else: job.result = self.scout_error("Could not determine encounter_id for {} at {}, {}".format(job.pokemon_name, job.lat, job.lng)) # Mark shadowbanned if too many errors sb_threshold = cfg_get('shadowban_threshold') if sb_threshold and self.errors >= sb_threshold: self.shadowbanned = True if self.shadowbanned: self.log_warning("Account probably shadowbanned. Stopping.") if cfg_get('discord_webhook'): self.post_discord_webhook(shadowbanned=True) break except (AuthException, BannedAccountException, CaptchaException) as e: job.result = self.scout_error(self.last_msg) if cfg_get('discord_webhook'): self.post_discord_webhook(banned=True) break except Exception: job.result = self.scout_error(repr(sys.exc_info())) finally: job.processed = True
def load_pgpool_accounts(count, reuse=False): addl_text = " Reusing previous accounts." if reuse else "" log.info("Trying to load {} accounts from PGPool.{}".format(count, addl_text)) request = { 'system_id': cfg_get('pgpool_system_id'), 'count': count, 'min_level': cfg_get('level'), 'reuse': reuse } r = requests.get("{}/account/request".format(cfg_get('pgpool_url')), params=request) return r.json()
def post_discord_webhook(self, banned=False, shadowbanned=False): running_time = (time.time() - self.start_time)/ 3600.0 if banned: message = "Account {} (Level {}) is banned or has captcha after {} encounters ({:.2f} hours). Releasing.".format(self.username, self.get_stats('level'), self.total_encounters, running_time) elif shadowbanned: message = "Account {} (Level {}) is probably shadowbanned after {} encounters ({:.2f} hours). Releasing.".format(self.username, self.get_stats('level'), self.total_encounters, running_time) else: message = self.last_msg if discord_webhook(cfg_get('discord_user', cfg_get('pgpool_system_id')), message): self.log_info("Message posted to Discord") else: self.log_warn("Error posting message to Discord")
def __init__(self, auth, username, password, job_queue): self.auth = auth self.username = username self.password = password self.job_queue = job_queue # Stats self.last_request = None self.previous_encounter = None self.last_msg = "" self.total_encounters = 0 # Things needed for requests self.inventory_timestamp = None # Collects the last few pauses between encounters to measure a "encounters per hour" value self.past_pauses = deque() self.encounters_per_hour = float(0) # instantiate pgoapi self.api = PGoApi() self.api.activate_hash_server(cfg_get('hash_key')) if have_proxies(): self.proxy = get_new_proxy() self.log_info("Using Proxy: {}".format(self.proxy)) self.api.set_proxy({ 'http': self.proxy, 'https': self.proxy })
def check_login(self): # Logged in? Enough time left? Cool! 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 > 60: self.log_debug( 'Credentials remain valid for another {} seconds.'.format(remaining_time)) return # Try to login. Repeat a few times, but don't get stuck here. num_tries = 0 # One initial try + login_retries. while num_tries < 3: try: self.api.set_authentication( provider=self.auth, username=self.username, password=self.password) break except AuthException: num_tries += 1 self.log_error( 'Failed to login. ' + 'Trying again in {} seconds.'.format(6)) time.sleep(6) if num_tries >= 3: self.log_error( 'Failed to login for {} tries. Giving up.'.format( num_tries)) raise TooManyLoginAttempts('Exceeded login attempts.') wait_after_login = cfg_get('wait_after_login') self.log_info('Login successful. Waiting {} more seconds.'.format(wait_after_login)) time.sleep(wait_after_login)
def print_scouts(lines, state, scouts): def scout_line(current_line, scout_guard): scout = scout_guard.acc warn = scout.get_state('warn') warn_str = '' if warn is None else ('Yes' if warn else 'No') active = 'Yes' if scout_guard.active else 'No' if cfg_get('proxies'): return line_tmpl.format( current_line, scout.username, scout.proxy_url, warn_str, active, scout.total_encounters, "{:5.1f}".format(scout.encounters_per_hour), hr_tstamp(scout.previous_encounter), scout.last_msg) else: return line_tmpl.format( current_line, scout.username, warn_str, active, scout.total_encounters, "{:5.1f}".format(scout.encounters_per_hour), hr_tstamp(scout.previous_encounter), scout.last_msg) len_username = str( reduce(lambda l1, l2: max(l1, l2), map(lambda s: len(s.acc.username), scouts))) len_num = str(len(str(len(scouts)))) if cfg_get('proxies'): line_tmpl = u'{:' + len_num + '} | {:' + len_username + '} | {:25} | {:4} | {:6} | {:10} | {:5} | {:14} | {}' lines.append( line_tmpl.format('#', 'Scout', 'Proxy', 'Warn', 'Active', 'Encounters', 'Enc/h', 'Last Encounter', 'Message')) else: line_tmpl = u'{:' + len_num + '} | {:' + len_username + '} | {:4} | {:6} | {:10} | {:5} | {:14} | {}' lines.append( line_tmpl.format('#', 'Scout', 'Warn', 'Active', 'Encounters', 'Enc/h', 'Last Encounter', 'Message')) return print_lines(lines, scout_line, scouts, 4, state)
def cache_cleanup_thread(): minutes = cfg_get('cache_timer') while True: time.sleep(60) num_deleted = cleanup_cache(minutes) log.info( "Cleaned up {} entries from encounter cache.".format(num_deleted))
def __init__(self, auth, username, password, job_queue): super(Scout, self).__init__(auth, username, password, hash_key_provider=cfg_get('hash_key_provider'), proxy_provider=cfg_get('proxy_provider')) self.job_queue = job_queue # Stats self.previous_encounter = None self.total_encounters = 0 # Collects the last few pauses between encounters to measure a "encounters per hour" value self.past_pauses = deque() self.encounters_per_hour = float(0) # Number of errors that may be the cause of a shadowban self.errors = 0
def get_iv(): error = None if not app_state.accept_new_requests: error = 'Not accepting new requests.' if not have_active_scouts(): error = 'No active scout available. All banned?' max_queued_jobs = cfg_get('max_queued_jobs') num_jobs = jobs.qsize() if max_queued_jobs and num_jobs >= max_queued_jobs: error = "Job queue full ({} items). Perform less encounters or add more scouts.".format( num_jobs) if error: log.warning(error) return jsonify({'success': False, 'error': error}) pokemon_id = request.args["pokemon_id"] pokemon_name = get_pokemon_name(pokemon_id) lat = request.args["latitude"] lng = request.args["longitude"] weather = request.args.get("weather", "unknown") encounter_id = normalize_encounter_id(request.args.get("encounter_id")) # Spawn point ID is assumed to be a hex string spawn_point_id = request.args.get("spawn_point_id") despawn_time = request.args.get("despawn_time") # Check cache cache_key = "{}-{}".format(encounter_id, weather) if encounter_id else "{}-{}-{}".format( pokemon_id, lat, lng) result = get_cached_encounter(cache_key) if result: log.info( u"Returning cached result: {:.1f}% level {} {} with {} CP".format( result['iv_percent'], result['level'], pokemon_name, result['cp'])) return jsonify(result) # Create a ScoutJob job = ScoutJob(pokemon_id, encounter_id, spawn_point_id, lat, lng, despawn_time=despawn_time) # Enqueue and wait for job to be processed jobs.put(job) while not job.processed: time.sleep(1) # Cache successful jobs and return result if job.result['success']: cache_encounter(cache_key, job.result) return jsonify(job.result)
def load_accounts(jobs): accounts_file = cfg_get('accounts_file') accounts = [] if accounts_file: log.info("Loading accounts from file {}.".format(accounts_file)) with codecs.open(accounts_file, mode='r', encoding='utf-8') as f: for line in f: fields = line.split(",") fields = map(unicode.strip, fields) accounts.append(ScoutGuard(fields[0], fields[1], fields[2], jobs)) elif cfg_get('pgpool_url') and cfg_get('pgpool_system_id') and cfg_get('pgpool_num_accounts') > 0: acc_json = load_pgpool_accounts(cfg_get('pgpool_num_accounts'), reuse=True) if isinstance(acc_json, dict) and len(acc_json) > 0: acc_json = [acc_json] for i in range(0, cfg_get('pgpool_num_accounts')): if i < len(acc_json): accounts.append(ScoutGuard(acc_json[i]['auth_service'], acc_json[i]['username'], acc_json[i]['password'], jobs)) else: #We are using PGPool, load empty ScoutGuards that can be filled later accounts.append(ScoutGuard(auth="", username="******", password="", job_queue=jobs)) if len(accounts) == 0: log.error("Could not load any accounts. Nothing to do. Exiting.") sys.exit(1) return accounts
def __init__(self, auth, username, password, job_queue, duplicate): super(Scout, self).__init__(auth, username, password, hash_key_provider=cfg_get('hash_key_provider'), proxy_provider=cfg_get('proxy_provider')) self.job_queue = job_queue # Stats self.start_time = time.time() self.previous_encounter = None self.total_encounters = 0 self.duplicate = duplicate # 0 = master account, 1 = duplicate account, 2 = release duplicate account from semaphore loop # Collects the last few pauses between encounters to measure a "encounters per hour" value self.past_pauses = deque() self.encounters_per_hour = float(0) # Number of errors that may be the cause of a shadowban self.errors = 0
def init_resoures_from_file(name, filename_key): resources = [] resource_file = cfg_get(filename_key) if resource_file: try: with open(resource_file) as f: for line in f: # Ignore blank lines and comment lines. if len(line.strip()) == 0 or line.startswith('#'): continue resource = line.strip() resources.append(resource) except IOError: log.exception('Could not load {} from {}.'.format(resource_file)) exit(1) return resources
def __init__(self, auth, username, password, job_queue): self.auth = auth self.username = username self.password = password self.job_queue = job_queue # Stats self.last_request = None self.last_msg = "" self.total_scouts = 0 # Holds timestamps of scout requests of the last hour self.history = deque() # instantiate pgoapi self.api = PGoApi() self.api.activate_hash_server(cfg_get('hash_key'))
def scout_line(current_line, scout_guard): scout = scout_guard.acc warn = scout.get_state('warn') warn_str = '' if warn is None else ('Yes' if warn else 'No') active = 'Yes' if scout_guard.active else 'No' if cfg_get('proxies'): return line_tmpl.format( current_line, scout.username, scout.proxy_url, warn_str, active, scout.total_encounters, "{:5.1f}".format(scout.encounters_per_hour), hr_tstamp(scout.previous_encounter), scout.last_msg) else: return line_tmpl.format( current_line, scout.username, warn_str, active, scout.total_encounters, "{:5.1f}".format(scout.encounters_per_hour), hr_tstamp(scout.previous_encounter), scout.last_msg)
def run(self): self.log_info("Waiting for job...") while True: job = self.job_queue.get() try: self.log_info(u"Scouting a {} at {}, {}".format( job.pokemon_name, job.lat, job.lng)) # Initialize API (lat, lng) = jitter_location(job.lat, job.lng) self.set_position(lat, lng, job.altitude) if not self.check_login(): job.result = self.scout_error(self.last_msg) continue # Check if banned. if self.is_banned(): job.result = self.scout_error("Account banned") break if job.encounter_id and job.spawn_point_id: job.result = self.scout_by_encounter_id(job) else: if self.find_pokemon(job): time.sleep(2) job.result = self.scout_by_encounter_id(job) else: job.result = self.scout_error( "Could not determine encounter_id for {} at {}, {}" .format(job.pokemon_name, job.lat, job.lng)) # Check shadowban status if self.shadowbanned or self.errors >= cfg_get( 'shadowban_threshold'): self.shadowbanned = True self.log_warning( "Account probably shadowbanned. Stopping.") break except: job.result = self.scout_error(repr(sys.exc_info())) finally: job.processed = True self.update_history()
def __init__(self, pokemon_id, encounter_id, spawn_point_id, lat, lng, despawn_time=None): self.pokemon_id = int(pokemon_id) self.pokemon_name = get_pokemon_name(pokemon_id) self.encounter_id = encounter_id self.spawn_point_id = spawn_point_id self.lat = float(lat) self.lng = float(lng) self.despawn_time = despawn_time self.processed = False self.result = {} # Set a time when this job expires if a TTL was given ttl = cfg_get('max_job_ttl') self.expire_at = time.time() + (ttl * 60) if ttl else None # Use fixed random altitude per job self.altitude = random.randint(12, 108)
def parse_encounter_response(self, responses, job): if not responses: return self.scout_error("Empty encounter response.") if self.has_captcha(): return self.scout_error("Scout account captcha'd.") encounter = responses.get('ENCOUNTER', {}) enc_status = encounter.get('status', None) # Check for shadowban - ENCOUNTER_BLOCKED_BY_ANTICHEAT if enc_status == 8: self.shadowbanned = True if enc_status != 1: return self.scout_error(ENCOUNTER_RESULTS[enc_status]) if 'wild_pokemon' not in encounter: return self.scout_error("No wild pokemon info found.") scout_level = self.player_stats['level'] if scout_level < cfg_get("require_min_trainer_level"): return self.scout_error( "Trainer level {} is too low. Needs to be {}+".format( scout_level, cfg_get("require_min_trainer_level"))) pokemon_info = encounter['wild_pokemon']['pokemon_data'] cp = pokemon_info['cp'] pokemon_level = calc_pokemon_level(pokemon_info['cp_multiplier']) probs = encounter['capture_probability']['capture_probability'] at = pokemon_info.get('individual_attack', 0) df = pokemon_info.get('individual_defense', 0) st = pokemon_info.get('individual_stamina', 0) iv = calc_iv(at, df, st) moveset_grades = get_moveset_grades(job.pokemon_id, job.pokemon_name, pokemon_info['move_1'], pokemon_info['move_2']) responses = { 'success': True, 'encounter_id': job.encounter_id, 'encounter_id_b64': b64encode(str(job.encounter_id)), 'height': pokemon_info['height_m'], 'weight': pokemon_info['weight_kg'], 'gender': pokemon_info['pokemon_display']['gender'], 'iv_percent': iv, 'iv_attack': at, 'iv_defense': df, 'iv_stamina': st, 'move_1': pokemon_info['move_1'], 'move_2': pokemon_info['move_2'], 'rating_attack': moveset_grades['offense'], 'rating_defense': moveset_grades['defense'], 'cp': cp, 'cp_multiplier': pokemon_info['cp_multiplier'], 'level': pokemon_level, 'catch_prob_1': probs[0], 'catch_prob_2': probs[1], 'catch_prob_3': probs[2], 'scout_level': scout_level, 'encountered_time': time.time() } # Add form of Unown if job.pokemon_id == 201: responses['form'] = pokemon_info['pokemon_display'].get('form', None) self.log_info( u"Found a {:.1f}% ({}/{}/{}) L{} {} with {} CP (scout level {}).".format( iv, at, df, st, pokemon_level, job.pokemon_name, cp, scout_level)) inc_for_pokemon(job.pokemon_id) return responses
def check_proxies(): source_proxies = [] check_results = [0] * (check_result_max + 1) # Load proxies from the file if such a file is configured. proxies_file = cfg_get('proxies_file') if not proxies_file: return source_proxies log.info('Loading proxies from file {}.'.format(proxies_file)) try: with open(proxies_file) as f: for line in f: # Ignore blank lines and comment lines. if len(line.strip()) == 0 or line.startswith('#'): continue source_proxies.append(line.strip()) except IOError: log.error('Could not load proxies from {}.'.format(proxies_file)) return [] log.info('Loaded {} proxies.'.format(len(source_proxies))) if len(source_proxies) == 0: log.error('Proxy file {} was configured but ' + 'no proxies were loaded. Aborting.'.format(proxies_file)) sys.exit(1) proxy_queue = Queue() total_proxies = len(source_proxies) log.info('Checking proxies...') working_proxies = [] for proxy in enumerate(source_proxies): proxy_queue.put(proxy) t = Thread(target=check_proxy, name='check_proxy', args=(proxy_queue, 5, working_proxies, check_results)) t.daemon = True t.start() # This is painful but we need to wait here until proxy_queue is # completed so we have a working list of proxies. proxy_queue.join() num_working_proxies = len(working_proxies) if num_working_proxies == 0: log.error('Proxies were configured but no working ' + 'proxies were found. Aborting.') sys.exit(1) else: other_fails = (check_results[check_result_failed] + check_results[check_result_wrong] + check_results[check_result_exception] + check_results[check_result_empty]) log.info('Proxy check completed. Working: %d, banned: %d, ' + 'timeout: %d, other fails: %d of total %d configured.', num_working_proxies, check_results[check_result_banned], check_results[check_result_timeout], other_fails, total_proxies) return working_proxies
def run_webserver(): app.run(threaded=True, port=cfg_get('port'))
def parse_encounter_response(self, responses, job): if not responses: return self.scout_error("Empty encounter response") if self.has_captcha(): return self.scout_error("Account captcha'd") if self.is_banned(): return self.scout_error("Account banned") encounter = responses.get('ENCOUNTER') if not encounter: return self.scout_error("No encounter result returned.") if not encounter.HasField('wild_pokemon'): self.errors += 1 return self.scout_error("No wild pokemon info found.") enc_status = encounter.status # Check for shadowban - ENCOUNTER_BLOCKED_BY_ANTICHEAT if enc_status == 8: self.errors += 1 self.shadowbanned = True if enc_status != 1: return self.scout_error(ENCOUNTER_RESULTS[enc_status]) scout_level = self.get_stats('level') if scout_level < cfg_get('level'): return self.scout_error( "Trainer level {} is too low. Needs to be {}+".format( scout_level, cfg_get("level"))) pokemon_info = encounter.wild_pokemon.pokemon_data cp = pokemon_info.cp pokemon_level = calc_pokemon_level(pokemon_info.cp_multiplier) probs = encounter.capture_probability.capture_probability at = pokemon_info.individual_attack df = pokemon_info.individual_defense st = pokemon_info.individual_stamina iv = calc_iv(at, df, st) moveset_grades = get_moveset_grades(job.pokemon_id, job.pokemon_name, pokemon_info.move_1, pokemon_info.move_2) responses = { 'success': True, 'encounter_id': job.encounter_id, 'encounter_id_b64': b64encode(str(job.encounter_id)), 'height': pokemon_info.height_m, 'weight': pokemon_info.weight_kg, 'gender': pokemon_info.pokemon_display.gender, 'iv_percent': iv, 'iv_attack': at, 'iv_defense': df, 'iv_stamina': st, 'move_1': pokemon_info.move_1, 'move_2': pokemon_info.move_2, 'rating_attack': moveset_grades['offense'], 'rating_defense': moveset_grades['defense'], 'cp': cp, 'cp_multiplier': pokemon_info.cp_multiplier, 'level': pokemon_level, 'catch_prob_1': probs[0], 'catch_prob_2': probs[1], 'catch_prob_3': probs[2], 'scout_level': scout_level, 'encountered_time': time.time() } # Add form of Unown if job.pokemon_id == 201: responses['form'] = pokemon_info.pokemon_display.form self.log_info( u"Found a {:.1f}% ({}/{}/{}) L{} {} with {} CP (scout level {}).". format(iv, at, df, st, pokemon_level, job.pokemon_name, cp, scout_level)) inc_for_pokemon(job.pokemon_id) return responses
def check_proxies(): source_proxies = [] check_results = [0] * (check_result_max + 1) # Load proxies from the file if such a file is configured. proxies_file = cfg_get('proxies_file') if not proxies_file: return source_proxies log.info('Loading proxies from file {}.'.format(proxies_file)) try: with open(proxies_file) as f: for line in f: # Ignore blank lines and comment lines. if len(line.strip()) == 0 or line.startswith('#'): continue source_proxies.append(line.strip()) except IOError: log.error('Could not load proxies from {}.'.format(proxies_file)) return [] log.info('Loaded {} proxies.'.format(len(source_proxies))) if len(source_proxies) == 0: log.error('Proxy file {} was configured but ' + 'no proxies were loaded. Aborting.'.format(proxies_file)) sys.exit(1) proxy_queue = Queue() total_proxies = len(source_proxies) log.info('Checking proxies...') working_proxies = [] for proxy in enumerate(source_proxies): proxy_queue.put(proxy) t = Thread(target=check_proxy, name='check_proxy', args=(proxy_queue, 5, working_proxies, check_results)) t.daemon = True t.start() # This is painful but we need to wait here until proxy_queue is # completed so we have a working list of proxies. proxy_queue.join() num_working_proxies = len(working_proxies) if num_working_proxies == 0: log.error('Proxies were configured but no working ' + 'proxies were found. Aborting.') sys.exit(1) else: other_fails = (check_results[check_result_failed] + check_results[check_result_wrong] + check_results[check_result_exception] + check_results[check_result_empty]) log.info( 'Proxy check completed. Working: %d, banned: %d, ' + 'timeout: %d, other fails: %d of total %d configured.', num_working_proxies, check_results[check_result_banned], check_results[check_result_timeout], other_fails, total_proxies) return working_proxies
app.run(threaded=True, port=cfg_get('port')) def cache_cleanup_thread(): while True: time.sleep(60) num_deleted = cleanup_cache() log.info( "Cleaned up {} entries from encounter cache.".format(num_deleted)) # =========================================================================== log.info("PGScout starting up.") with open(cfg_get('accounts_file'), 'r') as f: for num, line in enumerate(f, 1): fields = line.split(",") fields = map(str.strip, fields) scout = Scout(fields[0], fields[1], fields[2], jobs) scouts.append(scout) t = Thread(target=scout.run, name="{}".format(scout.username)) t.daemon = True t.start() # Cleanup cache in background t = Thread(target=cache_cleanup_thread, name="cache_cleaner") t.daemon = True t.start() # Start thread to print current status and get user input.
log.info("PGScout starting up.") cfg_init() scouts = load_accounts(jobs) for scout in scouts: t = Thread(target=scout.run) t.daemon = True t.start() # Cleanup cache in background t = Thread(target=cache_cleanup_thread, name="cache_cleaner") t.daemon = True t.start() # Start thread to print current status and get user input. t = Thread(target=print_status, name='status_printer', args=(scouts, cfg_get('initial_view'), jobs)) t.daemon = True t.start() # Launch the webserver t = Thread(target=run_webserver, name='webserver') t.daemon = True t.start() # Catch SIGINT to exit signal.signal(signal.SIGINT, signal_handler) while True: time.sleep(1)
log.exception('Could not load {} from {}.'.format(resource_file)) exit(1) return resources # =========================================================================== log.info("PGScout starting up.") init_mr_mime() init_proxies() hash_key_provider = CyclicResourceProvider() hash_key = cfg_get('hash_key') if hash_key and len(hash_key) > 0: hash_key_provider.add_resource(hash_key) log.info("Loaded single hash key from config.") hash_keys = cfg_get('hash_keys') if hash_keys and len(hash_keys) > 0: for hk in hash_keys: hash_key_provider.add_resource(hk) log.info("Loaded {} hash keys from config.".format(len(hash_keys))) hash_keys = init_resoures_from_file('hash keys', 'hash_key_file') if hash_keys and len(hash_keys) > 0: for hk in hash_keys: hash_key_provider.add_resource(hk) log.info("Loaded {} hash keys from file {}.".format(
def get_pokemon_prio(pokemon_id): low_prio_pokemon = cfg_get('low_prio_pokemon') return PRIO_NORMAL if low_prio_pokemon and int( pokemon_id) not in low_prio_pokemon else PRIO_LOW
def status(page=1): def td(cell): return "<td>{}</td>".format(cell) max_scouts_per_page = 25 max_page = int(math.ceil(len(scouts) / float(max_scouts_per_page))) lines = "<style> th,td { padding-left: 10px; padding-right: 10px; border: 1px solid #ddd; } table { border-collapse: collapse } td { text-align:center }</style>" lines += "<meta http-equiv='Refresh' content='5'>" lines += "Accepting requests: {} | Job queue length: {} | Cached encounters: {} | Mem Usage: {}".format( app_state.accept_new_requests, jobs.qsize(), get_cached_count(), rss_mem_size()) lines += "<br><br>" if cfg_get('proxies'): headers = [ '#', 'Scout', 'Proxy', 'Start', 'Warn', 'Active', 'Encounters', 'Enc/h', 'Errors', 'Last Encounter', 'Message' ] else: headers = [ '#', 'Scout', 'Start', 'Warn', 'Active', 'Encounters', 'Enc/h', 'Errors', 'Last Encounter', 'Message' ] lines += "<table><tr>" for h in headers: lines += "<th>{}</th>".format(h) lines += "</tr>" if page * max_scouts_per_page > len( scouts): #Page number is too great, set to last page page = max_page if page < 1: page = 1 for i in range((page - 1) * max_scouts_per_page, page * max_scouts_per_page): if i >= len(scouts): break lines += "<tr>" s = scouts[i].acc warn = s.get_state('warn') warn_str = '' if warn is None else ('Yes' if warn else 'No') lines += td(i + 1) lines += td(s.username) lines += td(s.proxy_url) if cfg_get('proxies') else "" lines += td(hr_tstamp(s.start_time)) lines += td(warn_str) lines += td('Yes' if scouts[i].active else 'No') lines += td(s.total_encounters) lines += td("{:5.1f}".format(s.encounters_per_hour)) lines += td(s.errors) lines += td(hr_tstamp(s.previous_encounter)) lines += td(s.last_msg.encode('utf-8')) lines += "</tr>" lines += "</table>" # Encounters enctotal = 0 active = 0 for scout in scouts: enctotal = enctotal + (scout.acc.encounters_per_hour if scout.active else 0.0) active = active + (1 if scout.active else 0) lines += "<br>" lines += "Enc/hr Total: {:5.0f} ({} active)".format(enctotal, active) lines += "<br>" if len( scouts ) > max_scouts_per_page: # Use pages if we have more than max_scouts_per_page lines += "Page: " if max_page > 1 and page > 1: lines += "<a href={}><</a> | ".format( url_for('status', page=page - 1)) for p in range(1, max_page + 1): if p == page: lines += str(p) else: url = url_for('status', page=p) lines += "<a href={}>{}</a>".format(url, p) if p < max_page: lines += " | " if max_page > 1 and page < max_page: lines += " | <a href={}>></a>".format( url_for('status', page=page + 1)) return lines
sys.exit(0) # =========================================================================== log.info("PGScout starting up.") cfg_init() scouts = load_accounts(jobs) for scout in scouts: t = Thread(target=scout.run, args=(scouts)) t.daemon = True t.start() if cfg_get('cache_timer') > 0: # Cleanup cache in background t = Thread(target=cache_cleanup_thread, name="cache_cleaner") t.daemon = True t.start() # Start thread to print current status and get user input. t = Thread(target=print_status, name='status_printer', args=(scouts, cfg_get('initial_view'), jobs)) t.daemon = True t.start() # Launch the webserver t = Thread(target=run_webserver, name='webserver') t.daemon = True
def get_iv(): if not app_state.accept_new_requests: return jsonify({ 'success': False, 'error': 'Not accepting new requests.' }) payload = {} payload['encounter_id'] = normalized['encounter_id'] payload['pokemon_id'] = normalized['pokemon_id'] payload['latitude'] = normalized['lat'] payload['longitude'] = normalized['lon'] payload[ 'error'] = "PGSCOUT ONTVANGEN, PGSCOUT ACCEPTEERT GEEN NIEUWE REQUESTS" response = requests.post('http://192.168.1.101:1418/test6', json=payload) #return_iv(request.args) payload = {} payload['encounter_id'] = request.args["encounter_id"] payload['pokemon_id'] = request.args["pokemon_id"] payload['latitude'] = request.args["latitude"] payload['longitude'] = request.args["longitude"] payload['pokehunt_id'] = request.args['pokehunt_id'] #response = requests.post('http://192.168.1.101:1418/test3', json=payload) pokemon_id = request.args["pokemon_id"] pokemon_name = get_pokemon_name(pokemon_id) lat = request.args["latitude"] lng = request.args["longitude"] encounter_id = normalize_encounter_id(request.args.get("encounter_id")) spawn_point_id = normalize_spawn_point_id( request.args.get("spawn_point_id")) pokehunt_id = request.args["pokehunt_id"] # Check cache cache_key = encounter_id if encounter_id else "{}-{}-{}".format( pokemon_id, lat, lng) result = get_cached_encounter(cache_key) if result: log.info( u"Returning cached result: {:.1f}% level {} {} with {} CP".format( result['iv_percent'], result['level'], pokemon_name, result['cp'])) response = requests.post(cfg_get('customwebhook'), json=job.result) if (response.status_code != 200): log.error("Error sending webhook: {}".format( response.raise_for_status())) return jsonify({ 'success': False, 'error': 'Not accepting new requests.' }) else: return jsonify({'success': True}) # Create a ScoutJob job = ScoutJob(pokemon_id, encounter_id, spawn_point_id, lat, lng, pokehunt_id) jobs.put(job) # Enqueue and wait for job to be processed NO return jsonify({ 'success': True, })