Skip to content

Commit

Permalink
Formatting changes, minor bug fixes
Browse files Browse the repository at this point in the history
  • Loading branch information
Noctem committed May 19, 2017
1 parent 8578633 commit 7ad37e7
Show file tree
Hide file tree
Showing 10 changed files with 184 additions and 100 deletions.
5 changes: 4 additions & 1 deletion aiopogo/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,8 @@
raise PleaseInstallProtobufVersion3('Protobuf not found, install it.')

if int(protobuf_version[:1]) < 3:
raise PleaseInstallProtobufVersion3('Protobuf 3 needed, you have {}'.format(protobuf_version))
raise PleaseInstallProtobufVersion3(
'Protobuf 3 needed, you have {}'.format(protobuf_version))

from os import path
import sys
Expand All @@ -34,10 +35,12 @@
from .rpc_api import RpcApi
from .hash_server import HashServer


def close_sessions():
SESSIONS.close()
HashServer.close_session()


def activate_hash_server(hash_token, conn_limit=300):
HashServer.set_token(hash_token)
HashServer.activate_session(conn_limit)
9 changes: 5 additions & 4 deletions aiopogo/auth.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

from .utilities import get_time_ms


class Auth:
loop = get_event_loop()

Expand Down Expand Up @@ -42,10 +43,10 @@ def is_new_ticket(self, new_ticket_time_ms):
def check_ticket(self):
if get_time_ms() < (self._ticket_expire - 10000):
return True
else:
self.log.debug('Removed expired Session Ticket (%s)', self._ticket_expire)
self._ticket_expire, self._ticket_start, self._ticket_end = 0, None, None
return False
self.log.debug(
'Removed expired Session Ticket (%s)', self._ticket_expire)
self._ticket_expire, self._ticket_start, self._ticket_end = 0, None, None
return False

def get_ticket(self):
return self._ticket_expire, self._ticket_start, self._ticket_end
Expand Down
74 changes: 42 additions & 32 deletions aiopogo/auth_google.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,10 @@
from .auth import Auth
from .exceptions import AuthException, InvalidCredentialsException


class AuthGoogle(Auth):
GOOGLE_LOGIN_ANDROID_ID = '9774d56d682e549c'
GOOGLE_LOGIN_SERVICE= 'audience:server:client_id:848232511240-7so421jotr2609rmqakceuu1luuq0ptb.apps.googleusercontent.com'
GOOGLE_LOGIN_SERVICE = 'audience:server:client_id:848232511240-7so421jotr2609rmqakceuu1luuq0ptb.apps.googleusercontent.com'
GOOGLE_LOGIN_APP = 'com.nianticlabs.pokemongo'
GOOGLE_LOGIN_CLIENT_SIG = '321187995bc7cdc2b5fc91b11a96e2baa8602c62'

Expand All @@ -21,16 +22,24 @@ def __init__(self, proxy=None, refresh_token=None):
self._proxy = proxy

async def user_login(self, username, password):
self.log.info('Google User Login for: {}'.format(username))
self.log.info('Google User Login for: %s', username)

try:
assert isinstance(self._username, str) and isinstance(self._password, str)
assert (isinstance(username, str)
and isinstance(password, str))
except AssertionError:
raise InvalidCredentialsException("Username/password not correctly specified")
raise InvalidCredentialsException(
"Username/password not correctly specified")

login = partial(
perform_master_login,
username,
password,
self.GOOGLE_LOGIN_ANDROID_ID,
proxy=self._proxy)

login = partial(perform_master_login, username, password, self.GOOGLE_LOGIN_ANDROID_ID, proxy=self._proxy)
with ThreadPoolExecutor(max_workers=1) as x:
user_login = await self.loop.run_in_executor(x, login)
with ThreadPoolExecutor(max_workers=1) as executor:
user_login = await self.loop.run_in_executor(executor, login)

try:
self._refresh_token = user_login['Token']
Expand All @@ -43,30 +52,31 @@ async def get_access_token(self, force_refresh=False):
if not force_refresh and self.check_access_token():
self.log.debug('Using cached Google access token')
return self._access_token
else:

self._access_token = None
self.authenticated = False
self.log.info('Requesting Google access token...')

oauth = partial(perform_oauth, None, self._refresh_token,
self.GOOGLE_LOGIN_ANDROID_ID, self.GOOGLE_LOGIN_SERVICE,
self.GOOGLE_LOGIN_APP, self.GOOGLE_LOGIN_CLIENT_SIG,
proxy=self._proxy)
with ThreadPoolExecutor(max_workers=1) as executor:
token_data = await self.loop.run_in_executor(executor, oauth)

try:
self._access_token = token_data['Auth']
except KeyError:
self._access_token = None
self.authenticated = False
self.log.info('Requesting Google access token...')

oauth = partial(perform_oauth, None, self._refresh_token,
self.GOOGLE_LOGIN_ANDROID_ID, self.GOOGLE_LOGIN_SERVICE,
self.GOOGLE_LOGIN_APP, self.GOOGLE_LOGIN_CLIENT_SIG,
proxy=self._proxy)
with ThreadPoolExecutor(max_workers=1) as x:
token_data = await self.loop.run_in_executor(x, oauth)

try:
self._access_token = token_data['Auth']
except KeyError:
self._access_token = None
self.authenticated = False
raise AuthException("Could not receive a Google Access Token")

try:
self._access_token_expiry = token_data['Expiry']
except KeyError:
self._access_token_expiry = time() + 7200.0
self.authenticated = True
self.log.info('Google Access Token successfully received.')
self.log.debug('Google Access Token: %s...', self._access_token[:25])
return self._access_token
raise AuthException("Could not receive a Google Access Token")

try:
self._access_token_expiry = token_data['Expiry']
except KeyError:
self._access_token_expiry = time() + 7200.0
self.authenticated = True
self.log.info('Google Access Token successfully received.')
self.log.debug('Google Access Token: %s...',
self._access_token[:25])
return self._access_token
31 changes: 19 additions & 12 deletions aiopogo/auth_ptc.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,10 @@
from .auth import Auth
from .exceptions import ActivationRequiredException, AuthConnectionException, AuthException, AuthTimeoutException, InvalidCredentialsException, ProxyException, SocksError, UnexpectedAuthError


class AuthPtc(Auth):
def __init__(self, username=None, password=None, proxy=None, proxy_auth=None, timeout=None, locale=None):
def __init__(self, username=None, password=None, proxy=None,
proxy_auth=None, timeout=None, locale=None):
Auth.__init__(self)
self.provider = 'ptc'

Expand All @@ -28,17 +30,20 @@ async def user_login(self, username=None, password=None):
self._password = password or self._password

try:
assert isinstance(self._username, str) and isinstance(self._password, str)
assert (isinstance(self._username, str)
and isinstance(self._password, str))
except AssertionError as e:
raise InvalidCredentialsException("Username/password not correctly specified") from e
self.log.info('PTC User Login for: {}'.format(self._username))
raise InvalidCredentialsException(
"Username/password not correctly specified") from e
self.log.info('PTC User Login for: %s', self._username)

try:
now = time()
async with ClientSession(
connector=SESSIONS.get_connector(self.socks),
loop=self.loop,
headers=(('User-Agent', 'niantic'), ('Host', 'sso.pokemon.com')),
headers=(('User-Agent', 'niantic'),
('Host', 'sso.pokemon.com')),
skip_auto_headers=('Accept', 'Accept-Encoding'),
request_class=ProxyClientRequest if self.socks else ClientRequest,
connector_owner=False,
Expand Down Expand Up @@ -74,11 +79,13 @@ async def user_login(self, username=None, password=None):
except (ClientHttpProxyError, ClientProxyConnectionError, SocksError) as e:
raise ProxyException('Proxy connection error during user_login.') from e
except ClientResponseError as e:
raise AuthConnectionException('Error {} during user_login: {}'.format(e.code, e.message))
raise AuthConnectionException('Error {} during user_login: {}'.format(
e.code, e.message))
except (TimeoutError, ServerTimeoutError) as e:
raise AuthTimeoutException('user_login timeout.') from e
except ClientError as e:
raise AuthConnectionException('{} during user_login.'.format(e.__class__.__name__)) from e
raise AuthConnectionException('{} during user_login.'.format(
e.__class__.__name__)) from e
except (AssertionError, TypeError, ValueError) as e:
raise AuthException('Invalid initial JSON response.') from e

Expand All @@ -91,8 +98,8 @@ async def get_access_token(self, force_refresh=False):
if not force_refresh and self.check_access_token():
self.log.debug('Using cached PTC Access Token')
return self._access_token
else:
self._access_token = None
self.authenticated = False
await self.user_login()
return self._access_token

self._access_token = None
self.authenticated = False
await self.user_login()
return self._access_token
5 changes: 1 addition & 4 deletions aiopogo/exceptions.py
Original file line number Diff line number Diff line change
Expand Up @@ -56,9 +56,6 @@ class ExpiredHashKeyException(HashServerException):
class InvalidCredentialsException(AiopogoError, ValueError):
"""Raised when the username, password, or provider are empty/invalid"""

class InvalidCredentialsException(AiopogoError, ValueError):
"""Raised when the username, password, or provider are empty/invalid"""


class MalformedResponseException(AiopogoError):
"""Raised when the response is empty or not in an expected format"""
Expand Down Expand Up @@ -134,6 +131,6 @@ class UnexpectedHashResponseException(UnexpectedResponseException, HashServerExc

class ServerApiEndpointRedirectException(AiopogoError):
"""Raised when the API redirects you to another endpoint"""

def __init__(self, endpoint):
self.endpoint = endpoint

16 changes: 10 additions & 6 deletions aiopogo/hash_server.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,12 @@
from itertools import cycle
from time import time
from logging import getLogger
from struct import pack, unpack

from aiohttp import ClientSession, ClientError, ClientResponseError, ServerConnectionError, ServerTimeoutError

from . import json_dumps, json_loads
from .exceptions import BadHashRequestException, ExpiredHashKeyException, HashingOfflineException, HashingTimeoutException, MalformedHashResponseException, NoHashKeyException, TempHashingBanException, TimeoutException, UnexpectedHashResponseException
from .connector import TimedConnector
from .exceptions import BadHashRequestException, ExpiredHashKeyException, HashingOfflineException, HashingTimeoutException, MalformedHashResponseException, NoHashKeyException, TempHashingBanException, UnexpectedHashResponseException
from .utilities import f2i


Expand All @@ -25,7 +24,8 @@ def __init__(self):
try:
self.instance_token = self.auth_token
except AttributeError:
NoHashKeyException('You must provide a hash key before making a request.')
NoHashKeyException(
'You must provide a hash key before making a request.')

async def hash(self, timestamp, latitude, longitude, accuracy, authticket, sessiondata, requests):
status = self.key_status
Expand Down Expand Up @@ -58,12 +58,14 @@ async def hash(self, timestamp, latitude, longitude, accuracy, authticket, sessi
for attempt in range(2):
try:
async with self._session.post("http://pokehash.buddyauth.com/api/v133_1/hash", headers=headers, json=payload) as resp:
if 400 <= resp.status:
if resp.status >= 400:
if resp.status == 400:
response = await resp.text()
if response == 'Unauthorized':
if self.multi:
self.log.warning('{:.10}... expired, removing from rotation.'.format(self.instance_token))
self.log.warning(
'{:.10}... expired, removing from rotation.'.format(
self.instance_token))
self.remove_token(self.instance_token)
self.instance_token = self.auth_token
if attempt < 1:
Expand All @@ -85,7 +87,9 @@ async def hash(self, timestamp, latitude, longitude, accuracy, authticket, sessi
self.instance_token = self.auth_token
return await self.hash(timestamp, latitude, longitude, accuracy, authticket, sessiondata, requests)
elif e.code >= 500 or e.code == 404:
raise HashingOfflineException('Hashing server error {}: {}'.format(e.code, e.message))
raise HashingOfflineException(
'Hashing server error {}: {}'.format(
e.code, e.message))
else:
raise UnexpectedHashResponseException('Unexpected hash code {}: {}'.format(e.code, e.message))
except ValueError as e:
Expand Down
34 changes: 24 additions & 10 deletions aiopogo/pgoapi.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,8 @@
except ImportError:
class Socks4Auth(Exception):
def __init__(*args, **kwargs):
raise ImportError('You must install aiosocks to use a SOCKS proxy.')
raise ImportError(
'You must install aiosocks to use a SOCKS proxy.')
Socks5Auth = Socks4Auth

from . import __title__, __version__
Expand All @@ -23,7 +24,7 @@ class PGoApi:
log = getLogger(__name__)
log.info('%s v%s', __title__, __version__)

def __init__(self, provider=None, lat=None, lon=None, alt=None, proxy=None, device_info=None):
def __init__(self, lat=None, lon=None, alt=None, proxy=None, device_info=None):
self.auth_provider = None
self.state = RpcState()

Expand All @@ -39,13 +40,20 @@ def __init__(self, provider=None, lat=None, lon=None, alt=None, proxy=None, devi

async def set_authentication(self, provider='ptc', username=None, password=None, timeout=10, locale='en_US', refresh_token=None):
if provider == 'ptc':
self.auth_provider = AuthPtc(username, password, proxy=self._proxy, proxy_auth=self.proxy_auth, timeout=timeout)
self.auth_provider = AuthPtc(
username,
password,
proxy=self._proxy,
proxy_auth=self.proxy_auth,
timeout=timeout)
elif provider == 'google':
self.auth_provider = AuthGoogle(proxy=proxy, refresh_token=refresh_token)
self.auth_provider = AuthGoogle(
proxy=self._proxy, refresh_token=refresh_token)
if refresh_token:
return await self.auth_provider.get_access_token()
else:
raise InvalidCredentialsException("Invalid authentication provider - only ptc/google available.")
raise InvalidCredentialsException(
"Invalid authentication provider - only ptc/google available.")

await self.auth_provider.user_login(username, password)

Expand All @@ -58,7 +66,8 @@ def set_position(self, lat, lon, alt=None):
def create_request(self):
return PGoApiRequest(self)

def activate_hash_server(self, hash_token, conn_limit=300):
@staticmethod
def activate_hash_server(hash_token, conn_limit=300):
HashServer.set_token(hash_token)
HashServer.activate_session(conn_limit)

Expand Down Expand Up @@ -90,13 +99,16 @@ def proxy(self, proxy):
if self._proxy.user:
scheme = self._proxy.scheme
if scheme == 'http':
self.proxy_auth = BasicAuth(self._proxy.user, self._proxy.password)
self.proxy_auth = BasicAuth(
self._proxy.user, self._proxy.password)
elif scheme == 'socks5':
self.proxy_auth = Socks5Auth(self._proxy.user, self._proxy.password)
self.proxy_auth = Socks5Auth(
self._proxy.user, self._proxy.password)
elif scheme == 'socks4':
self.proxy_auth = Socks4Auth(self._proxy.user)
else:
raise ValueError('Proxy protocol must be http, socks5, or socks4.')
raise ValueError(
'Proxy protocol must be http, socks5, or socks4.')

@property
def start_time(self):
Expand Down Expand Up @@ -153,12 +165,14 @@ def list_curr_methods(self):

def __getattr__(self, func):
func = func.upper()

def function(**kwargs):
self.log.debug('Creating a new request...')

try:
if kwargs:
self._req_method_list.append((RequestType.Value(func), kwargs))
self._req_method_list.append(
(RequestType.Value(func), kwargs))
self.log.debug("Arguments of '%s': \n\r%s", func, kwargs)
else:
self._req_method_list.append(RequestType.Value(func))
Expand Down
Loading

0 comments on commit 7ad37e7

Please sign in to comment.