Repository: RocketMap/RocketMap

Issue:
Fix L30 accounts beeing set on hold
I have 20 small areas with 1 L30 account in each.
I know it isn't much but should be enough, i only encounter some rare spawns.
The accounts keep getting put on hold for nonsens reasons and they are never retried.
Restarting the map fixes everything, but restarting every hour is getting a bit boring.

## Expected Behavior
L30 accounts should be retried not put away immediately.
If still not working put them back on hold, but not forever.
Retry them after n minutes.

## Current Behavior
L30 account is put on hold for all kinds of exceptions. Like NianticOfflineException.

## Possible Solution
Add retry, and retry accounts put on hold after a while.
Add auto solve captchas on L30 accounts as an option we decide.
And add the L30 accounts to the status page or something.
I have no idea how healthy my L30 accounts are. Are they put on hold ? Are they having captchas ?
Now, i have to log to file and dig into thousand of rows.

## Steps to Reproduce (for bugs)
Scan a st 10 area with 8 low level accounts and one L30 account, it works good for 60-90 minutes.
Until i get a NianticOffline exception, the connection was forcibly closed by the host.

## Your Environment
Latest RM.
Latest Pyhton.
Windows 10.



Discussion:

Resolving patch:
diff --git a/pogom/account.py b/pogom/account.py
--- a/pogom/account.py
+++ b/pogom/account.py
@@ -329,18 +329,41 @@ def spin_pokestop_request(api, fort, step_location):
             fort_longitude=fort['longitude'],
             player_latitude=step_location[0],
             player_longitude=step_location[1])
-        spin_pokestop_response = req.check_challenge()
-        spin_pokestop_response = req.get_hatched_eggs()
-        spin_pokestop_response = req.get_inventory()
-        spin_pokestop_response = req.check_awarded_badges()
-        spin_pokestop_response = req.download_settings()
-        spin_pokestop_response = req.get_buddy_walked()
+        req.check_challenge()
+        req.get_hatched_eggs()
+        req.get_inventory()
+        req.check_awarded_badges()
+        req.download_settings()
+        req.get_buddy_walked()
         spin_pokestop_response = req.call()
 
         return spin_pokestop_response
 
     except Exception as e:
-        log.warning('Exception while spinning Pokestop: %s', repr(e))
+        log.error('Exception while spinning Pokestop: %s.', repr(e))
+        return False
+
+
+def encounter_pokemon_request(api, encounter_id, spawnpoint_id, scan_location):
+    try:
+        # Setup encounter request envelope.
+        req = api.create_request()
+        req.encounter(
+            encounter_id=encounter_id,
+            spawn_point_id=spawnpoint_id,
+            player_latitude=scan_location[0],
+            player_longitude=scan_location[1])
+        req.check_challenge()
+        req.get_hatched_eggs()
+        req.get_inventory()
+        req.check_awarded_badges()
+        req.download_settings()
+        req.get_buddy_walked()
+        encounter_result = req.call()
+
+        return encounter_result
+    except Exception as e:
+        log.error('Exception while encountering Pokémon: %s.', repr(e))
         return False
 
 
diff --git a/pogom/models.py b/pogom/models.py
--- a/pogom/models.py
+++ b/pogom/models.py
@@ -34,7 +34,7 @@
 from .transform import transform_from_wgs_to_gcj, get_new_coords
 from .customLog import printPokemon
 from .account import (tutorial_pokestop_spin, get_player_level, check_login,
-                      setup_api)
+                      setup_api, encounter_pokemon_request)
 
 log = logging.getLogger(__name__)
 
@@ -1989,7 +1989,8 @@ def parse_map(args, map_dict, step_location, db_update_queue, wh_update_queue,
                         # these single-use variables are making me ill.
                         if args.hash_key:
                             key = key_scheduler.next()
-                            log.debug('Using key %s for this encounter.', key)
+                            log.debug('Using hashing key %s for this'
+                                      + ' encounter.', key)
                             hlvl_api.activate_hash_server(key)
 
                     # We have an API object now. If necessary, store it.
@@ -2003,52 +2004,58 @@ def parse_map(args, map_dict, step_location, db_update_queue, wh_update_queue,
                     check_login(args, hlvl_account, hlvl_api, scan_location,
                                 status['proxy_url'])
 
-                    # Setup encounter request envelope.
-                    req = hlvl_api.create_request()
-                    req.encounter(
-                        encounter_id=p['encounter_id'],
-                        spawn_point_id=p['spawn_point_id'],
-                        player_latitude=scan_location[0],
-                        player_longitude=scan_location[1])
-                    req.check_challenge()
-                    req.get_hatched_eggs()
-                    req.get_inventory()
-                    req.check_awarded_badges()
-                    req.download_settings()
-                    req.get_buddy_walked()
-                    encounter_result = req.call()
-
-                    # Readability.
-                    responses = encounter_result['responses']
-
-                    # Check for captcha
-                    captcha_url = responses['CHECK_CHALLENGE']['challenge_url']
-                    # Throw warning but finish parsing
-                    if len(captcha_url) > 1:
-                        # Flag account.
-                        hlvl_account['captcha'] = True
-                        log.info('Level %s account %s encountered a captcha.',
-                                 encounter_level,
-                                 hlvl_account['username'])
+                    # Encounter Pokémon.
+                    encounter_result = encounter_pokemon_request(
+                        hlvl_api,
+                        p['encounter_id'],
+                        p['spawn_point_id'],
+                        scan_location)
+
+                    # Handle errors.
+                    if encounter_result:
+                        # Readability.
+                        responses = encounter_result['responses']
+
+                        # Check for captcha.
+                        captcha_url = responses[
+                            'CHECK_CHALLENGE']['challenge_url']
+
+                        # Throw warning but finish parsing.
+                        if len(captcha_url) > 1:
+                            # Flag account.
+                            hlvl_account['captcha'] = True
+                            log.error('Account %s encountered a captcha.'
+                                      + ' Account will not be used.',
+                                      hlvl_account['username'])
+                        else:
+                            # Update level indicator before we clear the
+                            # response.
+                            encounter_level = get_player_level(
+                                encounter_result)
+
+                            # User error?
+                            if encounter_level < 30:
+                                raise Exception('Expected account of level 30'
+                                                + ' or higher, but account '
+                                                + hlvl_account['username']
+                                                + ' is only level '
+                                                + encounter_level + '.')
+
+                        # We're done with the encounter. If it's from an
+                        # AccountSet, release account back to the pool.
+                        if using_accountset:
+                            account_sets.release(hlvl_account)
+
+                        # Clear the response for memory management.
+                        encounter_result = clear_dict_response(
+                            encounter_result)
                     else:
-                        # Update level indicator before we clear the response.
-                        encounter_level = get_player_level(encounter_result)
-
-                        # User error?
-                        if encounter_level < 30:
-                            raise Exception('Expected account of level 30 or'
-                                            + ' higher, but account '
-                                            + hlvl_account['username']
-                                            + ' is only level '
-                                            + encounter_level + '.')
-
-                    # We're done with the encounter. If it's from an
-                    # AccountSet, release account back to the pool.
-                    if using_accountset:
-                        account_sets.release(hlvl_account)
-
-                    # Clear the response for memory management.
-                    encounter_result = clear_dict_response(encounter_result)
+                        # Something happened. Clean up.
+
+                        # We're done with the encounter. If it's from an
+                        # AccountSet, release account back to the pool.
+                        if using_accountset:
+                            account_sets.release(hlvl_account)
                 else:
                     log.error('No L30 accounts are available, please'
                               + ' consider adding more. Skipping encounter.')


Test patch: