Advertisement
Guest User

Untitled

a guest
Aug 1st, 2016
73
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 12.82 KB | None | 0 0
  1. #!/usr/bin/python
  2. # -*- coding: utf-8 -*-
  3.  
  4. import logging
  5. import os
  6. import time
  7. from pushbullet import Pushbullet
  8. from peewee import Model, MySQLDatabase, SqliteDatabase, InsertQuery,\
  9.                    IntegerField, CharField, DoubleField, BooleanField,\
  10.                    DateTimeField, OperationalError
  11. from datetime import datetime, timedelta
  12. from base64 import b64encode
  13.  
  14. from . import config
  15. from .utils import get_pokemon_name, get_args, send_to_webhook
  16. from .transform import transform_from_wgs_to_gcj
  17. from .customLog import printPokemon
  18.  
  19. log = logging.getLogger(__name__)
  20.  
  21. args = get_args()
  22. db = None
  23. pushbullet_client = None
  24.  
  25. def push(pokemon):
  26.     latLon = '{},{}'.format(repr(pokemon["lat"]), repr(pokemon["lng"]))
  27.     google_maps_link = 'http://maps.google.com/maps?q={}&{}z'.format(latLon, 20)
  28.  
  29.     notification_text = "Pokemon Found " + _str(pokemon["name"]) + "!"
  30.     disappear_time = str(datetime.fromtimestamp(pokemon["disappear_time"]).strftime("%I:%M%p").lstrip('0'))+")"
  31.     location_text = "Location : " + google_maps_link + ". " + _str(pokemon["name"]) + " Available till " + disappear_time + "."
  32.     pushbullet_client.push_link(notification_text, google_maps_link, body=location_text)
  33.  
  34. def init_database():
  35.     global db, pushbullet_client
  36.  
  37.     pushbullet_client = Pushbullet('o.B3ovWssv6DUcgHPaxbX61B182g4OqejY')
  38.  
  39.     if db is not None:
  40.         return db
  41.  
  42.     if args.db_type == 'mysql':
  43.         db = MySQLDatabase(
  44.             args.db_name,
  45.             user=args.db_user,
  46.             password=args.db_pass,
  47.             host=args.db_host)
  48.         log.info('Connecting to MySQL database on {}.'.format(args.db_host))
  49.     else:
  50.         db = SqliteDatabase(args.db)
  51.         log.info('Connecting to local SQLLite database.')
  52.  
  53.     return db
  54.  
  55.  
  56. class BaseModel(Model):
  57.     class Meta:
  58.         database = init_database()
  59.  
  60.     @classmethod
  61.     def get_all(cls):
  62.         results = [m for m in cls.select().dicts()]
  63.         if args.china:
  64.             for result in results:
  65.                 result['latitude'], result['longitude'] = \
  66.                     transform_from_wgs_to_gcj(
  67.                         result['latitude'], result['longitude'])
  68.         return results
  69.  
  70.  
  71. class Pokemon(BaseModel):
  72.     # We are base64 encoding the ids delivered by the api
  73.     # because they are too big for sqlite to handle
  74.     encounter_id = CharField(primary_key=True, max_length=50)
  75.     spawnpoint_id = CharField()
  76.     pokemon_id = IntegerField()
  77.     latitude = DoubleField()
  78.     longitude = DoubleField()
  79.     disappear_time = DateTimeField()
  80.  
  81.     @classmethod
  82.     def get_active(cls, swLat, swLng, neLat, neLng):
  83.         if swLat is None or swLng is None or neLat is None or neLng is None:
  84.             query = (Pokemon
  85.                      .select()
  86.                      .where(Pokemon.disappear_time > datetime.utcnow())
  87.                      .dicts())
  88.         else:
  89.             query = (Pokemon
  90.                      .select()
  91.                      .where((Pokemon.disappear_time > datetime.utcnow()) &
  92.                             (Pokemon.latitude >= swLat) &
  93.                             (Pokemon.longitude >= swLng) &
  94.                             (Pokemon.latitude <= neLat) &
  95.                             (Pokemon.longitude <= neLng))
  96.                      .dicts())
  97.  
  98.         pokemons = []
  99.         for p in query:
  100.             p['pokemon_name'] = get_pokemon_name(p['pokemon_id'])
  101.             if args.china:
  102.                 p['latitude'], p['longitude'] = \
  103.                     transform_from_wgs_to_gcj(p['latitude'], p['longitude'])
  104.             pokemons.append(p)
  105.  
  106.         return pokemons
  107.  
  108.     @classmethod
  109.     def get_active_by_id(cls, ids, swLat, swLng, neLat, neLng):
  110.         if swLat is None or swLng is None or neLat is None or neLng is None:
  111.             query = (Pokemon
  112.                      .select()
  113.                      .where((Pokemon.pokemon_id << ids) &
  114.                             (Pokemon.disappear_time > datetime.utcnow()))
  115.                      .dicts())
  116.         else:
  117.             query = (Pokemon
  118.                      .select()
  119.                      .where((Pokemon.pokemon_id << ids) &
  120.                             (Pokemon.disappear_time > datetime.utcnow()) &
  121.                             (Pokemon.latitude >= swLat) &
  122.                             (Pokemon.longitude >= swLng) &
  123.                             (Pokemon.latitude <= neLat) &
  124.                             (Pokemon.longitude <= neLng))
  125.                      .dicts())
  126.  
  127.         pokemons = []
  128.         for p in query:
  129.             p['pokemon_name'] = get_pokemon_name(p['pokemon_id'])
  130.             if args.china:
  131.                 p['latitude'], p['longitude'] = \
  132.                     transform_from_wgs_to_gcj(p['latitude'], p['longitude'])
  133.             pokemons.append(p)
  134.  
  135.         return pokemons
  136.  
  137.  
  138. class Pokestop(BaseModel):
  139.     pokestop_id = CharField(primary_key=True, max_length=50)
  140.     enabled = BooleanField()
  141.     latitude = DoubleField()
  142.     longitude = DoubleField()
  143.     last_modified = DateTimeField()
  144.     lure_expiration = DateTimeField(null=True)
  145.     active_pokemon_id = IntegerField(null=True)
  146.  
  147.     @classmethod
  148.     def get_stops(cls, swLat, swLng, neLat, neLng):
  149.         if swLat is None or swLng is None or neLat is None or neLng is None:
  150.             query = (Pokestop
  151.                      .select()
  152.                      .dicts())
  153.         else:
  154.             query = (Pokestop
  155.                      .select()
  156.                      .where((Pokestop.latitude >= swLat) &
  157.                             (Pokestop.longitude >= swLng) &
  158.                             (Pokestop.latitude <= neLat) &
  159.                             (Pokestop.longitude <= neLng))
  160.                      .dicts())
  161.  
  162.         pokestops = []
  163.         for p in query:
  164.             if args.china:
  165.                 p['latitude'], p['longitude'] = \
  166.                     transform_from_wgs_to_gcj(p['latitude'], p['longitude'])
  167.             pokestops.append(p)
  168.  
  169.         return pokestops
  170.  
  171.  
  172. class Gym(BaseModel):
  173.     UNCONTESTED = 0
  174.     TEAM_MYSTIC = 1
  175.     TEAM_VALOR = 2
  176.     TEAM_INSTINCT = 3
  177.  
  178.     gym_id = CharField(primary_key=True, max_length=50)
  179.     team_id = IntegerField()
  180.     guard_pokemon_id = IntegerField()
  181.     gym_points = IntegerField()
  182.     enabled = BooleanField()
  183.     latitude = DoubleField()
  184.     longitude = DoubleField()
  185.     last_modified = DateTimeField()
  186.  
  187.     @classmethod
  188.     def get_gyms(cls, swLat, swLng, neLat, neLng):
  189.         if swLat is None or swLng is None or neLat is None or neLng is None:
  190.             query = (Gym
  191.                      .select()
  192.                      .dicts())
  193.         else:
  194.             query = (Gym
  195.                      .select()
  196.                      .where((Gym.latitude >= swLat) &
  197.                             (Gym.longitude >= swLng) &
  198.                             (Gym.latitude <= neLat) &
  199.                             (Gym.longitude <= neLng))
  200.                      .dicts())
  201.  
  202.         gyms = []
  203.         for g in query:
  204.             gyms.append(g)
  205.  
  206.         return gyms
  207.  
  208.  
  209. class ScannedLocation(BaseModel):
  210.     scanned_id = CharField(primary_key=True, max_length=50)
  211.     latitude = DoubleField()
  212.     longitude = DoubleField()
  213.     last_modified = DateTimeField()
  214.  
  215.     @classmethod
  216.     def get_recent(cls, swLat, swLng, neLat, neLng):
  217.         query = (ScannedLocation
  218.                  .select()
  219.                  .where((ScannedLocation.last_modified >=
  220.                         (datetime.utcnow() - timedelta(minutes=15))) &
  221.                         (ScannedLocation.latitude >= swLat) &
  222.                         (ScannedLocation.longitude >= swLng) &
  223.                         (ScannedLocation.latitude <= neLat) &
  224.                         (ScannedLocation.longitude <= neLng))
  225.                  .dicts())
  226.  
  227.         scans = []
  228.         for s in query:
  229.             scans.append(s)
  230.  
  231.         return scans
  232.  
  233.  
  234. def parse_map(map_dict, iteration_num, step, step_location):
  235.     pokemons = {}
  236.     pokestops = {}
  237.     gyms = {}
  238.     scanned = {}
  239.  
  240.     cells = map_dict['responses']['GET_MAP_OBJECTS']['map_cells']
  241.     for cell in cells:
  242.         if config['parse_pokemon']:
  243.             for p in cell.get('wild_pokemons', []):
  244.                 d_t = datetime.utcfromtimestamp(
  245.                     (p['last_modified_timestamp_ms'] +
  246.                      p['time_till_hidden_ms']) / 1000.0)
  247.                 printPokemon(p['pokemon_data']['pokemon_id'], p['latitude'],
  248.                              p['longitude'], d_t)
  249.                 pokemons[p['encounter_id']] = {
  250.                     'encounter_id': b64encode(str(p['encounter_id'])),
  251.                     'spawnpoint_id': p['spawnpoint_id'],
  252.                     'pokemon_id': p['pokemon_data']['pokemon_id'],
  253.                     'latitude': p['latitude'],
  254.                     'longitude': p['longitude'],
  255.                     'disappear_time': d_t
  256.                 }
  257.  
  258.                 webhook_data = {
  259.                     'encounter_id': b64encode(str(p['encounter_id'])),
  260.                     'spawnpoint_id': p['spawnpoint_id'],
  261.                     'pokemon_id': p['pokemon_data']['pokemon_id'],
  262.                     'latitude': p['latitude'],
  263.                     'longitude': p['longitude'],
  264.                     'disappear_time': time.mktime(d_t.timetuple()),
  265.                     'name': p['name']
  266.                 }
  267.                 push(webhook_data)
  268.                 send_to_webhook('pokemon', webhook_data)
  269.  
  270.         if iteration_num > 0 or step > 50:
  271.             for f in cell.get('forts', []):
  272.                 if config['parse_pokestops'] and f.get('type') == 1:  # Pokestops
  273.                         if 'lure_info' in f:
  274.                             lure_expiration = datetime.utcfromtimestamp(
  275.                                 f['lure_info']['lure_expires_timestamp_ms'] / 1000.0)
  276.                             active_pokemon_id = f['lure_info']['active_pokemon_id']
  277.                         else:
  278.                             lure_expiration, active_pokemon_id = None, None
  279.  
  280.                         pokestops[f['id']] = {
  281.                             'pokestop_id': f['id'],
  282.                             'enabled': f['enabled'],
  283.                             'latitude': f['latitude'],
  284.                             'longitude': f['longitude'],
  285.                             'last_modified': datetime.utcfromtimestamp(
  286.                                 f['last_modified_timestamp_ms'] / 1000.0),
  287.                             'lure_expiration': lure_expiration,
  288.                             'active_pokemon_id': active_pokemon_id
  289.                         }
  290.  
  291.                 elif config['parse_gyms'] and f.get('type') is None:  # Currently, there are only stops and gyms
  292.                         gyms[f['id']] = {
  293.                             'gym_id': f['id'],
  294.                             'team_id': f.get('owned_by_team', 0),
  295.                             'guard_pokemon_id': f.get('guard_pokemon_id', 0),
  296.                             'gym_points': f.get('gym_points', 0),
  297.                             'enabled': f['enabled'],
  298.                             'latitude': f['latitude'],
  299.                             'longitude': f['longitude'],
  300.                             'last_modified': datetime.utcfromtimestamp(
  301.                                 f['last_modified_timestamp_ms'] / 1000.0),
  302.                         }
  303.  
  304.     pokemons_upserted = 0
  305.     pokestops_upserted = 0
  306.     gyms_upserted = 0
  307.  
  308.     if pokemons and config['parse_pokemon']:
  309.         pokemons_upserted = len(pokemons)
  310.         log.debug("Upserting {} pokemon".format(len(pokemons)))
  311.         bulk_upsert(Pokemon, pokemons)
  312.  
  313.     if pokestops and config['parse_pokestops']:
  314.         pokestops_upserted = len(pokestops)
  315.         log.debug("Upserting {} pokestops".format(len(pokestops)))
  316.         bulk_upsert(Pokestop, pokestops)
  317.  
  318.     if gyms and config['parse_gyms']:
  319.         gyms_upserted = len(gyms)
  320.         log.debug("Upserting {} gyms".format(len(gyms)))
  321.         bulk_upsert(Gym, gyms)
  322.  
  323.     log.info("Upserted {} pokemon, {} pokestops, and {} gyms".format(
  324.       pokemons_upserted,
  325.       pokestops_upserted,
  326.       gyms_upserted))
  327.  
  328.     scanned[0] = {
  329.         'scanned_id': str(step_location[0])+','+str(step_location[1]),
  330.         'latitude': step_location[0],
  331.         'longitude': step_location[1],
  332.         'last_modified': datetime.utcnow(),
  333.     }
  334.  
  335.     bulk_upsert(ScannedLocation, scanned)
  336.  
  337.  
  338. def bulk_upsert(cls, data):
  339.     num_rows = len(data.values())
  340.     i = 0
  341.     step = 120
  342.  
  343.     while i < num_rows:
  344.         log.debug("Inserting items {} to {}".format(i, min(i+step, num_rows)))
  345.         try:
  346.             InsertQuery(cls, rows=data.values()[i:min(i+step, num_rows)]).upsert().execute()
  347.         except OperationalError as e:
  348.             log.warning("%s... Retrying", e)
  349.             continue
  350.  
  351.         i+=step
  352.  
  353.  
  354. def create_tables(db):
  355.     db.connect()
  356.     db.create_tables([Pokemon, Pokestop, Gym, ScannedLocation], safe=True)
  357.     db.close()
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement