Skip to content

Commit

Permalink
Allow tor usage
Browse files Browse the repository at this point in the history
  • Loading branch information
Tim Schroeder committed Jul 31, 2016
1 parent c360bec commit bc04202
Show file tree
Hide file tree
Showing 7 changed files with 84 additions and 51 deletions.
3 changes: 2 additions & 1 deletion pogom/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,5 +12,6 @@
'REQ_SLEEP': 5,
'REQ_HEAVY_SLEEP': 30,
'REQ_MAX_FAILED': 5,
'PASSWORD': None
'PASSWORD': None,
'USE_TOR': False
}
12 changes: 7 additions & 5 deletions pogom/pgoapi/pgoapi.py
Original file line number Diff line number Diff line change
Expand Up @@ -36,25 +36,27 @@

logger = logging.getLogger(__name__)


class PGoApi:

API_ENTRY = 'https://pgorelease.nianticlabs.com/plfe/rpc'

def __init__(self):
def __init__(self, use_tor=False):

self.log = logging.getLogger(__name__)

self._auth_provider = None
self._api_endpoint = None
self._use_tor = use_tor

self._position_lat = 0
self._position_lng = 0
self._position_alt = 0

self._req_method_list = []

def copy(self):
other = PGoApi()
def copy(self, use_tor=False):
other = PGoApi(use_tor=use_tor)
other.log = self.log
other._auth_provider = self._auth_provider
other._api_endpoint = self._api_endpoint
Expand All @@ -73,8 +75,8 @@ def call(self):
return False

player_position = self.get_position()
request = RpcApi(self._auth_provider)

request = RpcApi(self._auth_provider, self._use_tor)

if self._api_endpoint:
api_endpoint = self._api_endpoint
Expand Down
20 changes: 13 additions & 7 deletions pogom/pgoapi/rpc_api.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,30 +24,36 @@
"""

import logging
import requests
import subprocess
import requesocks
import requests

from exceptions import NotLoggedInException, ServerBusyOrOfflineException

from google.protobuf.message import DecodeError
from protobuf_to_dict import protobuf_to_dict
from utilities import h2f, to_camel_case, get_class
from utilities import to_camel_case, get_class

import protos.RpcEnum_pb2 as RpcEnum
import protos.RpcEnvelope_pb2 as RpcEnvelope

class RpcApi:

def __init__(self, auth_provider):
def __init__(self, auth_provider, use_tor=False):

self.log = logging.getLogger(__name__)

self._session = requests.session()

if use_tor:
self._session = requesocks.session()
self._session.proxies = {'http': 'socks5://127.0.0.1:9050',
'https': 'socks5://127.0.0.1:9050'}
else:
self._session = requests.session()
self._session.headers.update({'User-Agent': 'Niantic App'})
self._session.verify = True

self._auth_provider = auth_provider

def get_rpc_id(self):
return 8145806132888207460

Expand All @@ -67,7 +73,7 @@ def _make_rpc(self, endpoint, request_proto_plain):
request_proto_serialized = request_proto_plain.SerializeToString()
try:
http_response = self._session.post(endpoint, data=request_proto_serialized)
except requests.exceptions.ConnectionError as e:
except (requests.exceptions.ConnectionError, requesocks.exceptions.ConnectionError):
raise ServerBusyOrOfflineException

return http_response
Expand Down
69 changes: 40 additions & 29 deletions pogom/search.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,9 @@
from . import config
from .models import parse_map

from stem import Signal
from stem.control import Controller

log = logging.getLogger(__name__)

TIMESTAMP = '\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000'
Expand All @@ -34,14 +37,9 @@
search_queue = Queue()


def calculate_lng_degrees(lat):
return float(lng_gap_meters) / \
(meters_per_degree * math.cos(math.radians(lat)))


def send_map_request(api, position):
def send_map_request(api_target, position, use_tor):
try:
api_copy = api.copy()
api_copy = api_target.copy(use_tor=use_tor)
api_copy.set_position(*position)
api_copy.get_map_objects(latitude=f2i(position[0]),
longitude=f2i(position[1]),
Expand All @@ -52,25 +50,27 @@ def send_map_request(api, position):
log.warning("Uncaught exception when downloading map " + str(e))
return False


def get_new_coords(init_loc, distance, bearing):
""" Given an initial lat/lng, a distance(in kms), and a bearing (degrees),
this will calculate the resulting lat/lng coordinates.
"""
R = 6378.1 #km radius of the earth
"""
R = 6378.1 # km radius of the earth
bearing = math.radians(bearing)

init_coords = [math.radians(init_loc[0]), math.radians(init_loc[1])] # convert lat/lng to radians
init_coords = [math.radians(init_loc[0]), math.radians(init_loc[1])] # convert lat/lng to radians

