Advertisement
Guest User

Untitled

a guest
Jul 20th, 2016
151
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 29.89 KB | None | 0 0
  1. #!/usr/bin/python
  2. # -*- coding: utf-8 -*-
  3.  
  4. import flask
  5. from flask import Flask, render_template
  6. from flask_googlemaps import GoogleMaps
  7. from flask_googlemaps import Map
  8. from flask_googlemaps import icons
  9. import os
  10. import re
  11. import sys
  12. import struct
  13. import json
  14. import requests
  15. import argparse
  16. import getpass
  17. import threading
  18. import werkzeug.serving
  19. import pokemon_pb2
  20. import time
  21. import winsound
  22. from google.protobuf.internal import encoder
  23. from google.protobuf.message import DecodeError
  24. from s2sphere import *
  25. from datetime import datetime
  26. from geopy.geocoders import GoogleV3
  27. from gpsoauth import perform_master_login, perform_oauth
  28. from geopy.exc import GeocoderTimedOut, GeocoderServiceError
  29. from requests.packages.urllib3.exceptions import InsecureRequestWarning
  30. from requests.adapters import ConnectionError
  31. from requests.models import InvalidURL
  32. from transform import *
  33.  
  34. requests.packages.urllib3.disable_warnings(InsecureRequestWarning)
  35.  
  36. API_URL = 'https://pgorelease.nianticlabs.com/plfe/rpc'
  37. LOGIN_URL = \
  38.     'https://sso.pokemon.com/sso/login?service=https://sso.pokemon.com/sso/oauth2.0/callbackAuthorize'
  39. LOGIN_OAUTH = 'https://sso.pokemon.com/sso/oauth2.0/accessToken'
  40. APP = 'com.nianticlabs.pokemongo'
  41.  
  42. with open('credentials.json') as file:
  43.     credentials = json.load(file)
  44.  
  45. PTC_CLIENT_SECRET = credentials.get('ptc_client_secret', None)
  46. ANDROID_ID = credentials.get('android_id', None)
  47. SERVICE = credentials.get('service', None)
  48. CLIENT_SIG = credentials.get('client_sig', None)
  49. GOOGLEMAPS_KEY = credentials.get('gmaps_key', None)
  50.  
  51. SESSION = requests.session()
  52. SESSION.headers.update({'User-Agent': 'Niantic App'})
  53. SESSION.verify = False
  54.  
  55. global_password = None
  56. global_token = None
  57. access_token = None
  58. DEBUG = True
  59. VERBOSE_DEBUG = False  # if you want to write raw request/response to the console
  60. COORDS_LATITUDE = 0
  61. COORDS_LONGITUDE = 0
  62. COORDS_ALTITUDE = 0
  63. FLOAT_LAT = 0
  64. FLOAT_LONG = 0
  65. NEXT_LAT = 0
  66. NEXT_LONG = 0
  67. auto_refresh = 0
  68. default_step = 0.001
  69. api_endpoint = None
  70. pokemons = {}
  71. gyms = {}
  72. pokestops = {}
  73. numbertoteam = {  # At least I'm pretty sure that's it. I could be wrong and then I'd be displaying the wrong owner team of gyms.
  74.     0: 'Gym',
  75.     1: 'Mystic',
  76.     2: 'Valor',
  77.     3: 'Instinct',
  78. }
  79. origin_lat, origin_lon = None, None
  80. is_ampm_clock = False
  81.  
  82. # stuff for in-background search thread
  83.  
  84. search_thread = None
  85.  
  86. def memoize(obj):
  87.     cache = obj.cache = {}
  88.  
  89.     @functools.wraps(obj)
  90.     def memoizer(*args, **kwargs):
  91.         key = str(args) + str(kwargs)
  92.         if key not in cache:
  93.             cache[key] = obj(*args, **kwargs)
  94.         return cache[key]
  95.     return memoizer
  96.  
  97. def parse_unicode(bytestring):
  98.     decoded_string = bytestring.decode(sys.getfilesystemencoding())
  99.     return decoded_string
  100.  
  101.  
  102. def debug(message):
  103.     if DEBUG:
  104.         print '[-] {}'.format(message)
  105.  
  106.  
  107. def time_left(ms):
  108.     s = ms / 1000
  109.     (m, s) = divmod(s, 60)
  110.     (h, m) = divmod(m, 60)
  111.     return (h, m, s)
  112.  
  113.  
  114. def encode(cellid):
  115.     output = []
  116.     encoder._VarintEncoder()(output.append, cellid)
  117.     return ''.join(output)
  118.  
  119.  
  120. def getNeighbors():
  121.     origin = CellId.from_lat_lng(LatLng.from_degrees(FLOAT_LAT,
  122.                                                      FLOAT_LONG)).parent(15)
  123.     walk = [origin.id()]
  124.  
  125.     # 10 before and 10 after
  126.  
  127.     next = origin.next()
  128.     prev = origin.prev()
  129.     for i in range(10):
  130.         walk.append(prev.id())
  131.         walk.append(next.id())
  132.         next = next.next()
  133.         prev = prev.prev()
  134.     return walk
  135.  
  136.  
  137. def f2i(float):
  138.     return struct.unpack('<Q', struct.pack('<d', float))[0]
  139.  
  140.  
  141. def f2h(float):
  142.     return hex(struct.unpack('<Q', struct.pack('<d', float))[0])
  143.  
  144.  
  145. def h2f(hex):
  146.     return struct.unpack('<d', struct.pack('<Q', int(hex, 16)))[0]
  147.  
  148.  
  149. def retrying_set_location(location_name):
  150.     """
  151.    Continue trying to get co-ords from Google Location until we have them
  152.    :param location_name: string to pass to Location API
  153.    :return: None
  154.    """
  155.  
  156.     while True:
  157.         try:
  158.             set_location(location_name)
  159.             return
  160.         except (GeocoderTimedOut, GeocoderServiceError), e:
  161.             debug(
  162.                 'retrying_set_location: geocoder exception ({}), retrying'.format(
  163.                     str(e)))
  164.         time.sleep(1.25)
  165.  
  166.  
  167. def set_location(location_name):
  168.     geolocator = GoogleV3()
  169.     prog = re.compile('^(\-?\d+(\.\d+)?),\s*(\-?\d+(\.\d+)?)$')
  170.     global origin_lat
  171.     global origin_lon
  172.     if prog.match(location_name):
  173.         local_lat, local_lng = [float(x) for x in location_name.split(",")]
  174.         alt = 0
  175.         origin_lat, origin_lon = local_lat, local_lng
  176.     else:
  177.         loc = geolocator.geocode(location_name)
  178.         origin_lat, origin_lon = local_lat, local_lng = loc.latitude, loc.longitude
  179.         alt = loc.altitude
  180.         print '[!] Your given location: {}'.format(loc.address.encode('utf-8'))
  181.  
  182.     print('[!] lat/long/alt: {} {} {}'.format(local_lat, local_lng, alt))
  183.     set_location_coords(local_lat, local_lng, alt)
  184.  
  185.  
  186. def set_location_coords(lat, long, alt):
  187.     global COORDS_LATITUDE, COORDS_LONGITUDE, COORDS_ALTITUDE
  188.     global FLOAT_LAT, FLOAT_LONG
  189.     FLOAT_LAT = lat
  190.     FLOAT_LONG = long
  191.     COORDS_LATITUDE = f2i(lat)  # 0x4042bd7c00000000 # f2i(lat)
  192.     COORDS_LONGITUDE = f2i(long)  # 0xc05e8aae40000000 #f2i(long)
  193.     COORDS_ALTITUDE = f2i(alt)
  194.  
  195.  
  196. def get_location_coords():
  197.     return (COORDS_LATITUDE, COORDS_LONGITUDE, COORDS_ALTITUDE)
  198.  
  199.  
  200. def retrying_api_req(service, api_endpoint, access_token, *args, **kwargs):
  201.     while True:
  202.         try:
  203.             response = api_req(service, api_endpoint, access_token, *args,
  204.                                **kwargs)
  205.             if response:
  206.                 return response
  207.             debug('retrying_api_req: api_req returned None, retrying')
  208.         except (InvalidURL, ConnectionError, DecodeError), e:
  209.             debug('retrying_api_req: request error ({}), retrying'.format(
  210.                 str(e)))
  211.         time.sleep(1)
  212.  
  213.  
  214. def api_req(service, api_endpoint, access_token, *args, **kwargs):
  215.     p_req = pokemon_pb2.RequestEnvelop()
  216.     p_req.rpc_id = 1469378659230941192
  217.  
  218.     p_req.unknown1 = 2
  219.  
  220.     (p_req.latitude, p_req.longitude, p_req.altitude) = \
  221.         get_location_coords()
  222.  
  223.     p_req.unknown12 = 989
  224.  
  225.     if 'useauth' not in kwargs or not kwargs['useauth']:
  226.         p_req.auth.provider = service
  227.         p_req.auth.token.contents = access_token
  228.         p_req.auth.token.unknown13 = 14
  229.     else:
  230.         p_req.unknown11.unknown71 = kwargs['useauth'].unknown71
  231.         p_req.unknown11.unknown72 = kwargs['useauth'].unknown72
  232.         p_req.unknown11.unknown73 = kwargs['useauth'].unknown73
  233.  
  234.     for arg in args:
  235.         p_req.MergeFrom(arg)
  236.  
  237.     protobuf = p_req.SerializeToString()
  238.  
  239.     r = SESSION.post(api_endpoint, data=protobuf, verify=False)
  240.  
  241.     p_ret = pokemon_pb2.ResponseEnvelop()
  242.     p_ret.ParseFromString(r.content)
  243.  
  244.     if VERBOSE_DEBUG:
  245.         print 'REQUEST:'
  246.         print p_req
  247.         print 'Response:'
  248.         print p_ret
  249.         print '''
  250.  
  251. '''
  252.     time.sleep(0.51)
  253.     return p_ret
  254.  
  255.  
  256. def get_api_endpoint(service, access_token, api=API_URL):
  257.     profile_response = None
  258.     while not profile_response:
  259.         profile_response = retrying_get_profile(service, access_token, api,
  260.                                                 None)
  261.         if not hasattr(profile_response, 'api_url'):
  262.             debug(
  263.                 'retrying_get_profile: get_profile returned no api_url, retrying')
  264.             profile_response = None
  265.             continue
  266.         if not len(profile_response.api_url):
  267.             debug(
  268.                 'get_api_endpoint: retrying_get_profile returned no-len api_url, retrying')
  269.             profile_response = None
  270.  
  271.     return 'https://%s/rpc' % profile_response.api_url
  272.  
  273. def retrying_get_profile(service, access_token, api, useauth, *reqq):
  274.     profile_response = None
  275.     while not profile_response:
  276.         profile_response = get_profile(service, access_token, api, useauth,
  277.                                        *reqq)
  278.         if not hasattr(profile_response, 'payload'):
  279.             debug(
  280.                 'retrying_get_profile: get_profile returned no payload, retrying')
  281.             profile_response = None
  282.             continue
  283.         if not profile_response.payload:
  284.             debug(
  285.                 'retrying_get_profile: get_profile returned no-len payload, retrying')
  286.             profile_response = None
  287.  
  288.     return profile_response
  289.  
  290. def get_profile(service, access_token, api, useauth, *reqq):
  291.     req = pokemon_pb2.RequestEnvelop()
  292.     req1 = req.requests.add()
  293.     req1.type = 2
  294.     if len(reqq) >= 1:
  295.         req1.MergeFrom(reqq[0])
  296.  
  297.     req2 = req.requests.add()
  298.     req2.type = 126
  299.     if len(reqq) >= 2:
  300.         req2.MergeFrom(reqq[1])
  301.  
  302.     req3 = req.requests.add()
  303.     req3.type = 4
  304.     if len(reqq) >= 3:
  305.         req3.MergeFrom(reqq[2])
  306.  
  307.     req4 = req.requests.add()
  308.     req4.type = 129
  309.     if len(reqq) >= 4:
  310.         req4.MergeFrom(reqq[3])
  311.  
  312.     req5 = req.requests.add()
  313.     req5.type = 5
  314.     if len(reqq) >= 5:
  315.         req5.MergeFrom(reqq[4])
  316.     return retrying_api_req(service, api, access_token, req, useauth=useauth)
  317.  
  318. def login_google(username, password):
  319.     print '[!] Google login for: {}'.format(username)
  320.     r1 = perform_master_login(username, password, ANDROID_ID)
  321.     r2 = perform_oauth(username,
  322.                        r1.get('Token', ''),
  323.                        ANDROID_ID,
  324.                        SERVICE,
  325.                        APP,
  326.                        CLIENT_SIG, )
  327.     return r2.get('Auth')
  328.  
  329. def login_ptc(username, password):
  330.     print '[!] PTC login for: {}'.format(username)
  331.     head = {'User-Agent': 'Niantic App'}
  332.     r = SESSION.get(LOGIN_URL, headers=head)
  333.     if r is None:
  334.         return render_template('nope.html', fullmap=fullmap)
  335.  
  336.     try:
  337.         jdata = json.loads(r.content)
  338.     except ValueError, e:
  339.         debug('login_ptc: could not decode JSON from {}'.format(r.content))
  340.         return None
  341.  
  342.     # Maximum password length is 15 (sign in page enforces this limit, API does not)
  343.  
  344.     if len(password) > 15:
  345.         print '[!] Trimming password to 15 characters'
  346.         password = password[:15]
  347.  
  348.     data = {
  349.         'lt': jdata['lt'],
  350.         'execution': jdata['execution'],
  351.         '_eventId': 'submit',
  352.         'username': username,
  353.         'password': password,
  354.     }
  355.     r1 = SESSION.post(LOGIN_URL, data=data, headers=head)
  356.  
  357.     ticket = None
  358.     try:
  359.         ticket = re.sub('.*ticket=', '', r1.history[0].headers['Location'])
  360.     except Exception, e:
  361.         if DEBUG:
  362.             print r1.json()['errors'][0]
  363.         return None
  364.  
  365.     data1 = {
  366.         'client_id': 'mobile-app_pokemon-go',
  367.         'redirect_uri': 'https://www.nianticlabs.com/pokemongo/error',
  368.         'client_secret': PTC_CLIENT_SECRET,
  369.         'grant_type': 'refresh_token',
  370.         'code': ticket,
  371.     }
  372.     r2 = SESSION.post(LOGIN_OAUTH, data=data1)
  373.     access_token = re.sub('&expires.*', '', r2.content)
  374.     access_token = re.sub('.*access_token=', '', access_token)
  375.  
  376.     return access_token
  377.  
  378.  
  379. def get_heartbeat(service,
  380.                   api_endpoint,
  381.                   access_token,
  382.                   response, ):
  383.     m4 = pokemon_pb2.RequestEnvelop.Requests()
  384.     m = pokemon_pb2.RequestEnvelop.MessageSingleInt()
  385.     m.f1 = int(time.time() * 1000)
  386.     m4.message = m.SerializeToString()
  387.     m5 = pokemon_pb2.RequestEnvelop.Requests()
  388.     m = pokemon_pb2.RequestEnvelop.MessageSingleString()
  389.     m.bytes = '05daf51635c82611d1aac95c0b051d3ec088a930'
  390.     m5.message = m.SerializeToString()
  391.     walk = sorted(getNeighbors())
  392.     m1 = pokemon_pb2.RequestEnvelop.Requests()
  393.     m1.type = 106
  394.     m = pokemon_pb2.RequestEnvelop.MessageQuad()
  395.     m.f1 = ''.join(map(encode, walk))
  396.     m.f2 = \
  397.         "\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000"
  398.     m.lat = COORDS_LATITUDE
  399.     m.long = COORDS_LONGITUDE
  400.     m1.message = m.SerializeToString()
  401.     response = get_profile(service,
  402.                            access_token,
  403.                            api_endpoint,
  404.                            response.unknown7,
  405.                            m1,
  406.                            pokemon_pb2.RequestEnvelop.Requests(),
  407.                            m4,
  408.                            pokemon_pb2.RequestEnvelop.Requests(),
  409.                            m5, )
  410.  
  411.     try:
  412.         payload = response.payload[0]
  413.     except (AttributeError, IndexError):
  414.         return
  415.  
  416.     heartbeat = pokemon_pb2.ResponseEnvelop.HeartbeatPayload()
  417.     heartbeat.ParseFromString(payload)
  418.     return heartbeat
  419.  
  420. def get_token(service, username, password):
  421.     """
  422.    Get token if it's not None
  423.    :return:
  424.    :rtype:
  425.    """
  426.  
  427.     global global_token
  428.     if global_token is None:
  429.         if service == 'ptc':
  430.             global_token = login_ptc(username, password)
  431.         else:
  432.             global_token = login_google(username, password)
  433.         return global_token
  434.     else:
  435.         return global_token
  436.  
  437.  
  438. def get_args():
  439.     parser = argparse.ArgumentParser()
  440.     parser.add_argument(
  441.         '-a', '--auth_service', type=str.lower, help='Auth Service', default='ptc')
  442.     parser.add_argument('-u', '--username', help='Username', required=True)
  443.     parser.add_argument('-p', '--password', help='Password', required=False)
  444.     parser.add_argument(
  445.         '-l', '--location', type=parse_unicode, help='Location', required=True)
  446.     parser.add_argument('-st', '--step-limit', help='Steps', required=True)
  447.     group = parser.add_mutually_exclusive_group(required=False)
  448.     group.add_argument(
  449.         '-i', '--ignore', help='Comma-separated list of Pokémon names or IDs to ignore')
  450.     group.add_argument(
  451.         '-o', '--only', help='Comma-separated list of Pokémon names or IDs to search')
  452.     group.add_argument(
  453.         '-n', '--notifyMe', help='Comma-separated list of Pokémon names or IDs to notify')
  454.     parser.add_argument(
  455.         "-ar",
  456.         "--auto_refresh",
  457.         help="Enables an autorefresh that behaves the same as a page reload. " +
  458.              "Needs an integer value for the amount of seconds")
  459.     parser.add_argument(
  460.         '-dp',
  461.         '--display-pokestop',
  462.         help='Display pokéstop',
  463.         action='store_true',
  464.         default=False)
  465.     parser.add_argument(
  466.         '-dg',
  467.         '--display-gym',
  468.         help='Display Gym',
  469.         action='store_true',
  470.         default=False)
  471.     parser.add_argument(
  472.         '-H',
  473.         '--host',
  474.         help='Set web server listening host',
  475.         default='127.0.0.1')
  476.     parser.add_argument(
  477.         '-P',
  478.         '--port',
  479.         type=int,
  480.         help='Set web server listening port',
  481.         default=5000)
  482.     parser.add_argument(
  483.         "-L",
  484.         "--locale",
  485.         help="Locale for Pokemon names: default en, check locale folder for more options",
  486.         default="en")
  487.     parser.add_argument(
  488.         "-ol",
  489.         "--onlylure",
  490.         help='Display only lured pokéstop',
  491.         action='store_true')
  492.     parser.add_argument(
  493.         '-c',
  494.         '--china',
  495.         help='Coordinates transformer for China',
  496.         action='store_true')
  497.     parser.add_argument(
  498.         "-pm",
  499.         "--ampm_clock",
  500.         help="Toggles the AM/PM clock for Pokemon timers",
  501.         action='store_true',
  502.         default=False)
  503.     parser.add_argument(
  504.         '-d', '--debug', help='Debug Mode', action='store_true')
  505.     parser.set_defaults(DEBUG=True)
  506.     return parser.parse_args()
  507.  
  508. @memoize
  509. def login(args):
  510.     global global_password
  511.     if not global_password:
  512.       if args.password:
  513.         global_password = args.password
  514.       else:
  515.         global_password = getpass.getpass()
  516.  
  517.     access_token = get_token(args.auth_service, args.username, global_password)
  518.     if access_token is None:
  519.         raise Exception('[-] Wrong username/password')
  520.  
  521.     print '[+] RPC Session Token: {} ...'.format(access_token[:25])
  522.  
  523.     api_endpoint = get_api_endpoint(args.auth_service, access_token)
  524.     if api_endpoint is None:
  525.         raise Exception('[-] RPC server offline')
  526.  
  527.     print '[+] Received API endpoint: {}'.format(api_endpoint)
  528.  
  529.     profile_response = retrying_get_profile(args.auth_service, access_token,
  530.                                             api_endpoint, None)
  531.     if profile_response is None or not profile_response.payload:
  532.         raise Exception('Could not get profile')
  533.  
  534.     print '[+] Login successful'
  535.  
  536.     payload = profile_response.payload[0]
  537.     profile = pokemon_pb2.ResponseEnvelop.ProfilePayload()
  538.     profile.ParseFromString(payload)
  539.     print '[+] Username: {}'.format(profile.profile.username)
  540.  
  541.     creation_time = \
  542.         datetime.fromtimestamp(int(profile.profile.creation_time)
  543.                                / 1000)
  544.     print '[+] You started playing Pokemon Go on: {}'.format(
  545.         creation_time.strftime('%Y-%m-%d %H:%M:%S'))
  546.  
  547.     for curr in profile.profile.currency:
  548.         print '[+] {}: {}'.format(curr.type, curr.amount)
  549.  
  550.     return api_endpoint, access_token, profile_response
  551.  
  552. def main():
  553.     full_path = os.path.realpath(__file__)
  554.     (path, filename) = os.path.split(full_path)
  555.  
  556.     args = get_args()
  557.  
  558.     if args.auth_service not in ['ptc', 'google']:
  559.         print '[!] Invalid Auth service specified'
  560.         return
  561.  
  562.     print('[+] Locale is ' + args.locale)
  563.     pokemonsJSON = json.load(
  564.         open(path + '/locales/pokemon.' + args.locale + '.json'))
  565.  
  566.     if args.debug:
  567.         global DEBUG
  568.         DEBUG = True
  569.         print '[!] DEBUG mode on'
  570.  
  571.     # only get location for first run
  572.     if not (FLOAT_LAT and FLOAT_LONG):
  573.       print('[+] Getting initial location')
  574.       retrying_set_location(args.location)
  575.  
  576.     if args.auto_refresh:
  577.         global auto_refresh
  578.         auto_refresh = int(args.auto_refresh) * 1000
  579.  
  580.     if args.ampm_clock:
  581.         global is_ampm_clock
  582.         is_ampm_clock = True
  583.  
  584.     api_endpoint, access_token, profile_response = login(args)
  585.  
  586.     clear_stale_pokemons()
  587.  
  588.     steplimit = int(args.step_limit)
  589.  
  590.     ignore = []
  591.     only = []
  592.     notifyMe = []
  593.     if args.ignore:
  594.         ignore = [i.lower().strip() for i in args.ignore.split(',')]
  595.     elif args.only:
  596.         only = [i.lower().strip() for i in args.only.split(',')]
  597.     elif args.notifyMe:
  598.         notifyMe = [i.lower().strip() for i in args.notifyMe.split(',')]
  599.  
  600.     pos = 1
  601.     x = 0
  602.     y = 0
  603.     dx = 0
  604.     dy = -1
  605.     steplimit2 = steplimit**2
  606.     for step in range(steplimit2):
  607.         #starting at 0 index
  608.         debug('looping: step {} of {}'.format((step+1), steplimit**2))
  609.         #debug('steplimit: {} x: {} y: {} pos: {} dx: {} dy {}'.format(steplimit2, x, y, pos, dx, dy))
  610.         # Scan location math
  611.         if -steplimit2 / 2 < x <= steplimit2 / 2 and -steplimit2 / 2 < y <= steplimit2 / 2:
  612.             set_location_coords(x * 0.0025 + origin_lat, y * 0.0025 + origin_lon, 0)
  613.         if x == y or x < 0 and x == -y or x > 0 and x == 1 - y:
  614.             (dx, dy) = (-dy, dx)
  615.  
  616.         (x, y) = (x + dx, y + dy)
  617.  
  618.         process_step(args, api_endpoint, access_token, profile_response,
  619.                      pokemonsJSON, ignore, only, notifyMe)
  620.  
  621.         print('Completed: ' + str(
  622.             ((step+1) + pos * .25 - .25) / (steplimit2) * 100) + '%')
  623.  
  624.     global NEXT_LAT, NEXT_LONG
  625.     if (NEXT_LAT and NEXT_LONG and
  626.             (NEXT_LAT != FLOAT_LAT or NEXT_LONG != FLOAT_LONG)):
  627.         print('Update to next location %f, %f' % (NEXT_LAT, NEXT_LONG))
  628.         set_location_coords(NEXT_LAT, NEXT_LONG, 0)
  629.         NEXT_LAT = 0
  630.         NEXT_LONG = 0
  631.     else:
  632.         set_location_coords(origin_lat, origin_lon, 0)
  633.  
  634.     register_background_thread()
  635.  
  636.  
  637. def process_step(args, api_endpoint, access_token, profile_response,
  638.                  pokemonsJSON, ignore, only, notifyMe):
  639.     print('[+] Searching for Pokemon at location {} {}'.format(FLOAT_LAT, FLOAT_LONG))
  640.     origin = LatLng.from_degrees(FLOAT_LAT, FLOAT_LONG)
  641.     step_lat = FLOAT_LAT
  642.     step_long = FLOAT_LONG
  643.     parent = CellId.from_lat_lng(LatLng.from_degrees(FLOAT_LAT,
  644.                                                      FLOAT_LONG)).parent(15)
  645.     h = get_heartbeat(args.auth_service, api_endpoint, access_token,
  646.                       profile_response)
  647.     hs = [h]
  648.     seen = {}
  649.  
  650.     for child in parent.children():
  651.         latlng = LatLng.from_point(Cell(child).get_center())
  652.         set_location_coords(latlng.lat().degrees, latlng.lng().degrees, 0)
  653.         hs.append(
  654.             get_heartbeat(args.auth_service, api_endpoint, access_token,
  655.                           profile_response))
  656.     set_location_coords(step_lat, step_long, 0)
  657.     visible = []
  658.  
  659.     for hh in hs:
  660.         try:
  661.             for cell in hh.cells:
  662.                 for wild in cell.WildPokemon:
  663.                     hash = wild.SpawnPointId;
  664.                     if hash not in seen.keys() or (seen[hash].TimeTillHiddenMs <= wild.TimeTillHiddenMs):
  665.                         visible.append(wild)    
  666.                     seen[hash] = wild.TimeTillHiddenMs
  667.                 if cell.Fort:
  668.                     for Fort in cell.Fort:
  669.                         if Fort.Enabled == True:
  670.                             if args.china:
  671.                                 (Fort.Latitude, Fort.Longitude) = \
  672. transform_from_wgs_to_gcj(Location(Fort.Latitude, Fort.Longitude))
  673.                             if Fort.GymPoints and args.display_gym:
  674.                                 gyms[Fort.FortId] = [Fort.Team, Fort.Latitude,
  675.                                                      Fort.Longitude, Fort.GymPoints]
  676.  
  677.                             elif Fort.FortType \
  678.                                 and args.display_pokestop:
  679.                                 expire_time = 0
  680.                                 if Fort.LureInfo.LureExpiresTimestampMs:
  681.                                     expire_time = datetime\
  682.                                         .fromtimestamp(Fort.LureInfo.LureExpiresTimestampMs / 1000.0)\
  683.                                         .strftime("%H:%M:%S")
  684.                                 if (expire_time != 0 or not args.onlylure):
  685.                                     pokestops[Fort.FortId] = [Fort.Latitude,
  686.                                                               Fort.Longitude, expire_time]
  687.         except AttributeError:
  688.             break
  689.  
  690.     for poke in visible:
  691.         pokeid = str(poke.pokemon.PokemonId)
  692.         pokename = pokemonsJSON[pokeid]
  693.         if args.ignore:
  694.             if pokename.lower() in ignore or pokeid in ignore:
  695.                 continue
  696.         elif args.only:
  697.             if pokename.lower() not in only and pokeid not in only:
  698.                 continue
  699.         elif args.notifyMe:
  700.             if pokename.lower() in notifyMe or pokeid in notifyMe:
  701.                 Freq = 2500
  702.                 Dur = 500
  703.                 winsound.Beep(Freq,Dur)
  704.  
  705.         disappear_timestamp = time.time() + poke.TimeTillHiddenMs \
  706.             / 1000
  707.  
  708.         if args.china:
  709.             (poke.Latitude, poke.Longitude) = \
  710.                 transform_from_wgs_to_gcj(Location(poke.Latitude,
  711.                     poke.Longitude))
  712.  
  713.         pokemons[poke.SpawnPointId] = {
  714.             "lat": poke.Latitude,
  715.             "lng": poke.Longitude,
  716.             "disappear_time": disappear_timestamp,
  717.             "id": poke.pokemon.PokemonId,
  718.             "name": pokename
  719.         }
  720.  
  721. def clear_stale_pokemons():
  722.     current_time = time.time()
  723.  
  724.     for pokemon_key in pokemons.keys():
  725.         pokemon = pokemons[pokemon_key]
  726.         if current_time > pokemon['disappear_time']:
  727.             print "[+] removing stale pokemon %s at %f, %f from list" % (
  728.                 pokemon['name'].encode('utf-8'), pokemon['lat'], pokemon['lng'])
  729.             del pokemons[pokemon_key]
  730.  
  731.  
  732. def register_background_thread(initial_registration=False):
  733.     """
  734.    Start a background thread to search for Pokemon
  735.    while Flask is still able to serve requests for the map
  736.    :param initial_registration: True if first registration and thread should start immediately, False if it's being called by the finishing thread to schedule a refresh
  737.    :return: None
  738.    """
  739.  
  740.     debug('register_background_thread called')
  741.     global search_thread
  742.  
  743.     if initial_registration:
  744.         if not werkzeug.serving.is_running_from_reloader():
  745.             debug(
  746.                 'register_background_thread: not running inside Flask so not starting thread')
  747.             return
  748.         if search_thread:
  749.             debug(
  750.                 'register_background_thread: initial registration requested but thread already running')
  751.             return
  752.  
  753.         debug('register_background_thread: initial registration')
  754.         search_thread = threading.Thread(target=main)
  755.  
  756.     else:
  757.         debug('register_background_thread: queueing')
  758.         search_thread = threading.Timer(30, main)  # delay, in seconds
  759.  
  760.     search_thread.daemon = True
  761.     search_thread.name = 'search_thread'
  762.     search_thread.start()
  763.  
  764.  
  765. def create_app():
  766.     app = Flask(__name__, template_folder='templates')
  767.  
  768.     GoogleMaps(app, key=GOOGLEMAPS_KEY)
  769.     return app
  770.  
  771.  
  772. app = create_app()
  773.  
  774.  
  775. @app.route('/data')
  776. def data():
  777.     """ Gets all the PokeMarkers via REST """
  778.     return json.dumps(get_pokemarkers())
  779.  
  780. @app.route('/raw_data')
  781. def raw_data():
  782.     """ Gets raw data for pokemons/gyms/pokestops via REST """
  783.     return flask.jsonify(pokemons=pokemons, gyms=gyms, pokestops=pokestops)
  784.  
  785.  
  786. @app.route('/config')
  787. def config():
  788.     """ Gets the settings for the Google Maps via REST"""
  789.     center = {
  790.         'lat': FLOAT_LAT,
  791.         'lng': FLOAT_LONG,
  792.         'zoom': 15,
  793.         'identifier': "fullmap"
  794.     }
  795.     return json.dumps(center)
  796.  
  797.  
  798. @app.route('/')
  799. def fullmap():
  800.     clear_stale_pokemons()
  801.  
  802.     return render_template(
  803.         'example_fullmap.html', key=GOOGLEMAPS_KEY, fullmap=get_map(), auto_refresh=auto_refresh)
  804.  
  805.  
  806. @app.route('/next_loc')
  807. def next_loc():
  808.     global NEXT_LAT, NEXT_LONG
  809.  
  810.     lat = flask.request.args.get('lat', '')
  811.     lon = flask.request.args.get('lon', '')
  812.     if not (lat and lon):
  813.         print('[-] Invalid next location: %s,%s' % (lat, lon))
  814.     else:
  815.         print('[+] Saved next location as %s,%s' % (lat, lon))
  816.         NEXT_LAT = float(lat)
  817.         NEXT_LONG = float(lon)
  818.         return 'ok'
  819.  
  820.  
  821. def get_pokemarkers():
  822.     pokeMarkers = [{
  823.         'icon': icons.dots.red,
  824.         'lat': origin_lat,
  825.         'lng': origin_lon,
  826.         'infobox': "Start position",
  827.         'type': 'custom',
  828.         'key': 'start-position',
  829.         'disappear_time': -1
  830.     }]
  831.  
  832.     for pokemon_key in pokemons:
  833.         pokemon = pokemons[pokemon_key]
  834.         datestr = datetime.fromtimestamp(pokemon[
  835.             'disappear_time'])
  836.         dateoutput = datestr.strftime("%H:%M:%S")
  837.         if is_ampm_clock:
  838.             dateoutput = datestr.strftime("%I:%M%p").lstrip('0')
  839.         pokemon['disappear_time_formatted'] = dateoutput
  840.  
  841.         LABEL_TMPL = u'''
  842. <div><b>{name}</b><span> - </span><small><a href='http://www.pokemon.com/us/pokedex/{id}' target='_blank' title='View in Pokedex'>#{id}</a></small></div>
  843. <div>Disappears at - {disappear_time_formatted} <span class='label-countdown' disappears-at='{disappear_time}'></span></div>
  844. <div><a href='https://www.google.com/maps/dir/Current+Location/{lat},{lng}' target='_blank' title='View in Maps'>Get Directions</a></div>
  845. '''
  846.         label = LABEL_TMPL.format(**pokemon)
  847.         #  NOTE: `infobox` field doesn't render multiple line string in frontend
  848.         label = label.replace('\n', '')
  849.  
  850.         pokeMarkers.append({
  851.             'type': 'pokemon',
  852.             'key': pokemon_key,
  853.             'disappear_time': pokemon['disappear_time'],
  854.             'icon': 'static/icons/%d.png' % pokemon["id"],
  855.             'lat': pokemon["lat"],
  856.             'lng': pokemon["lng"],
  857.             'infobox': label
  858.         })
  859.  
  860.     for gym_key in gyms:
  861.         gym = gyms[gym_key]
  862.         if gym[0] == 0:
  863.             color = "rgba(0,0,0,.4)"
  864.         if gym[0] == 1:
  865.             color = "rgba(74, 138, 202, .6)"
  866.         if gym[0] == 2:
  867.             color = "rgba(240, 68, 58, .6)"
  868.         if gym[0] == 3:
  869.             color = "rgba(254, 217, 40, .6)"
  870.  
  871.         icon = 'static/forts/'+numbertoteam[gym[0]]+'_large.png'
  872.         pokeMarkers.append({
  873.             'icon': 'static/forts/' + numbertoteam[gym[0]] + '.png',
  874.             'type': 'gym',
  875.             'key': gym_key,
  876.             'disappear_time': -1,
  877.             'lat': gym[1],
  878.             'lng': gym[2],
  879.             'infobox': "<div><center><small>Gym owned by:</small><br><b style='color:" + color + "'>Team " + numbertoteam[gym[0]] + "</b><br><img id='" + numbertoteam[gym[0]] + "' height='100px' src='"+icon+"'><br>Prestige: " + str(gym[3]) + "</center>"
  880.         })
  881.     for stop_key in pokestops:
  882.         stop = pokestops[stop_key]
  883.         if stop[2] > 0:
  884.             pokeMarkers.append({
  885.                 'type': 'lured_stop',
  886.                 'key': stop_key,
  887.                 'disappear_time': -1,
  888.                 'icon': 'static/forts/PstopLured.png',
  889.                 'lat': stop[0],
  890.                 'lng': stop[1],
  891.                 'infobox': 'Lured Pokestop, expires at ' + stop[2],
  892.             })
  893.         else:
  894.             pokeMarkers.append({
  895.                 'type': 'stop',
  896.                 'key': stop_key,
  897.                 'disappear_time': -1,
  898.                 'icon': 'static/forts/Pstop.png',
  899.                 'lat': stop[0],
  900.                 'lng': stop[1],
  901.                 'infobox': 'Pokestop',
  902.             })
  903.     return pokeMarkers
  904.  
  905.  
  906. def get_map():
  907.     fullmap = Map(
  908.         identifier="fullmap2",
  909.         style='height:100%;width:100%;top:0;left:0;position:absolute;z-index:200;',
  910.         lat=origin_lat,
  911.         lng=origin_lon,
  912.         markers=get_pokemarkers(),
  913.         zoom='15', )
  914.     return fullmap
  915.  
  916.  
  917. if __name__ == '__main__':
  918.     args = get_args()
  919.     register_background_thread(initial_registration=True)
  920.     app.run(debug=True, threaded=True, host=args.host, port=args.port)
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement