Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[FEATURE] Api Wrapper to handle connection issues #1459

Merged
merged 5 commits into from
Jul 28, 2016
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 3 additions & 4 deletions pokemongo_bot/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
from metrics import Metrics
from spiral_navigator import SpiralNavigator
from worker_result import WorkerResult
from api_wrapper import ApiWrapper


class PokemonGoBot(object):
Expand Down Expand Up @@ -205,9 +206,7 @@ def check_session(self, position):

def login(self):
logger.log('Attempting login to Pokemon Go.', 'white')
self.api._auth_token = None
self.api._auth_provider = None
self.api._api_endpoint = None
self.api.reset_auth()
lat, lng = self.position[0:2]
self.api.set_position(lat, lng, 0)

Expand All @@ -223,7 +222,7 @@ def login(self):

def _setup_api(self):
# instantiate pgoapi
self.api = PGoApi()
self.api = ApiWrapper(PGoApi())

# provide player position on the earth
self._set_starting_position()
Expand Down
55 changes: 55 additions & 0 deletions pokemongo_bot/api_wrapper.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
# api_wrapper.py

from pgoapi import PGoApi
from pgoapi.exceptions import NotLoggedInException
from human_behaviour import sleep
import logger

class ApiWrapper(object):
def __init__(self, api):
self._api = api
self.reset_auth()

def reset_auth(self):
self._api._auth_token = None
self._api._auth_provider = None
self._api._api_endpoint = None

# wrap api methods
def _can_call(self):
if not self._api._req_method_list or len(self._api._req_method_list) == 0:
raise RuntimeError('Trying to call the api without setting any request')
if self._api._auth_provider is None or not self._api._auth_provider.is_login():
logger.log('Not logged in!', 'red')
raise NotLoggedInException()
return True

def call(self, max_retry=5):
if not self._can_call():
return False

api_req_method_list = self._api._req_method_list
result = None
try_cnt = 0
while True:
self._api._req_method_list = [req_method for req_method in api_req_method_list] # api internally clear this field after a call
result = self._api.call()
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Worth wrapping in a try...except block perhaps? Exceptions can be raised from here still.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What else can be raised here if I may ask?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Well I am not familiar with the underlying API. I'd say whenever you call a function, there's a risk of an Exception being raised (maybe not even in the current API release). So it's a matter of deciding if you want to harden your API wrapper to handle those errors or not.

Any of the core maintainers care to share their opinions?

if result is None:
try_cnt += 1
logger.log('Server seems to be busy or offline - try again - {}/{}'.format(try_cnt, max_retry), 'red')
if try_cnt >= max_retry:
raise ServerBusyOrOfflineException()
sleep(1)
else:
break
return result

def login(self, provider, username, password):
return self._api.login(provider, username, password)

# fallback
def __getattr__(self, func):
return getattr(self._api, func)