new_lat = math.asin( math.sin(init_coords[0])*math.cos(distance/R) +
math.cos(init_coords[0])*math.sin(distance/R)*math.cos(bearing))
new_lat = math.asin(math.sin(init_coords[0])*math.cos(distance/R) +
math.cos(init_coords[0])*math.sin(distance/R)*math.cos(bearing))

new_lon = init_coords[1] + math.atan2(math.sin(bearing)*math.sin(distance/R)*math.cos(init_coords[0]),
math.cos(distance/R)-math.sin(init_coords[0])*math.sin(new_lat))
math.cos(distance/R)-math.sin(init_coords[0])*math.sin(new_lat))

return [math.degrees(new_lat), math.degrees(new_lon)]


def generate_location_steps(initial_loc, step_count):
#Bearing (degrees)
# Bearing (degrees)
NORTH = 0
EAST = 90
SOUTH = 180
Expand All @@ -80,30 +80,30 @@ def generate_location_steps(initial_loc, step_count):
xdist = math.sqrt(3)*pulse_radius # dist between column centers
ydist = 3*(pulse_radius/2) # dist between row centers

yield (initial_loc[0], initial_loc[1], 0) #insert initial location
yield (initial_loc[0], initial_loc[1], 0) # insert initial location

ring = 1
ring = 1
loc = initial_loc
while ring < step_count:
#Set loc to start at top left
# Set loc to start at top left
loc = get_new_coords(loc, ydist, NORTH)
loc = get_new_coords(loc, xdist/2, WEST)
for direction in range(6):
for i in range(ring):
if direction == 0: # RIGHT
if direction == 0: # RIGHT
loc = get_new_coords(loc, xdist, EAST)
if direction == 1: # DOWN + RIGHT
if direction == 1: # DOWN + RIGHT
loc = get_new_coords(loc, ydist, SOUTH)
loc = get_new_coords(loc, xdist/2, EAST)
if direction == 2: # DOWN + LEFT
if direction == 2: # DOWN + LEFT
loc = get_new_coords(loc, ydist, SOUTH)
loc = get_new_coords(loc, xdist/2, WEST)
if direction == 3: # LEFT
if direction == 3: # LEFT
loc = get_new_coords(loc, xdist, WEST)
if direction == 4: # UP + LEFT
if direction == 4: # UP + LEFT
loc = get_new_coords(loc, ydist, NORTH)
loc = get_new_coords(loc, xdist/2, WEST)
if direction == 5: # UP + RIGHT
if direction == 5: # UP + RIGHT
loc = get_new_coords(loc, ydist, NORTH)
loc = get_new_coords(loc, xdist/2, EAST)
yield (loc[0], loc[1], 0)
Expand Down Expand Up @@ -148,29 +148,29 @@ def search_thread(q):
q.task_done()
continue

log.debug("{}: processing itteration {} step {}".format(threadname, i, step))
log.debug("{}: processing iteration {} step {}".format(threadname, i, step))
response_dict = {}
failed_consecutive = 0
while not response_dict:
response_dict = send_map_request(api, step_location)
response_dict = send_map_request(api, step_location, config['USE_TOR'])
if response_dict:
with lock:
try:
parse_map(response_dict, i, step, step_location)
log.debug("{}: itteration {} step {} complete".format(threadname, i, step))
log.debug("{}: iteration {} step {} complete".format(threadname, i, step))
except KeyError:
log.error('Search thread failed. Response dictionary key error')
log.debug('{}: itteration {} step {} failed. Response dictionary\
log.debug('{}: iteration {} step {} failed. Response dictionary\
key error.'.format(threadname, i, step))
failed_consecutive += 1
if(failed_consecutive >= config['REQ_MAX_FAILED']):
if failed_consecutive >= config['REQ_MAX_FAILED']:
log.error('Niantic servers under heavy load. Waiting before trying again')
time.sleep(config['REQ_HEAVY_SLEEP'])
failed_consecutive = 0
response_dict = {}
else:
log.info('Map download failed, waiting and retrying')
log.debug('{}: itteration {} step {} failed'.format(threadname, i, step))
log.debug('{}: iteration {} step {} failed'.format(threadname, i, step))
time.sleep(config['REQ_SLEEP'])

time.sleep(config['REQ_SLEEP'])
Expand All @@ -184,6 +184,8 @@ def search_loop(args):
i = 0
while True:
log.info("Search loop {} starting".format(i))
if args.use_tor:
renew_connection(args)
try:
search(args, i)
log.info("Search loop {} complete.".format(i))
Expand Down Expand Up @@ -244,3 +246,12 @@ def fake_search_loop():
while True:
log.info('Fake search loop running...')
time.sleep(10)


#
# Get a new Tor Connection to change up the IP
#
def renew_connection(args):
with Controller.from_port(port=9051) as controller:
controller.authenticate(password=args.tor_password)
controller.signal(Signal.NEWNYM)
16 changes: 14 additions & 2 deletions pogom/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,9 @@ def get_args():
parser.add_argument('-nk', '--no-pokestops',
help='Disables PokeStops from the map (including parsing them into local db)',
action='store_true', default=False)
parser.add_argument('-ut', '--use-tor', help='Enables the use of tor on api calls',
action='store_true', default=False)
parser.add_argument('-tp', '--tor-password', help='Password for tor controller')
parser.add_argument('--db-type', help='Type of database to be used (default: sqlite)',
default='sqlite')
parser.add_argument('--db-name', help='Name of the database to be used')
Expand All @@ -110,13 +113,15 @@ def get_args():

args = parser.parse_args()

config['USE_TOR'] = args.use_tor

if args.only_server:
if args.location is None:
parser.print_usage()
print sys.argv[0] + ': error: arguments -l/--location is required'
sys.exit(1)
else:
if (args.username is None or args.location is None or args.step_limit is None):
if args.username is None or args.location is None or args.step_limit is None:
parser.print_usage()
print sys.argv[0] + ': error: arguments -u/--username, -l/--location, -st/--step-limit are required'
sys.exit(1)
Expand Down Expand Up @@ -180,9 +185,11 @@ def insert_mock_data():
gym_points=1000
)


def i8ln(word):
log.debug("Translating: %s", word)
if config['LOCALE'] == "en": return word
if config['LOCALE'] == "en":
return word
if not hasattr(i8ln, 'dictionary'):
file_path = os.path.join(
config['ROOT_PATH'],
Expand All @@ -201,6 +208,7 @@ def i8ln(word):
log.debug("Unable to find translation!")
return word


def get_pokemon_data(pokemon_id):
if not hasattr(get_pokemon_data, 'pokemon'):
file_path = os.path.join(
Expand All @@ -212,16 +220,20 @@ def get_pokemon_data(pokemon_id):
get_pokemon_data.pokemon = json.loads(f.read())
return get_pokemon_data.pokemon[str(pokemon_id)]


def get_pokemon_name(pokemon_id):
return i8ln(get_pokemon_data(pokemon_id)['name'])


def get_pokemon_rarity(pokemon_id):
return i8ln(get_pokemon_data(pokemon_id)['rarity'])


def get_pokemon_types(pokemon_id):
pokemon_types = get_pokemon_data(pokemon_id)['types']
return map(lambda x: {"type": i8ln(x['type']), "color": x['color']}, pokemon_types)


def send_to_webhook(message_type, message):
args = get_args()

Expand Down
2 changes: 2 additions & 0 deletions requirements.txt
Original file line number Diff line number Diff line change
Expand Up @@ -17,3 +17,5 @@ PyMySQL==0.7.5
flask-cors==2.1.2
flask-compress==1.3.0
LatLon==1.0.1
stem==1.4.0
requesocks==0.10.8
13 changes: 6 additions & 7 deletions runserver.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,15 +27,15 @@
args = get_args()

if args.debug:
log.setLevel(logging.DEBUG);
log.setLevel(logging.DEBUG)
else:
log.setLevel(logging.INFO);
log.setLevel(logging.INFO)

# Let's not forget to run Grunt / Only needed when running with webserver
if not args.no_server:
if not os.path.exists(os.path.join(os.path.dirname(__file__), 'static/dist')):
log.critical('Please run "grunt build" before starting the server.');
sys.exit();
log.critical('Please run "grunt build" before starting the server.')
sys.exit()

# These are very noisey, let's shush them up a bit
logging.getLogger("peewee").setLevel(logging.INFO)
Expand All @@ -54,7 +54,6 @@
logging.getLogger("pgoapi").setLevel(logging.DEBUG)
logging.getLogger("rpc_api").setLevel(logging.DEBUG)


position = get_pos_by_name(args.location)
if not any(position):
log.error('Could not get a position by name, aborting.')
Expand Down Expand Up @@ -84,7 +83,7 @@
create_tables(db)

if not args.only_server:
# Gather the pokemons!
# Gather the pokemon!
if not args.mock:
log.debug('Starting a real search thread and {} search runner thread(s)'.format(args.num_threads))
create_search_threads(args.num_threads)
Expand All @@ -99,7 +98,7 @@
search_thread.start()

if args.cors:
CORS(app);
CORS(app)

config['ROOT_PATH'] = app.root_path
config['GMAPS_KEY'] = args.gmaps_key
Expand Down

0 comments on commit bc04202

Please sign in to comment.