def _setup_event_system(self): handlers = [] if self.config.logging and 'color' in self.config.logging and self.config.logging['color']: handlers.append(ColoredLoggingHandler(self)) else: handlers.append(LoggingHandler(self)) if self.config.enable_social: handlers.append(SocialHandler(self)) if self.config.websocket_server_url: if self.config.websocket_start_embedded_server: self.sio_runner = SocketIoRunner(self.config.websocket_server_url) self.sio_runner.start_listening_async() websocket_handler = SocketIoHandler( self, self.config.websocket_server_url ) handlers.append(websocket_handler) if self.config.websocket_remote_control: remote_control = WebsocketRemoteControl(self).start() # @var EventManager self.event_manager = EventManager(self.config.walker_limit_output, *handlers) self._register_events() if self.config.show_events: self.event_manager.event_report() sys.exit(1)
def facade_main(): print("Client: I want to have a big party for my wife's birthday.\n") em = EventManager() em.arrange()
def _setup_event_system(self): handlers = [] if self.config.logging_color: handlers.append(ColoredLoggingHandler()) else: handlers.append(LoggingHandler()) if self.config.websocket_server_url: if self.config.websocket_start_embedded_server: self.sio_runner = SocketIoRunner( self.config.websocket_server_url) self.sio_runner.start_listening_async() websocket_handler = SocketIoHandler( self, self.config.websocket_server_url) handlers.append(websocket_handler) if self.config.websocket_remote_control: remote_control = WebsocketRemoteControl(self).start() self.event_manager = EventManager(*handlers) self._register_events() if self.config.show_events: self.event_manager.event_report() sys.exit(1)
def __init__(self, verbose=False, visual_debug=False): self.verbose = verbose self.visual_debug = visual_debug ipdb.launch_ipdb_on_exception() # Control Stuff self.researched_warpgate = False # Remove me later # Managers and controllers self.worker_controller = WorkerController(bot=self, verbose=self.verbose) self.army_controller = ArmyController(bot=self, verbose=self.verbose) self.scouting_controller = ScoutingController(bot=self, verbose=self.verbose) self.upgrades_controller = UpgradesController(bot=self, verbose=self.verbose) self.robotics_facility_controller = RoboticsFacilitiyController( bot=self, verbose=self.verbose, ) self.gateway_controller = GatewayController( bot=self, verbose=self.verbose, auto_morph_to_warpgate=True) self.building_controller = BuildingController(bot=self, verbose=self.verbose) self.event_manager = EventManager() self.build_order_controller = BuildOrderController( verbose=self.verbose, bot=self) self.coordinator = Coordinator(bot=self, verbose=self.verbose, build_order='three_gate_blink_all_in') self.order_queue = []
def __init__(self, novel_helper, robot_army): self.nh = novel_helper self.novel_helper = novel_helper self.book_warehouse = self.nh.book_warehouse self.robot_army = robot_army self.user_map = dict() self.init_user_map() self.book_map = dict() self.init_book_map() self.offline_uid_set = set(list(self.user_map.keys())) self.recommend_uid_set = set() self.choosing_uid_set = set() self.click_drive_uid_set = set() self.read_drive_uid_set = set() self.reading_uid_set = set() self.has_online_set = set() self._period = 0 self.rec_sys = RecSysRandom(self) self.event_manager = EventManager(self) self.event_manager.clean_all_csv() self.metrics_client = MetricsClient(self)
def on_handshake(event): sock = event.get_initiator() message = sock.recv(16) connecting_session = uuid.UUID(bytes=message[:16]) storage = SimpleMemCache() # Invalid Handshake if len(message) != 16: sock.send(Message('SERVER', 'Invalid handshake!').serialize()) sock.shutdown(SHUT_RDWR) sock.close() return connecting_user = None if connecting_session == uuid.UUID(int=0): session_id = uuid.uuid4() connecting_user = ConnectionUser(sock, session_id, random_name()) storage.add_user(connecting_user) sock.send(Message('SERVER', '{}.{}'.format(session_id.int, connecting_user.name)).serialize()) elif storage.user_exists(connecting_session): connecting_user = storage.get_user_by_id(connecting_session) sock.send(Message('SERVER', '{}.{}'.format(connecting_session.int, connecting_user.name)).serialize()) EventManager().emit(RoomJoinEvent(event.get_room(), connecting_user))
def __init__(self, root, is_type_editor): """ Args: root: path of project root folder is_type_editor: bool. see class docstring """ self.path = util.normpath(os.path.abspath(root)) self.is_type_editor = is_type_editor self._auto_create_clazz_folder = True # Must be the first self.event_manager = EventManager() self.type_manager = TypeManager() self.fs_manager = FileSystemManager( self, os.path.join(self.path, const.PROJECT_FOLDER_DATA)) # should after fs_manager self.object_manager = ObjectManager(self) # should after object_manager self.ref_manager = RefManager() # self._langauges = ('en', ) self._default_language = 'en' self._translations = {} self._verifier = None self._loading_errors = AttrVerifyLogger() self.tags = set() self._next_ids = {} # {clazz_name: next_id} self._loaded = False self._editor_project = None
def _setup_event_system(self): handlers = [] if self.config.logging_color: handlers.append(ColoredLoggingHandler()) else: handlers.append(LoggingHandler()) if self.config.websocket_server_url: if self.config.websocket_start_embedded_server: self.sio_runner = SocketIoRunner(self.config.websocket_server_url) self.sio_runner.start_listening_async() websocket_handler = SocketIoHandler( self, self.config.websocket_server_url ) handlers.append(websocket_handler) if self.config.websocket_remote_control: remote_control = WebsocketRemoteControl(self).start() self.event_manager = EventManager(*handlers) self._register_events() if self.config.show_events: self.event_manager.event_report() sys.exit(1)
def test(): event_name = ["Fund", "Extreme"] listener = [ Listener(event_name[0], start_fund), Listener(event_name[1], start_extreme) ] event_manager = EventManager() event_manager.AddEventListener(listener[0]) event_driver = Event_Source(event_manager) event_driver.start() event_driver.start() event_driver.start() event_manager.Start()
def main_setup(output_name): ''' This should be called at the beginning of main if you're running unit tests or simulations. We need to set |globals_.event_manager| for most class definitions and helper functions to make sense. ''' globals_.event_manager = EventManager(output_name) globals_.stats_manager = StatsManager(output_name)
def __init__(self, background=None): if background!=None: self.set_background(background) self.event_manager = EventManager() self.subscribe(pygame.QUIT, "quit", self) self.items = pygame.sprite.Group()
def main(): parse_args() ev = EventManager() game = Game(ev, WIDTH, HEIGHT) keybd = KeyboardController(ev) movement_controller = MovementController(ev, game.sprites, game.board) apply_fn( lambda x: ev.register_listener(x), [ keybd, game, movement_controller, ], ) if IS_HOST: begin_on_client_connect(ev, PORT) else: connect_to_server_host(ev, HOST, PORT) reactor.run()
def __init__(self,): """ Définit une Window et un screen qui y est dessiné """ self.surface = pygame.display.set_mode((1024, 574), pg.DOUBLEBUF) pygame.display.set_caption("Dunwall's Gate") self.eventmanager = EventManager(self) self._screen = None self.game = None self.set_screen(HomeScreen()) self.fpsClock = pygame.time.Clock() self.do_run = True
def serve_one(self, sock): EventManager().emit(HandshakingEvent(self, sock)) user = None for u in self.connecting_users: if u.get_socket() == sock: user = u while True: message = sock.recv(1024) if len(message) == 0: EventManager().emit(RoomExitEvent(self, user)) break else: m = Message(raw=message) if m.is_command(): EventManager().emit( UserCommandEvent(self, user, Command(raw=message))) else: EventManager().emit(UserMessageEvent(self, user, m))
def __init__(self, node, southwest, northeast, extras): logging.info("Beginning TwitterStreamer init") StreamListener.__init__(self) # Lock and target location self.lock = threading.Lock() self.buckets = {} self.deltas = {} self.uploaders = {} self.location = [southwest[LONG],southwest[LAT],northeast[LONG],northeast[LAT]] self.event_manager = EventManager() # Upload handler self.node = node logging.info("TwitterStreamer init successful")
class Window(): def __init__(self,): """ Définit une Window et un screen qui y est dessiné """ self.surface = pygame.display.set_mode((1024, 574), pg.DOUBLEBUF) pygame.display.set_caption("Dunwall's Gate") self.eventmanager = EventManager(self) self._screen = None self.game = None self.set_screen(HomeScreen()) self.fpsClock = pygame.time.Clock() self.do_run = True def set_screen(self, screen): """ Définit l'écran affiché dans la Window """ if self._screen is not None: self._screen.surface.fill(0) self._screen.shutdown() self.eventmanager.purge_callbacks(self._screen) self._screen = screen self._screen.start(self, self.eventmanager) def set_do_run(self, value=True): self.do_run = value def start_game(self, game): self.game = game game.start(self) def run(self): """ Lance le jeu """ self.eventmanager.on_quit(lambda x: self.set_do_run(False), "global") while self.do_run: self._screen.update() self._screen.draw() if self.game: self.game.game_event.update() self.eventmanager.run(pygame.event.get()) pygame.display.flip() self.fpsClock.tick(FPS) pygame.quit()
class PokemonGoBot(Datastore): @property def position(self): return self.api.actual_lat, self.api.actual_lng, self.api.actual_alt @property def noised_position(self): return self.api.noised_lat, self.api.noised_lng, self.api.noised_alt #@position.setter # these should be called through api now that gps replication is there... #def position(self, position_tuple): # self.api._position_lat, self.api._position_lng, self.api._position_alt = position_tuple @property def player_data(self): """ Returns the player data as received from the API. :return: The player data. :rtype: dict """ return self._player def __init__(self, config): # Database connection MUST be setup before migrations will work self.database = _init_database('/data/{}.db'.format(config.username)) self.config = config super(PokemonGoBot, self).__init__() self.fort_timeouts = dict() self.pokemon_list = json.load( open(os.path.join(_base_dir, 'data', 'pokemon.json')) ) self.item_list = json.load(open(os.path.join(_base_dir, 'data', 'items.json'))) self.metrics = Metrics(self) self.latest_inventory = None self.cell = None self.recent_forts = [None] * config.forts_max_circle_size self.tick_count = 0 self.softban = False self.start_position = None self.last_map_object = None self.last_time_map_object = 0 self.logger = logging.getLogger(type(self).__name__) self.alt = self.config.gps_default_altitude # Make our own copy of the workers for this instance self.workers = [] # Theading setup for file writing self.web_update_queue = Queue.Queue(maxsize=1) self.web_update_thread = threading.Thread(target=self.update_web_location_worker) self.web_update_thread.start() # Heartbeat limiting self.heartbeat_threshold = self.config.heartbeat_threshold self.heartbeat_counter = 0 self.last_heartbeat = time.time() def start(self): self._setup_event_system() self._setup_logging() self._setup_api() self._load_recent_forts() init_inventory(self) self.display_player_info() self._print_character_info() if self.config.pokemon_bag_show_at_start and self.config.pokemon_bag_pokemon_info: self._print_list_pokemon() random.seed() def _setup_event_system(self): handlers = [] if self.config.logging_color: handlers.append(ColoredLoggingHandler()) else: handlers.append(LoggingHandler()) if self.config.enable_social: handlers.append(SocialHandler(self)) if self.config.websocket_server_url: if self.config.websocket_start_embedded_server: self.sio_runner = SocketIoRunner(self.config.websocket_server_url) self.sio_runner.start_listening_async() websocket_handler = SocketIoHandler( self, self.config.websocket_server_url ) handlers.append(websocket_handler) if self.config.websocket_remote_control: remote_control = WebsocketRemoteControl(self).start() self.event_manager = EventManager(*handlers) self._register_events() if self.config.show_events: self.event_manager.event_report() sys.exit(1) # Registering event: # self.event_manager.register_event("location", parameters=['lat', 'lng']) # # Emitting event should be enough to add logging and send websocket # message: : # self.event_manager.emit('location', 'level'='info', data={'lat': 1, 'lng':1}), def _register_events(self): self.event_manager.register_event( 'location_found', parameters=('position', 'location') ) self.event_manager.register_event('api_error') self.event_manager.register_event('config_error') self.event_manager.register_event('login_started') self.event_manager.register_event('login_failed') self.event_manager.register_event('login_successful') self.event_manager.register_event('set_start_location') self.event_manager.register_event('load_cached_location') self.event_manager.register_event('location_cache_ignored') self.event_manager.register_event( 'position_update', parameters=( 'current_position', 'last_position', 'distance', # optional 'distance_unit' # optional ) ) self.event_manager.register_event( 'path_lap_update', parameters=( 'number_lap', 'number_lap_max' ) ) self.event_manager.register_event( 'path_lap_end', parameters=( 'duration', 'resume' ) ) self.event_manager.register_event('location_cache_error') self.event_manager.register_event('bot_start') self.event_manager.register_event('bot_exit') self.event_manager.register_event('bot_interrupted') # sleep stuff self.event_manager.register_event( 'next_sleep', parameters=('time',) ) self.event_manager.register_event( 'bot_sleep', parameters=( 'time_hms', 'wake' ) ) # random pause self.event_manager.register_event( 'next_random_pause', parameters=( 'time', 'duration' ) ) self.event_manager.register_event( 'bot_random_pause', parameters=( 'time_hms', 'resume' ) ) # random alive pause self.event_manager.register_event( 'next_random_alive_pause', parameters=( 'time', 'duration' ) ) self.event_manager.register_event( 'bot_random_alive_pause', parameters=( 'time_hms', 'resume' ) ) # fort stuff self.event_manager.register_event( 'spun_fort', parameters=( 'fort_id', 'latitude', 'longitude' ) ) self.event_manager.register_event( 'lured_pokemon_found', parameters=( 'fort_id', 'fort_name', 'encounter_id', 'latitude', 'longitude' ) ) self.event_manager.register_event( 'moving_to_fort', parameters=( 'fort_name', 'distance' ) ) self.event_manager.register_event( 'moving_to_lured_fort', parameters=( 'fort_name', 'distance', 'lure_distance' ) ) self.event_manager.register_event( 'spun_pokestop', parameters=( 'pokestop', 'exp', 'items' ) ) self.event_manager.register_event( 'pokestop_empty', parameters=('pokestop',) ) self.event_manager.register_event( 'pokestop_out_of_range', parameters=('pokestop',) ) self.event_manager.register_event( 'pokestop_on_cooldown', parameters=('pokestop', 'minutes_left') ) self.event_manager.register_event( 'unknown_spin_result', parameters=('status_code',) ) self.event_manager.register_event('pokestop_searching_too_often') self.event_manager.register_event('arrived_at_fort') # pokemon stuff self.event_manager.register_event( 'catchable_pokemon', parameters=( 'pokemon_id', 'spawn_point_id', 'encounter_id', 'latitude', 'longitude', 'expiration_timestamp_ms', 'pokemon_name' ) ) self.event_manager.register_event( 'pokemon_appeared', parameters=( 'pokemon', 'ncp', 'cp', 'iv', 'iv_display', 'encounter_id', 'latitude', 'longitude', 'pokemon_id' ) ) self.event_manager.register_event('no_pokeballs') self.event_manager.register_event('enough_ultraballs') self.event_manager.register_event( 'pokemon_catch_rate', parameters=( 'catch_rate', 'ball_name', 'berry_name', 'berry_count' ) ) self.event_manager.register_event( 'threw_berry', parameters=( 'berry_name', 'ball_name', 'new_catch_rate' ) ) self.event_manager.register_event( 'threw_pokeball', parameters=( 'throw_type', 'spin_label', 'ball_name', 'success_percentage', 'count_left' ) ) self.event_manager.register_event( 'pokemon_capture_failed', parameters=('pokemon',) ) self.event_manager.register_event( 'pokemon_vanished', parameters=( 'pokemon', 'encounter_id', 'latitude', 'longitude', 'pokemon_id' ) ) self.event_manager.register_event('pokemon_not_in_range') self.event_manager.register_event('pokemon_inventory_full') self.event_manager.register_event( 'pokemon_caught', parameters=( 'pokemon', 'ncp', 'cp', 'iv', 'iv_display', 'exp', 'encounter_id', 'latitude', 'longitude', 'pokemon_id' ) ) self.event_manager.register_event( 'pokemon_evolved', parameters=('pokemon', 'iv', 'cp', 'xp', 'candy') ) self.event_manager.register_event('skip_evolve') self.event_manager.register_event('threw_berry_failed', parameters=('status_code',)) self.event_manager.register_event('vip_pokemon') self.event_manager.register_event('gained_candy', parameters=('quantity', 'type')) self.event_manager.register_event('catch_limit') # level up stuff self.event_manager.register_event( 'level_up', parameters=( 'previous_level', 'current_level' ) ) self.event_manager.register_event( 'level_up_reward', parameters=('items',) ) # lucky egg self.event_manager.register_event( 'used_lucky_egg', parameters=('amount_left',) ) self.event_manager.register_event('lucky_egg_error') # softban self.event_manager.register_event('softban') self.event_manager.register_event('softban_fix') self.event_manager.register_event('softban_fix_done') # egg incubating self.event_manager.register_event( 'incubate_try', parameters=( 'incubator_id', 'egg_id' ) ) self.event_manager.register_event( 'incubate', parameters=('distance_in_km',) ) self.event_manager.register_event( 'next_egg_incubates', parameters=('eggs_left', 'eggs_inc', 'eggs') ) self.event_manager.register_event('incubator_already_used') self.event_manager.register_event('egg_already_incubating') self.event_manager.register_event( 'egg_hatched', parameters=( 'pokemon', 'cp', 'iv', 'exp', 'stardust', 'candy' ) ) # discard item self.event_manager.register_event( 'item_discarded', parameters=( 'amount', 'item', 'maximum' ) ) self.event_manager.register_event( 'item_discard_skipped', parameters=('space',) ) self.event_manager.register_event( 'item_discard_fail', parameters=('item',) ) # inventory self.event_manager.register_event('inventory_full') # release self.event_manager.register_event( 'keep_best_release', parameters=( 'amount', 'pokemon', 'criteria' ) ) self.event_manager.register_event( 'future_pokemon_release', parameters=( 'pokemon', 'cp', 'iv', 'below_iv', 'below_cp', 'cp_iv_logic' ) ) self.event_manager.register_event( 'pokemon_release', parameters=('pokemon', 'iv', 'cp', 'candy') ) # polyline walker self.event_manager.register_event( 'polyline_request', parameters=('url',) ) # cluster self.event_manager.register_event( 'found_cluster', parameters=( 'num_points', 'forts', 'radius', 'distance' ) ) self.event_manager.register_event( 'arrived_at_cluster', parameters=( 'num_points', 'forts', 'radius' ) ) # rename self.event_manager.register_event( 'rename_pokemon', parameters=('old_name', 'current_name',) ) self.event_manager.register_event( 'pokemon_nickname_invalid', parameters=('nickname',) ) self.event_manager.register_event( 'unset_pokemon_nickname', parameters=('old_name',) ) # Move To map pokemon self.event_manager.register_event( 'move_to_map_pokemon_fail', parameters=('message',) ) self.event_manager.register_event( 'move_to_map_pokemon_updated_map', parameters=('lat', 'lon') ) self.event_manager.register_event( 'move_to_map_pokemon_teleport_to', parameters=('poke_name', 'poke_dist', 'poke_lat', 'poke_lon', 'disappears_in') ) self.event_manager.register_event( 'move_to_map_pokemon_encounter', parameters=('poke_name', 'poke_dist', 'poke_lat', 'poke_lon', 'disappears_in') ) self.event_manager.register_event( 'move_to_map_pokemon_move_towards', parameters=('poke_name', 'poke_dist', 'poke_lat', 'poke_lon', 'disappears_in') ) self.event_manager.register_event( 'move_to_map_pokemon_teleport_back', parameters=('last_lat', 'last_lon') ) self.event_manager.register_event( 'moving_to_pokemon_throught_fort', parameters=('fort_name', 'distance','poke_name','poke_dist') ) # cached recent_forts self.event_manager.register_event('loaded_cached_forts') self.event_manager.register_event('cached_fort') self.event_manager.register_event( 'no_cached_forts', parameters=('path', ) ) self.event_manager.register_event( 'error_caching_forts', parameters=('path', ) ) # database shit self.event_manager.register_event('catch_log') self.event_manager.register_event('evolve_log') self.event_manager.register_event('login_log') self.event_manager.register_event('transfer_log') self.event_manager.register_event('pokestop_log') self.event_manager.register_event('softban_log') def tick(self): self.health_record.heartbeat() self.cell = self.get_meta_cell() now = time.time() * 1000 for fort in self.cell["forts"]: timeout = fort.get("cooldown_complete_timestamp_ms", 0) if timeout >= now: self.fort_timeouts[fort["id"]] = timeout self.tick_count += 1 # Check if session token has expired self.check_session(self.position) for worker in self.workers: if worker.work() == WorkerResult.RUNNING: return def get_meta_cell(self): location = self.position[0:2] cells = self.find_close_cells(*location) # Combine all cells into a single dict of the items we care about. forts = [] wild_pokemons = [] catchable_pokemons = [] for cell in cells: if "forts" in cell and len(cell["forts"]): forts += cell["forts"] if "wild_pokemons" in cell and len(cell["wild_pokemons"]): wild_pokemons += cell["wild_pokemons"] if "catchable_pokemons" in cell and len(cell["catchable_pokemons"]): catchable_pokemons += cell["catchable_pokemons"] # If there are forts present in the cells sent from the server or we don't yet have any cell data, return all data retrieved if len(forts) > 1 or not self.cell: return { "forts": forts, "wild_pokemons": wild_pokemons, "catchable_pokemons": catchable_pokemons } # If there are no forts present in the data from the server, keep our existing fort data and only update the pokemon cells. else: return { "forts": self.cell["forts"], "wild_pokemons": wild_pokemons, "catchable_pokemons": catchable_pokemons } def update_web_location(self, cells=[], lat=None, lng=None, alt=None): # we can call the function with no arguments and still get the position # and map_cells if lat is None: lat = self.api._position_lat if lng is None: lng = self.api._position_lng if alt is None: alt = self.api._position_alt # dont cache when teleport_to if self.api.teleporting: return if cells == []: location = self.position[0:2] cells = self.find_close_cells(*location) user_data_cells = os.path.join(_base_dir, 'data', 'cells-%s.json' % self.config.username) try: with open(user_data_cells, 'w') as outfile: json.dump(cells, outfile) except IOError as e: self.logger.info('[x] Error while opening location file: %s' % e) user_web_location = os.path.join( _base_dir, 'web', 'location-%s.json' % self.config.username ) # alt is unused atm but makes using *location easier try: with open(user_web_location, 'w') as outfile: json.dump({ 'lat': lat, 'lng': lng, 'alt': alt, 'cells': cells }, outfile) except IOError as e: self.logger.info('[x] Error while opening location file: %s' % e) user_data_lastlocation = os.path.join( _base_dir, 'data', 'last-location-%s.json' % self.config.username ) try: with open(user_data_lastlocation, 'w') as outfile: json.dump({'lat': lat, 'lng': lng, 'alt': alt, 'start_position': self.start_position}, outfile) except IOError as e: self.logger.info('[x] Error while opening location file: %s' % e) def find_close_cells(self, lat, lng): cellid = get_cell_ids(lat, lng) timestamp = [0, ] * len(cellid) response_dict = self.get_map_objects(lat, lng, timestamp, cellid) map_objects = response_dict.get( 'responses', {} ).get('GET_MAP_OBJECTS', {}) status = map_objects.get('status', None) map_cells = [] if status and status == 1: map_cells = map_objects['map_cells'] position = (lat, lng, 0) map_cells.sort( key=lambda x: distance( lat, lng, x['forts'][0]['latitude'], x['forts'][0]['longitude']) if x.get('forts', []) else 1e6 ) return map_cells def _setup_logging(self): # log settings # log format if self.config.debug: log_level = logging.DEBUG logging.getLogger("requests").setLevel(logging.DEBUG) logging.getLogger("websocket").setLevel(logging.DEBUG) logging.getLogger("socketio").setLevel(logging.DEBUG) logging.getLogger("engineio").setLevel(logging.DEBUG) logging.getLogger("socketIO-client").setLevel(logging.DEBUG) logging.getLogger("pgoapi").setLevel(logging.DEBUG) logging.getLogger("rpc_api").setLevel(logging.DEBUG) else: log_level = logging.ERROR logging.getLogger("requests").setLevel(logging.ERROR) logging.getLogger("websocket").setLevel(logging.ERROR) logging.getLogger("socketio").setLevel(logging.ERROR) logging.getLogger("engineio").setLevel(logging.ERROR) logging.getLogger("socketIO-client").setLevel(logging.ERROR) logging.getLogger("pgoapi").setLevel(logging.ERROR) logging.getLogger("rpc_api").setLevel(logging.ERROR) logging.basicConfig( level=log_level, format='%(asctime)s [%(name)10s] [%(levelname)s] %(message)s' ) def check_session(self, position): # Check session expiry if self.api._auth_provider and self.api._auth_provider._ticket_expire: # prevent crash if return not numeric value if not self.is_numeric(self.api._auth_provider._ticket_expire): self.logger.info("Ticket expired value is not numeric", 'yellow') return remaining_time = \ self.api._auth_provider._ticket_expire / 1000 - time.time() if remaining_time < 60: self.event_manager.emit( 'api_error', sender=self, level='info', formatted='Session stale, re-logging in.' ) self.api = ApiWrapper(config=self.config) self.api.set_position(*position) self.login() self.api.activate_signature(self.get_encryption_lib()) @staticmethod def is_numeric(s): try: float(s) return True except ValueError: return False def login(self): self.event_manager.emit( 'login_started', sender=self, level='info', formatted="Login procedure started." ) lat, lng = self.position[0:2] self.api.set_position(lat, lng, self.alt) # or should the alt kept to zero? while not self.api.login( self.config.auth_service, str(self.config.username), str(self.config.password)): self.event_manager.emit( 'login_failed', sender=self, level='info', formatted="Login error, server busy. Waiting 10 seconds to try again." ) time.sleep(10) with self.database as conn: c = conn.cursor() c.execute("SELECT COUNT(name) FROM sqlite_master WHERE type='table' AND name='login'") result = c.fetchone() while True: if result[0] == 1: conn.execute('''INSERT INTO login (timestamp, message) VALUES (?, ?)''', (time.time(), 'LOGIN_SUCCESS')) break else: self.event_manager.emit( 'login_failed', sender=self, level='info', formatted="Login table not founded, skipping log" ) break self.event_manager.emit( 'login_successful', sender=self, level='info', formatted="Login successful." ) def get_encryption_lib(self): if _platform == "Windows" or _platform == "win32": # Check if we are on 32 or 64 bit if sys.maxsize > 2**32: file_name = 'encrypt_64.dll' else: file_name = 'encrypt.dll' else: file_name = 'encrypt.so' if self.config.encrypt_location == '': path = os.path.abspath(os.path.join(os.path.dirname(__file__), os.pardir)) else: path = self.config.encrypt_location full_path = path + '/'+ file_name if not os.path.isfile(full_path): self.logger.error(file_name + ' is not found! Please place it in the bots root directory or set encrypt_location in config.') self.logger.info('Platform: '+ _platform + ' ' + file_name + ' directory: '+ path) sys.exit(1) else: self.logger.info('Found '+ file_name +'! Platform: ' + _platform + ' ' + file_name + ' directory: ' + path) return full_path def _setup_api(self): # instantiate pgoapi self.api = ApiWrapper(config=self.config) # provide player position on the earth self._set_starting_position() self.login() # chain subrequests (methods) into one RPC call self.api.activate_signature(self.get_encryption_lib()) self.logger.info('') # send empty map_cells and then our position self.update_web_location() def _print_character_info(self): # get player profile call # ---------------------- response_dict = self.api.get_player() # print('Response dictionary: \n\r{}'.format(json.dumps(response_dict, indent=2))) currency_1 = "0" currency_2 = "0" if response_dict: self._player = response_dict['responses']['GET_PLAYER']['player_data'] player = self._player else: self.logger.info( "The API didn't return player info, servers are unstable - " "retrying.", 'red' ) sleep(5) self._print_character_info() # @@@ TODO: Convert this to d/m/Y H:M:S creation_date = datetime.datetime.fromtimestamp( player['creation_timestamp_ms'] / 1e3) creation_date = creation_date.strftime("%Y/%m/%d %H:%M:%S") pokecoins = '0' stardust = '0' items_inventory = inventory.items() if 'amount' in player['currencies'][0]: pokecoins = player['currencies'][0]['amount'] if 'amount' in player['currencies'][1]: stardust = player['currencies'][1]['amount'] self.logger.info('') self.logger.info('--- {username} ---'.format(**player)) self.logger.info( 'Pokemon Bag: {}/{}'.format( inventory.Pokemons.get_space_used(), inventory.get_pokemon_inventory_size() ) ) self.logger.info( 'Items: {}/{}'.format( inventory.Items.get_space_used(), inventory.get_item_inventory_size() ) ) self.logger.info( 'Stardust: {}'.format(stardust) + ' | Pokecoins: {}'.format(pokecoins) ) # Items Output self.logger.info( 'PokeBalls: ' + str(items_inventory.get(1).count) + ' | GreatBalls: ' + str(items_inventory.get(2).count) + ' | UltraBalls: ' + str(items_inventory.get(3).count) + ' | MasterBalls: ' + str(items_inventory.get(4).count)) self.logger.info( 'RazzBerries: ' + str(items_inventory.get(701).count) + ' | BlukBerries: ' + str(items_inventory.get(702).count) + ' | NanabBerries: ' + str(items_inventory.get(703).count)) self.logger.info( 'LuckyEgg: ' + str(items_inventory.get(301).count) + ' | Incubator: ' + str(items_inventory.get(902).count) + ' | TroyDisk: ' + str(items_inventory.get(501).count)) self.logger.info( 'Potion: ' + str(items_inventory.get(101).count) + ' | SuperPotion: ' + str(items_inventory.get(102).count) + ' | HyperPotion: ' + str(items_inventory.get(103).count) + ' | MaxPotion: ' + str(items_inventory.get(104).count)) self.logger.info( 'Incense: ' + str(items_inventory.get(401).count) + ' | IncenseSpicy: ' + str(items_inventory.get(402).count) + ' | IncenseCool: ' + str(items_inventory.get(403).count)) self.logger.info( 'Revive: ' + str(items_inventory.get(201).count) + ' | MaxRevive: ' + str(items_inventory.get(202).count)) self.logger.info('') def _print_list_pokemon(self): # get pokemon list bag = inventory.pokemons().all() id_list =list(set(map(lambda x: x.pokemon_id, bag))) id_list.sort() pokemon_list = [filter(lambda x: x.pokemon_id == y, bag) for y in id_list] show_count = self.config.pokemon_bag_show_count show_candies = self.config.pokemon_bag_show_candies poke_info_displayed = self.config.pokemon_bag_pokemon_info def get_poke_info(info, pokemon): poke_info = { 'cp': 'CP {}'.format(pokemon.cp), 'iv_ads': 'A/D/S {}/{}/{}'.format(pokemon.iv_attack, pokemon.iv_defense, pokemon.iv_stamina), 'iv_pct': 'IV {}'.format(pokemon.iv), 'ivcp': 'IVCP {}'.format(round(pokemon.ivcp,2)), 'ncp': 'NCP {}'.format(round(pokemon.cp_percent,2)), 'level': "Level {}".format(pokemon.level), 'hp': 'HP {}/{}'.format(pokemon.hp, pokemon.hp_max), 'moveset': 'Moves: {}'.format(pokemon.moveset), 'dps': 'DPS {}'.format(round(pokemon.moveset.dps, 2)) } if info not in poke_info: raise ConfigException("info '{}' isn't available for displaying".format(info)) return poke_info[info] self.logger.info('Pokemon:') for pokes in pokemon_list: line_p = '#{} {}'.format(pokes[0].pokemon_id, pokes[0].name) if show_count: line_p += '[{}]'.format(len(pokes)) if show_candies: line_p += '[{} candies]'.format(pokes[0].candy_quantity) line_p += ': ' poke_info = ['({})'.format(', '.join([get_poke_info(x, p) for x in poke_info_displayed])) for p in pokes] self.logger.info(line_p + ' | '.join(poke_info)) self.logger.info('') def use_lucky_egg(self): return self.api.use_item_xp_boost(item_id=301) def _set_starting_position(self): self.event_manager.emit( 'set_start_location', sender=self, level='info', formatted='Setting start location.' ) has_position = False if self.config.test: # TODO: Add unit tests return if self.config.location: location_str = self.config.location location = self.get_pos_by_name(location_str.replace(" ", "")) msg = "Location found: {location} {position}" self.event_manager.emit( 'location_found', sender=self, level='info', formatted=msg, data={ 'location': location_str, 'position': location } ) self.api.set_position(*location) self.event_manager.emit( 'position_update', sender=self, level='info', formatted="Now at {current_position}", data={ 'current_position': self.position, 'last_position': '', 'distance': '', 'distance_unit': '' } ) self.start_position = self.position has_position = True if self.config.location_cache: try: # save location flag used to pull the last known location from # the location.json self.event_manager.emit( 'load_cached_location', sender=self, level='debug', formatted='Loading cached location...' ) with open(os.path.join(_base_dir, 'data', 'last-location-%s.json' % self.config.username)) as f: location_json = json.load(f) location = ( location_json['lat'], location_json['lng'], location_json['alt'], ) # If location has been set in config, only use cache if starting position has not differed if has_position and 'start_position' in location_json: last_start_position = tuple(location_json.get('start_position', [])) # Start position has to have been set on a previous run to do this check if last_start_position and last_start_position != self.start_position: msg = 'Going to a new place, ignoring cached location.' self.event_manager.emit( 'location_cache_ignored', sender=self, level='debug', formatted=msg ) return self.api.set_position(*location) self.event_manager.emit( 'position_update', sender=self, level='debug', formatted='Loaded location {current_position} from cache', data={ 'current_position': location, 'last_position': '', 'distance': '', 'distance_unit': '' } ) has_position = True except Exception: if has_position is False: sys.exit( "No cached Location. Please specify initial location." ) self.event_manager.emit( 'location_cache_error', sender=self, level='debug', formatted='Parsing cached location failed.' ) def get_pos_by_name(self, location_name): # Check if the given location is already a coordinate. if ',' in location_name: possible_coordinates = re.findall( "[-]?\d{1,3}[.]\d{3,7}", location_name ) if len(possible_coordinates) >= 2: # 2 matches, this must be a coordinate. We'll bypass the Google # geocode so we keep the exact location. self.logger.info( '[x] Coordinates found in passed in location, ' 'not geocoding.' ) return float(possible_coordinates[0]), float(possible_coordinates[1]), (float(possible_coordinates[2]) if len(possible_coordinates) == 3 else self.alt) geolocator = GoogleV3(api_key=self.config.gmapkey) loc = geolocator.geocode(location_name, timeout=10) return float(loc.latitude), float(loc.longitude), float(loc.altitude) def heartbeat(self): # Remove forts that we can now spin again. now = time.time() self.fort_timeouts = {id: timeout for id, timeout in self.fort_timeouts.iteritems() if timeout >= now * 1000} if now - self.last_heartbeat >= self.heartbeat_threshold: self.last_heartbeat = now request = self.api.create_request() request.get_player() request.check_awarded_badges() request.call() try: self.web_update_queue.put_nowait(True) # do this outside of thread every tick except Queue.Full: pass def update_web_location_worker(self): while True: self.web_update_queue.get() self.update_web_location() def display_player_info(self): inventory_items = self.api.get_inventory() inventory_items = inventory_items['responses']['GET_INVENTORY']['inventory_delta']['inventory_items'] player_stats = next((x["inventory_item_data"]["player_stats"] for x in inventory_items if x.get("inventory_item_data", {}).get("player_stats", {})), None) if player_stats: nextlvlxp = (int(player_stats.get('next_level_xp', 0)) - int(player_stats.get('experience', 0))) if 'level' in player_stats and 'experience' in player_stats: self.logger.info( 'Level: {level}'.format( **player_stats) + ' (Next Level: {} XP)'.format( nextlvlxp) + ' (Total: {experience} XP)' ''.format(**player_stats)) if 'pokemons_captured' in player_stats and 'poke_stop_visits' in player_stats: self.logger.info( 'Pokemon Captured: ' '{pokemons_captured}'.format( **player_stats) + ' | Pokestops Visited: ' '{poke_stop_visits}'.format( **player_stats)) def get_forts(self, order_by_distance=False): forts = [fort for fort in self.cell['forts'] if 'latitude' in fort and 'type' in fort] if order_by_distance: forts.sort(key=lambda x: distance( self.position[0], self.position[1], x['latitude'], x['longitude'] )) return forts def get_map_objects(self, lat, lng, timestamp, cellid): if time.time() - self.last_time_map_object < self.config.map_object_cache_time: return self.last_map_object self.last_map_object = self.api.get_map_objects( latitude=f2i(lat), longitude=f2i(lng), since_timestamp_ms=timestamp, cell_id=cellid ) self.last_time_map_object = time.time() return self.last_map_object def _load_recent_forts(self): if not self.config.forts_cache_recent_forts: return cached_forts_path = os.path.join(_base_dir, 'data', 'recent-forts-%s.json' % self.config.username) try: # load the cached recent forts with open(cached_forts_path) as f: cached_recent_forts = json.load(f) num_cached_recent_forts = len(cached_recent_forts) num_recent_forts = len(self.recent_forts) # Handles changes in max_circle_size if not num_recent_forts: self.recent_forts = [] elif num_recent_forts > num_cached_recent_forts: self.recent_forts[-num_cached_recent_forts:] = cached_recent_forts elif num_recent_forts < num_cached_recent_forts: self.recent_forts = cached_recent_forts[-num_recent_forts:] else: self.recent_forts = cached_recent_forts self.event_manager.emit( 'loaded_cached_forts', sender=self, level='debug', formatted='Loaded cached forts...' ) except IOError: self.event_manager.emit( 'no_cached_forts', sender=self, level='debug', formatted='Starting new cached forts for {path}', data={'path': cached_forts_path} )
class TwitterStreamer(StreamListener): def __init__(self, node, southwest, northeast, extras): logging.info("Beginning TwitterStreamer init") StreamListener.__init__(self) # Lock and target location self.lock = threading.Lock() self.buckets = {} self.deltas = {} self.uploaders = {} self.location = [southwest[LONG],southwest[LAT],northeast[LONG],northeast[LAT]] self.event_manager = EventManager() # Upload handler self.node = node logging.info("TwitterStreamer init successful") # # Threading Functiosn # # Start node def start(self): logging.info("Starting TwitterStreamer") # This handles Twitter authetification and the connection to Twitter Streaming API auth = OAuthHandler(CONSUMER_KEY, CONSUMER_SECRET) auth.set_access_token(ACCESS_TOKEN, ACCESS_TOKEN_SECRET) # 2nd parameter self serves as the StreamListener object self.stream = Stream(auth, self) logging.debug("Created Stream object") # Start streaming with right parameters #self.stream.filter(locations=self.location, async=True) t = threading.Thread(target=self.stream.filter, kwargs={'locations':self.location, 'async':False}) t.daemon = True t.start() logging.info("TwitterStreamer started successfully") return t def stop(self): logging.info("Stopping TwitterStreamer") # Disconnect the stream self.stream.disconnect() # Cancel our uploading threads for t in self.uploaders: self.uploaders[t].cancel() logging.info("TwitterStreamer stopped") # # Data Management # def find_location(self, json): # Primary check coordinates = json['place']['bounding_box']['coordinates'][0] return coordinates def record_event(self,long,lat): key = str(long) + "," + str(lat) # If this is the first time recording for bucket, launch updater if key not in self.buckets: self.buckets[key] = self.buckets.get(key,0) + 1 self.deltas[key] = datetime.datetime.now() self.post_bucket(key) else: self.buckets[key] += 1 def post_bucket(self, key): #now = datetime.datetime.now() #period = (now - self.deltas[key]).total_seconds() #self.deltas[key] = now period = 10 velocity = float(self.buckets[key]) / float(period) accel, torque = self.event_manager.record(velocity) x, y = [int(i) for i in key.split(',')] x = int(x) y = int(y) data = { 'x': x, 'y': y, 'width': 1, 'velocity':velocity, 'acceleration':accel, 'torque':torque } self.node.post_results(data) self.buckets[key] = 0 # Rerun again later t = threading.Timer(10, self.post_bucket, args=(key,)) t.daemon = True t.start() self.uploaders[key] = t # # Event-driven functions # # Runs for every tweet def on_status(self, status): logging.debug("Status received!") json = status._json coords = self.find_location(json) # Random location within assigned region TODO improve this? left = max(self.location[0], coords[0][0]) bottom = max(self.location[1], coords[0][1]) right = min(self.location[2], coords[2][0]) top = min(self.location[3], coords[2][1]) long = int(random.uniform(left, right)) lat = int(random.uniform(bottom, top)) #print lat self.record_event(long,lat) return True def on_warning(self, warning): logging.warning(str(warning)) return True # Catches errors def on_error(self, status): logging.critical("ERROR " + str(status)) return False # Handles incoming control signals def on_command(self, command): # Reformat incoming commands name = command['name'] text = command['text'] try: name = name.encode('UTF-8') text = text.encode('UTF-8') except: return # Don't act on messages we sent. if name == self.name: return # Attempt to parse for commands tokens = text.split() if tokens[0][1:] == self.name or tokens[0][1:] == self.nick: if tokens[1] == "close" or tokens[1] == "stop": self.close() else: #self.respond("Sorry, I don't recognize that command.") self.log("Unrecognized command: " + text) # # Utility functions # def respond(self, message): #self.messages.push({'name':self.nick, 'text':message}) pass
class PokemonGoBot(object): @property def position(self): return self.api._position_lat, self.api._position_lng, 0 @position.setter def position(self, position_tuple): self.api._position_lat, self.api._position_lng, self.api._position_alt = position_tuple @property def player_data(self): """ Returns the player data as received from the API. :return: The player data. :rtype: dict """ return self._player def __init__(self, config): self.config = config self.fort_timeouts = dict() self.pokemon_list = json.load( open(os.path.join('data', 'pokemon.json'))) self.item_list = json.load(open(os.path.join('data', 'items.json'))) self.metrics = Metrics(self) self.latest_inventory = None self.cell = None self.recent_forts = [None] * config.forts_max_circle_size self.tick_count = 0 self.softban = False self.start_position = None self.last_map_object = None self.last_time_map_object = 0 self.logger = logging.getLogger(type(self).__name__) # Make our own copy of the workers for this instance self.workers = [] # Theading setup for file writing self.web_update_queue = Queue.Queue(maxsize=1) self.web_update_thread = threading.Thread( target=self.update_web_location_worker) self.web_update_thread.start() def start(self): self._setup_event_system() self._setup_logging() self._setup_api() random.seed() def _setup_event_system(self): handlers = [LoggingHandler()] if self.config.websocket_server_url: if self.config.websocket_start_embedded_server: self.sio_runner = SocketIoRunner( self.config.websocket_server_url) self.sio_runner.start_listening_async() websocket_handler = SocketIoHandler( self, self.config.websocket_server_url) handlers.append(websocket_handler) if self.config.websocket_remote_control: remote_control = WebsocketRemoteControl(self).start() self.event_manager = EventManager(*handlers) self._register_events() if self.config.show_events: self.event_manager.event_report() sys.exit(1) # Registering event: # self.event_manager.register_event("location", parameters=['lat', 'lng']) # # Emitting event should be enough to add logging and send websocket # message: : # self.event_manager.emit('location', 'level'='info', data={'lat': 1, 'lng':1}), def _register_events(self): self.event_manager.register_event('location_found', parameters=('position', 'location')) self.event_manager.register_event('api_error') self.event_manager.register_event('config_error') self.event_manager.register_event('login_started') self.event_manager.register_event('login_failed') self.event_manager.register_event('login_successful') self.event_manager.register_event('set_start_location') self.event_manager.register_event('load_cached_location') self.event_manager.register_event('location_cache_ignored') self.event_manager.register_event( 'position_update', parameters=( 'current_position', 'last_position', 'distance', # optional 'distance_unit' # optional )) self.event_manager.register_event('location_cache_error') self.event_manager.register_event('bot_start') self.event_manager.register_event('bot_exit') # sleep stuff self.event_manager.register_event('next_sleep', parameters=('time', )) self.event_manager.register_event('bot_sleep', parameters=('time_in_seconds', )) # fort stuff self.event_manager.register_event('spun_fort', parameters=('fort_id', 'latitude', 'longitude')) self.event_manager.register_event('lured_pokemon_found', parameters=('fort_id', 'fort_name', 'encounter_id', 'latitude', 'longitude')) self.event_manager.register_event('moving_to_fort', parameters=('fort_name', 'distance')) self.event_manager.register_event('moving_to_lured_fort', parameters=('fort_name', 'distance', 'lure_distance')) self.event_manager.register_event('spun_pokestop', parameters=('pokestop', 'exp', 'items')) self.event_manager.register_event('pokestop_empty', parameters=('pokestop', )) self.event_manager.register_event('pokestop_out_of_range', parameters=('pokestop', )) self.event_manager.register_event('pokestop_on_cooldown', parameters=('pokestop', 'minutes_left')) self.event_manager.register_event('unknown_spin_result', parameters=('status_code', )) self.event_manager.register_event('pokestop_searching_too_often') self.event_manager.register_event('arrived_at_fort') # pokemon stuff self.event_manager.register_event( 'catchable_pokemon', parameters=('pokemon_id', 'spawn_point_id', 'encounter_id', 'latitude', 'longitude', 'expiration_timestamp_ms')) self.event_manager.register_event('pokemon_appeared', parameters=( 'pokemon', 'cp', 'iv', 'iv_display', )) self.event_manager.register_event('pokemon_catch_rate', parameters=('catch_rate', 'berry_name', 'berry_count')) self.event_manager.register_event('threw_berry', parameters=('berry_name', 'new_catch_rate')) self.event_manager.register_event('threw_pokeball', parameters=('pokeball', 'success_percentage', 'count_left')) self.event_manager.register_event('pokemon_escaped', parameters=('pokemon', )) self.event_manager.register_event('pokemon_vanished', parameters=('pokemon', )) self.event_manager.register_event('pokemon_caught', parameters=('pokemon', 'cp', 'iv', 'iv_display', 'exp')) self.event_manager.register_event('pokemon_evolved', parameters=('pokemon', 'iv', 'cp')) self.event_manager.register_event('pokemon_evolve_fail', parameters=('pokemon', )) self.event_manager.register_event('skip_evolve') self.event_manager.register_event('threw_berry_failed', parameters=('status_code', )) self.event_manager.register_event('vip_pokemon') # level up stuff self.event_manager.register_event('level_up', parameters=('previous_level', 'current_level')) self.event_manager.register_event('level_up_reward', parameters=('items', )) # lucky egg self.event_manager.register_event('used_lucky_egg', parameters=('amount_left', )) self.event_manager.register_event('lucky_egg_error') # softban self.event_manager.register_event('softban') self.event_manager.register_event('softban_fix') self.event_manager.register_event('softban_fix_done') # egg incubating self.event_manager.register_event('incubate_try', parameters=('incubator_id', 'egg_id')) self.event_manager.register_event('incubate', parameters=('distance_in_km', )) self.event_manager.register_event('next_egg_incubates', parameters=('distance_in_km', )) self.event_manager.register_event('incubator_already_used') self.event_manager.register_event('egg_already_incubating') self.event_manager.register_event('egg_hatched', parameters=('pokemon', 'cp', 'iv', 'exp', 'stardust', 'candy')) # discard item self.event_manager.register_event('item_discarded', parameters=('amount', 'item', 'maximum')) self.event_manager.register_event('item_discard_fail', parameters=('item', )) # inventory self.event_manager.register_event('inventory_full') # release self.event_manager.register_event('keep_best_release', parameters=('amount', 'pokemon', 'criteria')) self.event_manager.register_event('future_pokemon_release', parameters=('pokemon', 'cp', 'iv', 'below_iv', 'below_cp', 'cp_iv_logic')) self.event_manager.register_event('pokemon_release', parameters=('pokemon', 'cp', 'iv')) # polyline walker self.event_manager.register_event('polyline_request', parameters=('url', )) # cluster self.event_manager.register_event('found_cluster', parameters=('num_points', 'forts', 'radius', 'distance')) self.event_manager.register_event('arrived_at_cluster', parameters=('forts', 'radius')) # rename self.event_manager.register_event('rename_pokemon', parameters=('old_name', 'current_name')) self.event_manager.register_event('pokemon_nickname_invalid', parameters=('nickname', )) self.event_manager.register_event('unset_pokemon_nickname') # Move To map pokemon self.event_manager.register_event('move_to_map_pokemon_fail', parameters=('message', )) self.event_manager.register_event('move_to_map_pokemon_updated_map', parameters=('lat', 'lon')) self.event_manager.register_event('move_to_map_pokemon_teleport_to', parameters=('poke_name', 'poke_dist', 'poke_lat', 'poke_lon', 'disappears_in')) self.event_manager.register_event('move_to_map_pokemon_encounter', parameters=('poke_name', 'poke_dist', 'poke_lat', 'poke_lon', 'disappears_in')) self.event_manager.register_event('move_to_map_pokemon_move_towards', parameters=('poke_name', 'poke_dist', 'poke_lat', 'poke_lon', 'disappears_in')) self.event_manager.register_event('move_to_map_pokemon_teleport_back', parameters=('last_lat', 'last_lon')) def tick(self): self.health_record.heartbeat() self.cell = self.get_meta_cell() self.tick_count += 1 # Check if session token has expired self.check_session(self.position[0:2]) for worker in self.workers: if worker.work() == WorkerResult.RUNNING: return def get_meta_cell(self): location = self.position[0:2] cells = self.find_close_cells(*location) # Combine all cells into a single dict of the items we care about. forts = [] wild_pokemons = [] catchable_pokemons = [] for cell in cells: if "forts" in cell and len(cell["forts"]): forts += cell["forts"] if "wild_pokemons" in cell and len(cell["wild_pokemons"]): wild_pokemons += cell["wild_pokemons"] if "catchable_pokemons" in cell and len( cell["catchable_pokemons"]): catchable_pokemons += cell["catchable_pokemons"] # If there are forts present in the cells sent from the server or we don't yet have any cell data, return all data retrieved if len(forts) > 1 or not self.cell: return { "forts": forts, "wild_pokemons": wild_pokemons, "catchable_pokemons": catchable_pokemons } # If there are no forts present in the data from the server, keep our existing fort data and only update the pokemon cells. else: return { "forts": self.cell["forts"], "wild_pokemons": wild_pokemons, "catchable_pokemons": catchable_pokemons } def update_web_location(self, cells=[], lat=None, lng=None, alt=None): # we can call the function with no arguments and still get the position # and map_cells if lat is None: lat = self.api._position_lat if lng is None: lng = self.api._position_lng if alt is None: alt = 0 if cells == []: location = self.position[0:2] cells = self.find_close_cells(*location) # insert detail info about gym to fort for cell in cells: if 'forts' in cell: for fort in cell['forts']: if fort.get('type') != 1: response_gym_details = self.api.get_gym_details( gym_id=fort.get('id'), player_latitude=lng, player_longitude=lat, gym_latitude=fort.get('latitude'), gym_longitude=fort.get('longitude')) fort['gym_details'] = response_gym_details.get( 'responses', {}).get('GET_GYM_DETAILS', None) user_data_cells = "data/cells-%s.json" % self.config.username with open(user_data_cells, 'w') as outfile: json.dump(cells, outfile) user_web_location = os.path.join( 'web', 'location-%s.json' % self.config.username) # alt is unused atm but makes using *location easier try: with open(user_web_location, 'w') as outfile: json.dump({ 'lat': lat, 'lng': lng, 'alt': alt, 'cells': cells }, outfile) except IOError as e: self.logger.info('[x] Error while opening location file: %s' % e) user_data_lastlocation = os.path.join( 'data', 'last-location-%s.json' % self.config.username) try: with open(user_data_lastlocation, 'w') as outfile: json.dump( { 'lat': lat, 'lng': lng, 'start_position': self.start_position }, outfile) except IOError as e: self.logger.info('[x] Error while opening location file: %s' % e) def find_close_cells(self, lat, lng): cellid = get_cell_ids(lat, lng) timestamp = [ 0, ] * len(cellid) response_dict = self.get_map_objects(lat, lng, timestamp, cellid) map_objects = response_dict.get('responses', {}).get('GET_MAP_OBJECTS', {}) status = map_objects.get('status', None) map_cells = [] if status and status == 1: map_cells = map_objects['map_cells'] position = (lat, lng, 0) map_cells.sort( key=lambda x: distance(lat, lng, x['forts'][0]['latitude'], x[ 'forts'][0]['longitude']) if x.get('forts', []) else 1e6) return map_cells def _setup_logging(self): # log settings # log format if self.config.debug: log_level = logging.DEBUG logging.getLogger("requests").setLevel(logging.DEBUG) logging.getLogger("websocket").setLevel(logging.DEBUG) logging.getLogger("socketio").setLevel(logging.DEBUG) logging.getLogger("engineio").setLevel(logging.DEBUG) logging.getLogger("socketIO-client").setLevel(logging.DEBUG) logging.getLogger("pgoapi").setLevel(logging.DEBUG) logging.getLogger("rpc_api").setLevel(logging.DEBUG) else: log_level = logging.ERROR logging.getLogger("requests").setLevel(logging.ERROR) logging.getLogger("websocket").setLevel(logging.ERROR) logging.getLogger("socketio").setLevel(logging.ERROR) logging.getLogger("engineio").setLevel(logging.ERROR) logging.getLogger("socketIO-client").setLevel(logging.ERROR) logging.getLogger("pgoapi").setLevel(logging.ERROR) logging.getLogger("rpc_api").setLevel(logging.ERROR) logging.basicConfig( level=log_level, format='%(asctime)s [%(name)10s] [%(levelname)s] %(message)s') def check_session(self, position): # Check session expiry if self.api._auth_provider and self.api._auth_provider._ticket_expire: # prevent crash if return not numeric value if not self.is_numeric(self.api._auth_provider._ticket_expire): self.logger.info("Ticket expired value is not numeric", 'yellow') return remaining_time = \ self.api._auth_provider._ticket_expire / 1000 - time.time() if remaining_time < 60: self.event_manager.emit( 'api_error', sender=self, level='info', formatted='Session stale, re-logging in.') position = self.position self.api = ApiWrapper() self.position = position self.login() self.api.activate_signature(self.get_encryption_lib()) @staticmethod def is_numeric(s): try: float(s) return True except ValueError: return False def login(self): self.event_manager.emit('login_started', sender=self, level='info', formatted="Login procedure started.") lat, lng = self.position[0:2] self.api.set_position(lat, lng, 0) while not self.api.login(self.config.auth_service, str(self.config.username), str(self.config.password)): self.event_manager.emit( 'login_failed', sender=self, level='info', formatted= "Login error, server busy. Waiting 10 seconds to try again.") time.sleep(10) self.event_manager.emit('login_successful', sender=self, level='info', formatted="Login successful.") def get_encryption_lib(self): if _platform == "linux" or _platform == "linux2" or _platform == "darwin": file_name = 'encrypt.so' elif _platform == "Windows" or _platform == "win32": # Check if we are on 32 or 64 bit if sys.maxsize > 2**32: file_name = 'encrypt_64.dll' else: file_name = 'encrypt.dll' if self.config.encrypt_location == '': path = os.path.abspath( os.path.join(os.path.dirname(__file__), os.pardir)) else: path = self.config.encrypt_location full_path = path + '/' + file_name if not os.path.isfile(full_path): self.logger.error( file_name + ' is not found! Please place it in the bots root directory or set libencrypt_location in config.' ) self.logger.info('Platform: ' + _platform + ' Encrypt.so directory: ' + path) sys.exit(1) else: self.logger.info('Found ' + file_name + '! Platform: ' + _platform + ' Encrypt.so directory: ' + path) return full_path def _setup_api(self): # instantiate pgoapi self.api = ApiWrapper() # provide player position on the earth self._set_starting_position() self.login() # chain subrequests (methods) into one RPC call self._print_character_info() self.api.activate_signature(self.get_encryption_lib()) self.logger.info('') self.update_inventory() # send empty map_cells and then our position self.update_web_location() def _print_character_info(self): # get player profile call # ---------------------- response_dict = self.api.get_player() # print('Response dictionary: \n\r{}'.format(json.dumps(response_dict, indent=2))) currency_1 = "0" currency_2 = "0" if response_dict: self._player = response_dict['responses']['GET_PLAYER'][ 'player_data'] player = self._player else: self.logger.info( "The API didn't return player info, servers are unstable - " "retrying.", 'red') sleep(5) self._print_character_info() # @@@ TODO: Convert this to d/m/Y H:M:S creation_date = datetime.datetime.fromtimestamp( player['creation_timestamp_ms'] / 1e3) creation_date = creation_date.strftime("%Y/%m/%d %H:%M:%S") pokecoins = '0' stardust = '0' items_stock = self.current_inventory() if 'amount' in player['currencies'][0]: pokecoins = player['currencies'][0]['amount'] if 'amount' in player['currencies'][1]: stardust = player['currencies'][1]['amount'] self.logger.info('') self.logger.info('--- {username} ---'.format(**player)) self.get_player_info() self.logger.info('Pokemon Bag: {}/{}'.format( self.get_inventory_count('pokemon'), player['max_pokemon_storage'])) self.logger.info('Items: {}/{}'.format( self.get_inventory_count('item'), player['max_item_storage'])) self.logger.info('Stardust: {}'.format(stardust) + ' | Pokecoins: {}'.format(pokecoins)) # Items Output self.logger.info('PokeBalls: ' + str(items_stock[1]) + ' | GreatBalls: ' + str(items_stock[2]) + ' | UltraBalls: ' + str(items_stock[3])) self.logger.info('RazzBerries: ' + str(items_stock[701]) + ' | BlukBerries: ' + str(items_stock[702]) + ' | NanabBerries: ' + str(items_stock[703])) self.logger.info('LuckyEgg: ' + str(items_stock[301]) + ' | Incubator: ' + str(items_stock[902]) + ' | TroyDisk: ' + str(items_stock[501])) self.logger.info('Potion: ' + str(items_stock[101]) + ' | SuperPotion: ' + str(items_stock[102]) + ' | HyperPotion: ' + str(items_stock[103]) + ' | MaxPotion: ' + str(items_stock[104])) self.logger.info('Incense: ' + str(items_stock[401]) + ' | IncenseSpicy: ' + str(items_stock[402]) + ' | IncenseCool: ' + str(items_stock[403])) self.logger.info('Revive: ' + str(items_stock[201]) + ' | MaxRevive: ' + str(items_stock[202])) self.logger.info('') def use_lucky_egg(self): return self.api.use_item_xp_boost(item_id=301) def get_inventory(self): if self.latest_inventory is None: self.latest_inventory = self.api.get_inventory() return self.latest_inventory def update_inventory(self): response = self.get_inventory() self.inventory = list() inventory_items = response.get('responses', {}).get( 'GET_INVENTORY', {}).get('inventory_delta', {}).get('inventory_items', {}) if inventory_items: for item in inventory_items: item_info = item.get('inventory_item_data', {}).get('item', {}) if {"item_id", "count"}.issubset(set(item_info.keys())): self.inventory.append(item['inventory_item_data']['item']) def current_inventory(self): inventory_req = self.get_inventory() inventory_dict = inventory_req['responses']['GET_INVENTORY'][ 'inventory_delta']['inventory_items'] user_web_inventory = 'web/inventory-%s.json' % self.config.username with open(user_web_inventory, 'w') as outfile: json.dump(inventory_dict, outfile) # get player items stock # ---------------------- items_stock = {x.value: 0 for x in list(Item)} for item in inventory_dict: item_dict = item.get('inventory_item_data', {}).get('item', {}) item_count = item_dict.get('count') item_id = item_dict.get('item_id') if item_count and item_id: if item_id in items_stock: items_stock[item_id] = item_count return items_stock def item_inventory_count(self, id): inventory_req = self.get_inventory() inventory_dict = inventory_req['responses']['GET_INVENTORY'][ 'inventory_delta']['inventory_items'] if id == 'all': return self._all_items_inventory_count(inventory_dict) else: return self._item_inventory_count_per_id(id, inventory_dict) def _item_inventory_count_per_id(self, id, inventory_dict): item_count = 0 for item in inventory_dict: item_dict = item.get('inventory_item_data', {}).get('item', {}) item_id = item_dict.get('item_id', False) item_count = item_dict.get('count', False) if item_id == int(id) and item_count: return item_count return 0 def _all_items_inventory_count(self, inventory_dict): item_count_dict = {} for item in inventory_dict: item_dict = item.get('inventory_item_data', {}).get('item', {}) item_id = item_dict.get('item_id', False) item_count = item_dict.get('count', False) if item_id and item_count: item_count_dict[item_id] = item_count return item_count_dict def _set_starting_position(self): self.event_manager.emit('set_start_location', sender=self, level='info', formatted='Setting start location.') has_position = False if self.config.test: # TODO: Add unit tests return if self.config.location: location_str = self.config.location location = self.get_pos_by_name(location_str.replace(" ", "")) msg = "Location found: {location} {position}" self.event_manager.emit('location_found', sender=self, level='info', formatted=msg, data={ 'location': location_str, 'position': location }) self.api.set_position(*location) self.event_manager.emit('position_update', sender=self, level='info', formatted="Now at {current_position}", data={ 'current_position': self.position, 'last_position': '', 'distance': '', 'distance_unit': '' }) self.start_position = self.position has_position = True if self.config.location_cache: try: # save location flag used to pull the last known location from # the location.json self.event_manager.emit('load_cached_location', sender=self, level='debug', formatted='Loading cached location...') with open('data/last-location-%s.json' % self.config.username) as f: location_json = json.load(f) location = (location_json['lat'], location_json['lng'], 0.0) # If location has been set in config, only use cache if starting position has not differed if has_position and 'start_position' in location_json: last_start_position = tuple( location_json.get('start_position', [])) # Start position has to have been set on a previous run to do this check if last_start_position and last_start_position != self.start_position: msg = 'Going to a new place, ignoring cached location.' self.event_manager.emit('location_cache_ignored', sender=self, level='debug', formatted=msg) return self.api.set_position(*location) self.event_manager.emit( 'position_update', sender=self, level='debug', formatted='Loaded location {current_position} from cache', data={ 'current_position': location, 'last_position': '', 'distance': '', 'distance_unit': '' }) has_position = True except Exception: if has_position is False: sys.exit( "No cached Location. Please specify initial location.") self.event_manager.emit( 'location_cache_error', sender=self, level='debug', formatted='Parsing cached location failed.') def get_pos_by_name(self, location_name): # Check if the given location is already a coordinate. if ',' in location_name: possible_coordinates = re.findall("[-]?\d{1,3}[.]\d{3,7}", location_name) if len(possible_coordinates) == 2: # 2 matches, this must be a coordinate. We'll bypass the Google # geocode so we keep the exact location. self.logger.info( '[x] Coordinates found in passed in location, ' 'not geocoding.') return float(possible_coordinates[0]), float( possible_coordinates[1]), float("0.0") geolocator = GoogleV3(api_key=self.config.gmapkey) loc = geolocator.geocode(location_name, timeout=10) return float(loc.latitude), float(loc.longitude), float(loc.altitude) def heartbeat(self): # Remove forts that we can now spin again. self.fort_timeouts = { id: timeout for id, timeout in self.fort_timeouts.iteritems() if timeout >= time.time() * 1000 } request = self.api.create_request() request.get_player() request.check_awarded_badges() request.call() try: self.web_update_queue.put_nowait( True) # do this outside of thread every tick except Queue.Full: pass def update_web_location_worker(self): while True: self.web_update_queue.get() self.update_web_location() def get_inventory_count(self, what): response_dict = self.get_inventory() inventory_items = response_dict.get('responses', {}).get( 'GET_INVENTORY', {}).get('inventory_delta', {}).get('inventory_items', {}) if inventory_items: pokecount = 0 itemcount = 1 for item in inventory_items: if 'inventory_item_data' in item: if 'pokemon_data' in item['inventory_item_data']: pokecount += 1 itemcount += item['inventory_item_data'].get( 'item', {}).get('count', 0) if 'pokemon' in what: return pokecount if 'item' in what: return itemcount return '0' def get_player_info(self): response_dict = self.get_inventory() inventory_items = response_dict.get('responses', {}).get( 'GET_INVENTORY', {}).get('inventory_delta', {}).get('inventory_items', {}) if inventory_items: pokecount = 0 itemcount = 1 for item in inventory_items: # print('item {}'.format(item)) playerdata = item.get('inventory_item_data', {}).get('player_stats') if playerdata: nextlvlxp = (int(playerdata.get('next_level_xp', 0)) - int(playerdata.get('experience', 0))) if 'level' in playerdata and 'experience' in playerdata: self.logger.info( 'Level: {level}'.format(**playerdata) + ' (Next Level: {} XP)'.format(nextlvlxp) + ' (Total: {experience} XP)' ''.format(**playerdata)) if 'pokemons_captured' in playerdata and 'poke_stop_visits' in playerdata: self.logger.info( 'Pokemon Captured: ' '{pokemons_captured}'.format(**playerdata) + ' | Pokestops Visited: ' '{poke_stop_visits}'.format(**playerdata)) def has_space_for_loot(self): number_of_things_gained_by_stop = 5 enough_space = ( self.get_inventory_count('item') < self._player['max_item_storage'] - number_of_things_gained_by_stop) return enough_space def get_forts(self, order_by_distance=False): forts = [ fort for fort in self.cell['forts'] if 'latitude' in fort and 'type' in fort ] if order_by_distance: forts.sort(key=lambda x: distance(self.position[0], self.position[ 1], x['latitude'], x['longitude'])) return forts def get_map_objects(self, lat, lng, timestamp, cellid): if time.time( ) - self.last_time_map_object < self.config.map_object_cache_time: return self.last_map_object self.last_map_object = self.api.get_map_objects( latitude=f2i(lat), longitude=f2i(lng), since_timestamp_ms=timestamp, cell_id=cellid) self.last_time_map_object = time.time() return self.last_map_object
class TestEventManager(unittest.TestCase): def setUp(self): self.event_manager = EventManager() self.client = MockClient(user_id='60') self.client2 = MockClient(user_id='50') def test_add_client(self): self.assertEqual(len(self.event_manager.clients), 0) self.event_manager.add_client(self.client) self.assertEqual(len(self.event_manager.clients), 1) self.assertEqual(self.event_manager.clients[self.client.user_id].user_id, self.client.user_id) def test_remove_client(self): self.event_manager.clients[self.client.user_id] = self.client self.assertEqual(len(self.event_manager.clients), 1) self.assertEqual(self.event_manager.clients[self.client.user_id].user_id, self.client.user_id) self.event_manager.remove_client(self.client.user_id) self.assertEqual(len(self.event_manager.clients), 0) def test_wrong_event(self): bogus_event = '666\F/60D50' with self.assertRaises(AssertionError): self.event_manager.receive_event(bogus_event) def test_follow_event_no_user(self): follow_event = '666|F|60|50' self.assertEqual(len(self.event_manager.clients), 0) self.assertEqual(len(self.event_manager.followers), 0) self.event_manager.receive_event(follow_event) self.assertEqual(len(self.event_manager.clients), 0) self.assertEqual(len(self.event_manager.followers), 1) self.assertIn('50', self.event_manager.followers) self.assertIn('60', self.event_manager.followers['50']) def test_follow_event_with_user(self): follow_event = '666|F|60|50' self.event_manager.add_client(self.client) self.event_manager.add_client(self.client2) self.assertEqual(len(self.event_manager.clients), 2) self.assertEqual(len(self.event_manager.followers), 0) self.event_manager.receive_event(follow_event) self.assertEqual(len(self.event_manager.clients), 2) self.assertEqual(len(self.event_manager.followers), 1) self.assertIn('50', self.event_manager.followers) self.assertIn('60', self.event_manager.followers['50']) def test_un_follow(self): self.event_manager.followers.setdefault('60', set()).add('50') response = self.event_manager.u_event('50', '60') self.assertEqual(len(self.event_manager.followers['60']), 0) self.assertEqual(len(response), 0) # no one is informed def test_broadcast_event(self): self.event_manager.add_client(self.client) self.event_manager.add_client(self.client2) response = self.event_manager.b_event() self.assertEqual(len(response), 2) self.assertIn(self.client.user_id, response) self.assertIn(self.client2.user_id, response) def test_status_event(self): self.event_manager.followers.setdefault(self.client.user_id, set()).add(self.client2.user_id) response = self.event_manager.s_event(self.client.user_id) self.assertEqual(len(response), 1) self.assertIn(self.client2.user_id, response) def test_send_message_event(self): self.event_manager.followers.setdefault(self.client.user_id, set()).add(self.client2.user_id) response = self.event_manager.p_event(self.client.user_id, self.client2.user_id) self.assertEqual(len(response), 1) self.assertIn(self.client2.user_id, response)
def setUp(self): self.event_manager = EventManager() self.client = MockClient(user_id='60') self.client2 = MockClient(user_id='50')
class ActionMachine(object): # DIO def __init__(self, novel_helper, robot_army): self.nh = novel_helper self.novel_helper = novel_helper self.book_warehouse = self.nh.book_warehouse self.robot_army = robot_army self.user_map = dict() self.init_user_map() self.book_map = dict() self.init_book_map() self.offline_uid_set = set(list(self.user_map.keys())) self.recommend_uid_set = set() self.choosing_uid_set = set() self.click_drive_uid_set = set() self.read_drive_uid_set = set() self.reading_uid_set = set() self.has_online_set = set() self._period = 0 self.recommend_sys = RecommendSysBuiltin(self) self.event_manager = EventManager(self) self.event_manager.clean_all_csv() def get_period(self): return self._period def init_user_map(self): for regiment in self.robot_army.regiment: for robot in regiment.robot: uid = robot.uid robot_user = RobotUser(robot) self._init_use_app_info(robot_user) self.user_map[uid] = robot_user def init_book_map(self): for book_def in self.book_warehouse.book: bid = book_def.bid self.book_map[bid] = Book(book_def) # 因为wv_word_idx_map里的key是word2vec产生的,所以有的词是没有的,要过滤掉 def _fill_no_title(self, word_list): new_word_list = [] for word in word_list: if word in self.nh.wv_word_idx_map: new_word_list.append(word) if not len(new_word_list): return ['no', 'title'] return new_word_list def _fill_empty_word_list(self, word_list): word_list = [ word for word in word_list if word in self.novel_helper.wv_word_idx_map ] if not word_list: word_list = ['empty', 'word', 'list'] return word_list def judge_robot_click_book(self, robot_user, book): score = self._get_robot_click_book_score(robot_user, book) if score > Args.ub_dot_threshold_alpha: return True return False # 统计查询,会先检查sqlite-in-memory的建表状态 def query(self, sql_text, reprepare=True): r = self.event_manager.query(sql_text, reprepare) return r # 更新用户的addict_value def update_addict_value(self, robot_user, update_type, score): if random.random() < Args.clean_addict_value_rate: robot_user.addict_value = -random.random() return if update_type == AddictUpdateType.CLICK: robot_user.addict_value += score elif update_type == AddictUpdateType.CHAPTER: robot_user.addict_value += score elif update_type == AddictUpdateType.DETEST: robot_user.addict_value -= random.random( ) * Args.addict_value_detest_rate elif update_type == AddictUpdateType.OFFLINE: robot_user.addict_value += robot_user.addict_value_restore_rate # 驱动分值:点击 # click_drive_score, chapter_read_drive_score, open_app_drive_score, detest_drive_score def _get_robot_click_book_score(self, robot_user, book): book_def = book.book_def title_word = list(book_def.title.word) synopsis_word = list(book_def.synopsis.word) book_word_list = self._fill_no_title(title_word + synopsis_word) user_word_list = [ei.word for ei in robot_user.robot_def.ei] book_vector = self._word_list_vector_pooling(book_word_list) user_vector = self._word_list_vector_pooling(user_word_list) score_sum = np.dot(book_vector, user_vector) score = score_sum / (len(book_word_list) * len(user_word_list)) return score # 对word_list取词向量做pooling是常见操作 def _word_list_vector_pooling(self, word_list): wv_word_idx_map = self.nh.wv_word_idx_map wv_vector = self.nh.wv_model.vectors word_idx_list = [wv_word_idx_map[word.lower()] for word in word_list] word_vector_list = [wv_vector[idx] for idx in word_idx_list] sum_vector = np.sum(word_vector_list, axis=0) return sum_vector # book_word多会用到,robot_word会分成多个sub_robot_word_list与book_word_list做 # 点积,这代表每次阅读机器人用户的关注点是不同的,同时也能引入随机量 def _dot_robot_book(self, robot_word_list, book_word_list, sample_loop): robot_word_list = self._fill_empty_word_list(robot_word_list) book_word_list = self._fill_empty_word_list(book_word_list) kb = len(book_word_list) kr = len(robot_word_list) sample_word_count = (kr - 1) // sample_loop + 1 sub_dot_score_list = [] book_vector = self._word_list_vector_pooling(book_word_list) for _ in range(sample_loop): sub_robot_word_list = random.sample(robot_word_list, sample_word_count) krp = len(sub_robot_word_list) sub_robot_vector = self._word_list_vector_pooling( sub_robot_word_list) sub_dot_score = np.dot(sub_robot_vector, book_vector) sub_dot_score /= (kb * krp) sub_dot_score_list.append(sub_dot_score) dot_score = max(sub_dot_score_list) return dot_score def _get_click_drive_score(self, robot_user, book, sample_loop=Args.default_sample_loop): # 传入book而非book_def是因为这样后续能让book中pb_def外的字段来参与算分 robot_def = robot_user._robot_def book_def = book._book_def robot_enlighten_info_list = robot_def.ei robot_enlighten_word_list = [ enlighten_info.word for enlighten_info in robot_enlighten_info_list ] title_word_list = S.sentence_to_string_list(book_def.title) synopsis_word_list = S.sentence_to_string_list(book_def.synopsis) title_synopsis_word_list = title_word_list + synopsis_word_list click_drive_score = self._dot_robot_book(robot_enlighten_word_list, synopsis_word_list, sample_loop=sample_loop) return click_drive_score def _get_read_drive_score(self, robot_user, book, chapter, sample_loop=Args.default_sample_loop): robot_def = robot_user._robot_def book_def = book._book_def robot_enlighten_info_list = robot_def.ei robot_enlighten_word_list = [ enlighten_info.word for enlighten_info in robot_enlighten_info_list ] paragraph_all_count = len(book_def.paragraph) assert paragraph_all_count >= chapter and chapter > 0, \ "chapter must in range %s>=chapter>=1 but get %s" % (paragraph_all_count, chapter) to_read_paragraph = book_def.paragraph[chapter - 1] paragraph_word_list = S.paragraph_to_string_list(to_read_paragraph) read_drive_score = self._dot_robot_book(robot_enlighten_word_list, paragraph_word_list, sample_loop=sample_loop) return read_drive_score def _get_title_detest_drive_score(self, robot_user, book, sample_loop=Args.default_sample_loop): robot_def = robot_user._robot_def book_def = book._book_def robot_detest_info_list = robot_def.detest_ei robot_detest_word_list = [ enlighten_info.word for enlighten_info in robot_detest_info_list ] title_word_list = S.sentence_to_string_list(book_def.title) synopsis_word_list = S.sentence_to_string_list(book_def.synopsis) title_synopsis_word_list = title_word_list + synopsis_word_list detest_drive_score = self._dot_robot_book(robot_detest_word_list, title_synopsis_word_list, sample_loop=sample_loop) return detest_drive_score def _get_detest_drive_score(self, robot_user, book, chapter, sample_loop=Args.default_sample_loop): robot_def = robot_user._robot_def book_def = book._book_def robot_detest_info_list = robot_def.detest_ei robot_detest_word_list = [ enlighten_info.word for enlighten_info in robot_detest_info_list ] paragraph_all_count = len(book_def.paragraph) assert paragraph_all_count >= chapter and chapter > 0, \ "chapter must in range %s>=chapter>=1 but get %s" % (paragraph_all_count, chapter) to_read_paragraph = book.paragraph[chapter - 1] paragraph_word_list = S.paragraph_to_string_list(to_read_paragraph) detest_drive_score = self._dot_robot_book(robot_detest_word_list, paragraph_word_list, sample_loop=sample_loop) return detest_drive_score def _get_addict_drive_score(self, robot_user, book, chapter, sample_loop=Args.default_sample_loop): robot_def = robot_user._robot_def book_def = book._book_def robot_addict_info_list = robot_def.addict_ei robot_addict_word_list = [ enlighten_info.word for enlighten_info in robot_addict_info_list ] paragraph_all_count = len(book_def.paragraph) assert paragraph_all_count >= chapter and chapter > 0, \ "chapter must in range %s>=chapter>=1 but get %s" % (paragraph_all_count, chapter) to_read_paragraph = book.paragraph[chapter - 1] paragraph_word_list = S.paragraph_to_string_list(to_read_paragraph) addict_drive_score = self._dot_robot_book(robot_addict_word_list, paragraph_word_list, sample_loop=sample_loop) return addict_drive_score def _get_normal_noise(self, noise_range=1.): return noise_range * random.gauss(0., 1.) def _drive_click(self, robot_user, book): drive_success = False click_drive_score = self._get_click_drive_score(robot_user, book) click_drive_score += self._get_normal_noise(0.1) if click_drive_score > Args.click_drive_threshold: drive_success = True return (drive_success, click_drive_score) def _drive_read(self, robot_user, book, chapter): drive_success = False read_drive_score = self._get_read_drive_score(robot_user, book, chapter) read_drive_score += self._get_normal_noise(0.1) if read_drive_score > Args.read_drive_threshold: drive_success = True addict_drive_score = self._get_addict_drive_score( robot_user, book, chapter) robot_user.addict_value += (addict_drive_score - 0.05) return (drive_success, read_drive_score, addict_drive_score) def _drive_detest(self, robot_user, book, chapter=0): drive_success = False if chapter == 0: detest_drive_score = self._get_title_detest_drive_score( robot_user, book) else: detest_drive_score = self._get_detest_drive_score(robot_user, book) detest_drive_score += self._get_normal_noise(0.1) if detest_drive_score > Args.detest_drive_threshold: drive_success = True robot_user.detest_value += (detest_drive_score - 0.05) return (drive_success, detest_drive_score, robot_user.detest_value) # 判断机器人是否会(继续)使用app def _drive_use_app(self, robot_user): use_app = False addict_value = robot_uesr.addict_value detest_value = robot_user.detest_value addict_value += self._get_normal_noise(0.1) detest_value += self._get_normal_noise(0.1) if addict_value > 0 and detest_value < 0: use_app = True return (use_app, addict_value, detest_value) def judge_robot_finish_chapter(self, robot_user, paragraph): score = self._get_robot_finish_chapter_score(robot_user, paragraph) if score > Args.ub_dot_chapter_finish_threshold_alpha: return True return False # 驱动分值:读完一章 def _get_robot_finish_chapter_score(self, robot_user, paragraph): paragraph_word_list = S.paragraph_to_string_list(paragraph) paragraph_word_list = S.lower_string_list(paragraph_word_list) book_word_list = self._fill_no_title(paragraph_word_list) user_word_list = [ei.word for ei in robot_user.robot_def.ei] book_vector = self._word_list_vector_pooling(book_word_list) user_vector = self._word_list_vector_pooling(user_word_list) score_sum = np.dot(book_vector, user_vector) score = score_sum / (len(book_word_list) * len(user_word_list)) return score def _report_robot_user_status(self): report_message_list = [] report_message_list.append('period: %s' % self._period) report_message_list.append('offline: %s' % len(self.offline_uid_set)) report_message_list.append('recommend: %s' % len(self.recommend_uid_set)) report_message_list.append('choosing: %s' % len(self.choosing_uid_set)) report_message_list.append('click_drive: %s' % len(self.click_drive_uid_set)) report_message_list.append('read_drive: %s' % len(self.read_drive_uid_set)) report_message_list.append('reading: %s' % len(self.reading_uid_set)) # report_message_list.append('has_online: %s' % len(self.has_online_set)) report_message = ','.join(report_message_list) logging.error(report_message) # self.metrics_writer.record_action_machine() # 在关闭app时做的收尾工作 def _just_shut_down_app(self, robot_user): robot_user._addict_value -= 0.5 # 更新_addict_value恢复速率 def _update_addict_value_restore_rate(self, robot_user): self._addict_value_restore_rate = self._addict_value_restore_rate # # offline状态 # def _run_robot_offline(self, robot_user): # robot_user._addict_value += robot_user._addict_value_restore_rate # addict_value = robot_user._addict_value # if addict_value > 0: # robot_user._status = RobotStatus.RECOMMEND # def _run_robot_choosing(self, robot_user): # self.update_addict_value(robot_user, AddictUpdateType.DETEST, 0) # robot_user.choosing_delay -= 1 # if robot_user.choosing_delay > 0: # robot_user.status = RobotStatus.CHOOSING # else: # robot_user.status = RobotStatus.CLICK_DRIVE # def _run_robot_click_drive(self, robot_user): # # 生成机器人的点击驱动分数,判断是否会发生点击行为 # for bid in robot_user.choosing_bid_list: # # 该刷已经点过的book_id,断不会再点 # if bid in robot_user.chosen_bid_set: # continue # # 之前展现过,但没点击过的,不会再点(todo: 软性降权,而不是直接不点) # if bid in robot_user.history_impr_map: # continue # book = self.book_map[bid] # click_score = self._get_robot_click_book_score(robot_user, book) # self.update_addict_value(robot_user, AddictUpdateType.CLICK, click_score) # if click_score >= Args.ub_dot_threshold_alpha: # self.event_manager.emit_one_event(uid=robot_user.uid, bid=bid, event='go_detail') # robot_user.reading_bid = bid # robot_user.chosen_bid_set.add(bid) # break # if robot_user.reading_bid is not None: # robot_user.status = RobotStatus.READING # elif self.get_addict_value(robot_user) > 0: # # 如果多次执行到这里,那就是所谓的`狂刷` # robot_user.status = RobotStatus.RECOMMEND # else: # # 执行到这里代表推荐的不好,用户关app了 # robot_user.status = RobotStatus.OFFLINE # def _run_robot_read_drive(self, robot_user): # read_drive_score = random.random() # drive_chapter = robot_user.reading_chapter + 1 # # todo drive_chapter calc # if read_drive_score < 0.1: # robot_user.reading_chapter += 1 # robot_user.status = RobotStatus.READING # robot_user.chapter_finish_delay = 3 # else: # # 返回列表页选择 # robot_user.status = RobotStatus.CLICK_DRIVE # def _run_robot_reading(self, robot_user): # self.update_addict_value(robot_user, AddictUpdateType.DETEST, 0) # robot_user.chapter_finish_delay -= 1 # if robot_user.chapter_finish_delay <= 0: # robot_user.status = RobotStatus.READ_DRIVE # else: # robot_user.status = RobotStatus.READING # return # # 获取用户热情度,用来决定是否继续使用产品 # def get_addict_value(self, robot_user): # return robot_user.addict_value def _init_use_app_info(self, robot_user): robot_user._use_app_impulse_value = random.random( ) - 0.99 # 有20%的用户会直接开app robot_user._addict_rate = random.random() robot_user._detest_rate = random.random() # 根据_recent_***那些变量俩计算 def _update_addict_rate(self, robot_user): addict_rate_room_decay = .8 addict_rate_room = 1. - robot_user._addict_rate addict_rate_room *= addict_rate_room_decay robot_user._addict_rate = 1. - addict_rate_room # 根据_recent_***那些变量俩计算 def _update_detest_rate(self, robot_user): detest_rate_decay = .8 robot_user._detest_rate *= detest_rate_decay def _update_use_app_impulse_value(self, robot_user): for bid, reading_info in robot_user._history_read_map.items(): bid_addict_value = reading_info.addict_value # 尚未想好bid_addict_value怎么影响_use_app_impulse_value delta = (robot_user._addict_rate - robot_user._detest_rate) * 1. robot_user._use_app_impulse_value += delta def _run_robot_offline(self, robot_user): if robot_user._use_app_impulse_value > 0: robot_user._status = RobotStatus.RECOMMEND else: robot_user._status = RobotStatus.OFFLINE self._update_use_app_impulse_value(robot_user) self._update_addict_rate(robot_user) self._update_detest_rate(robot_user) def _run_robot_recommend(self, robot_user): self.recommend_sys.recommend(robot_user) robot_user._chosen_bid_set.clear() robot_user._choosing_delay = 2 robot_user._reading_bid = None robot_user._status = RobotStatus.CHOOSING for bid in robot_user._choosing_bid_list: self.event_manager.emit_one_event(uid=robot_user.uid, bid=bid, event='impression') def _run_robot_choosing(self, robot_user): if robot_user._choosing_delay > 0: robot_user._status = RobotStatus.CHOOSING else: robot_user._status = RobotStatus.CLICK_DRIVE robot_user._choosing_delay -= 1 def _run_robot_click_drive(self, robot_user): for bid in robot_user._choosing_bid_list: if bid in robot_user._chosen_bid_set: continue book = self.book_map[bid] click_drive_score = self._get_click_drive_score(robot_user, book, sample_loop=1) if bid in robot_user._history_impr_map: suppress_rate = .5 else: suppress_rate = 1. # sys.stdout.write("\r %s" % click_drive_score) click_drive_score *= suppress_rate if click_drive_score > Args.click_drive_threshold: robot_user._reading_bid = bid robot_user._chosen_bid_set.add(bid) robot_user._history_read_map[bid] = ReadingInfo( last_period=self._period, chapter=0, addict_value=0) break if random.random() < 0.1: # 10%的概率会被机器人记住“给我推过了” robot_user._history_impr_map[bid] = ImpressionInfo( last_period=self._period) if robot_user._reading_bid: robot_user._status = RobotStatus.READ_DRIVE else: # todo: not only OFFLINE, but also RECOMMEND robot_user._status = RobotStatus.OFFLINE # chapter记录的是之前读完哪一章了,之后从下一章开始读 def _run_robot_read_drive(self, robot_user): robot_user._status = RobotStatus.OFFLINE bid = robot_user._reading_bid book = self.book_map[bid] reading_info = robot_user._history_read_map[bid] reading_info.chapter += 1 if reading_info.chapter > len(book._book_def.paragraph): # 返回第一章继续阅读 reading_info.chapter = 1 read_drive_score = self._get_read_drive_score( robot_user, book, chapter=reading_info.chapter, sample_loop=1) if read_drive_score > Args.read_drive_threshold: robot_user._status = RobotStatus.READING robot_user._chapter_finish_delay = 3 else: robot_user._status = RobotStatus.CHOOSING def _run_robot_reading(self, robot_user): if robot_user._chapter_finish_delay > 0: robot_user._status = RobotStatus.READING robot_user._chapter_finish_delay -= 1 else: robot_user._status = RobotStatus.READ_DRIVE def run_one_period(self): self._period += 1 for uid in self.offline_uid_set: robot_user = self.user_map[uid] self._run_robot_offline(robot_user) for uid in self.recommend_uid_set: robot_user = self.user_map[uid] self._run_robot_recommend(robot_user) for uid in self.choosing_uid_set: robot_user = self.user_map[uid] self._run_robot_choosing(robot_user) for uid in self.click_drive_uid_set: robot_user = self.user_map[uid] self._run_robot_click_drive(robot_user) for uid in self.read_drive_uid_set: robot_user = self.user_map[uid] self._run_robot_read_drive(robot_user) for uid in self.reading_uid_set: robot_user = self.user_map[uid] self._run_robot_reading(robot_user) self._update_robot_status() self._report_robot_user_status() def run(self, k=Args.period_threshold): self._period = 0 while self._period + 1 <= k: self.run_one_period() # 在每一peroid结束时进行 def _update_robot_status(self): self.offline_uid_set.clear() self.recommend_uid_set.clear() self.choosing_uid_set.clear() self.click_drive_uid_set.clear() self.read_drive_uid_set.clear() self.reading_uid_set.clear() for uid, robot_user in self.user_map.items(): status = robot_user._status # sys.stdout.write('%s'%status) if status == RobotStatus.OFFLINE: self.offline_uid_set.add(uid) elif status == RobotStatus.RECOMMEND: self.recommend_uid_set.add(uid) elif status == RobotStatus.CHOOSING: self.choosing_uid_set.add(uid) elif status == RobotStatus.CLICK_DRIVE: self.click_drive_uid_set.add(uid) elif status == RobotStatus.READ_DRIVE: self.read_drive_uid_set.add(uid) elif status == RobotStatus.READING: self.reading_uid_set.add(uid)
from player import Player from event_manager import EventManager from db_connector import DbConnector from data_listener import BookListener initial_money = 10000 player_name = 'Notroop' em = EventManager() conn = DbConnector('postgres', 5432, 'postgres', '127.0.0.1') file_path = 'D:\\genericbacktesters\\book_data\\file.dat' bl = BookListener('', 12347, file_path) player = Player(initial_money, player_name, em, conn) symbol = 'YESBANK_EQ' price = 1000 direction = 'SHORT' quantity = 50 order_id = '9f04581c-a00b-4cd1-bb07-fd25ecf64315' player.place_new_order(symbol, price, direction, quantity)
from event_manager import EventManager manager = EventManager() manager.start()
class Scenario: def __init__(self, background=None): if background!=None: self.set_background(background) self.event_manager = EventManager() self.subscribe(pygame.QUIT, "quit", self) self.items = pygame.sprite.Group() def set_background(self, background): self.background = pygame.image.load(background) self.size = self.background.get_size() self.surface = pygame.display.set_mode(self.size) self.backgroundRect = self.background.get_rect() self.set_limits( (0, 0, self.size[0], self.size[1])) def set_limits(self, limits): self.limits = limits def add(self, item): self.items.add(item) Logger.log_debug("Added "+ str(item)) def remove(self, item): self.items.remove(item) Logger.log_debug("Removed "+ str(item)) def render(self): self.surface.blit(self.background, self.backgroundRect) self.items.draw(self.surface) pygame.display.flip() def subscribe(self, event, action, handler): self.event_manager.add(event, action, handler) Logger.log_debug("Event "+str(event)+" subscribed "+str(handler)+"#"+str(action)) def unsubscribe(self, event, action, handler): self.event_manager.remove(event, action, handler) Logger.log_debug("Event "+str(event)+" unsubscribed "+str(handler)+"#"+str(action)) def post_event(self, code, info): pygame.event.post(pygame.event.Event(code, info)) def update(self): self.event_manager.handle(pygame.event.get()) self.items.update() def quit(self, event): pygame.quit() sys.exit() def position_allowed(self, item, position): half_size = (item.get_size()[0]/2, item.get_size()[1]/2) if position[0] - half_size[0] < self.limits[0]: return False if position[1] - half_size[0] < self.limits[1]: return False if position[0] + half_size[0] > self.limits[2]: return False if position[1] + half_size[1] > self.limits[3]: return False return True
class TapiocaBot(sc2.BotAI): def __init__(self, verbose=False, visual_debug=False): self.verbose = verbose self.visual_debug = visual_debug ipdb.launch_ipdb_on_exception() # Control Stuff self.researched_warpgate = False # Remove me later # Managers and controllers self.worker_controller = WorkerController(bot=self, verbose=self.verbose) self.army_controller = ArmyController(bot=self, verbose=self.verbose) self.scouting_controller = ScoutingController(bot=self, verbose=self.verbose) self.upgrades_controller = UpgradesController(bot=self, verbose=self.verbose) self.robotics_facility_controller = RoboticsFacilitiyController( bot=self, verbose=self.verbose, ) self.gateway_controller = GatewayController( bot=self, verbose=self.verbose, auto_morph_to_warpgate=True) self.building_controller = BuildingController(bot=self, verbose=self.verbose) self.event_manager = EventManager() self.build_order_controller = BuildOrderController( verbose=self.verbose, bot=self) self.coordinator = Coordinator(bot=self, verbose=self.verbose, build_order='three_gate_blink_all_in') self.order_queue = [] def on_start(self): self.army_controller.init() self.event_manager.add_event(self.worker_controller.step, 0.1, jitter=0) self.event_manager.add_event( self.building_controller.update_nexus_list, 2.5) self.event_manager.add_event(self.build_order_controller.step, 0.5) self.event_manager.add_event(self.army_controller.step, 0.1, jitter=0) self.event_manager.add_event(self.coordinator.step, 1) self.coordinator.on_start() async def on_step(self, iteration): if iteration == 0: # Do nothing on the first iteration to avoid # everything being done at the same time if self.verbose: print('\n------------------------\n') print('%8.2f %3d Rise and Shine' % (self.time, self.supply_used)) await self.chat_send( "Cry 'havoc', and let slip the Tapiocas of war!") return events = self.event_manager.get_current_events(self.time) for event in events: await event() await self.debug() await self.execute_order_queue() if self.verbose: sys.stdout.flush() async def do(self, action): self.order_queue.append(action) async def execute_order_queue(self): await self._client.actions(self.order_queue, game_data=self._game_data) self.order_queue = [] async def debug(self): if not self.visual_debug: return # Setup and info font_size = 14 total_units = 0 for unit_type in self.army_controller.units_available_for_attack.keys( ): total_units += self.units(unit_type).idle.amount # Text messages = [ ' n_workers: %3d' % self.units(UnitTypeId.PROBE).amount, ' n_stalkers: %3d' % self.units(UnitTypeId.STALKER).amount, ' militia_size: %3d' % len(self.worker_controller.militia_controller.militia), '', 'ememy_structures_nearby: %3d' % len(self.worker_controller.militia_controller. nearby_enemy_structures_found), ' ememy_workers_nearby: %3d' % len(self.worker_controller.militia_controller. nearby_enemy_workers_found), ' ememy_units_nearby: %3d' % len(self.worker_controller.militia_controller. nearby_enemy_units_found), '', ' know_enemy_structures: %3d' % len(self.known_enemy_structures) ] y = 0 inc = 0.018 for message in messages: self._client.debug_text_screen(message, pos=(0.001, y), size=font_size) y += inc # 3D text debug_army_state = False if debug_army_state: for tag in self.army_controller.soldiers: unit = self.units.find_by_tag(tag) if unit is not None: message = self.army_controller.soldiers[tag]['state'] self._client.debug_text_world(message, pos=unit.position3d, size=font_size) # Spheres debug_army_groups = False if debug_army_groups: leader_tag = self.army_controller.leader for soldier_tag in self.army_controller.soldiers: soldier_unit = self.units.find_by_tag(soldier_tag) if soldier_unit is not None: if soldier_tag == leader_tag: self._client.debug_sphere_out(soldier_unit, r=1, color=(255, 0, 0)) else: self._client.debug_sphere_out(soldier_unit, r=1, color=(0, 0, 255)) # Lines if debug_army_groups: if self.army_controller.army_size() > 0: leader_tag = self.army_controller.leader leader_unit = self.units.find_by_tag(leader_tag) for soldier_tag in self.army_controller.soldiers: if soldier_tag == leader_tag: continue soldier_unit = self.units.find_by_tag(soldier_tag) if soldier_unit is not None: leader_tag = self.army_controller.leader leader_unit = self.units.find_by_tag(leader_tag) if leader_unit is not None: self._client.debug_line_out(leader_unit, soldier_unit, color=(0, 255, 255)) # Attack Lines debug_army_attack = False if debug_army_attack: if self.army_controller.army_size() > 0: for soldier_tag in self.army_controller.soldiers: soldier_unit = self.units.find_by_tag(soldier_tag) if soldier_unit is not None and \ self.army_controller.soldiers[soldier_tag]['state'] == 'attacking' and \ self.army_controller.attack_target is not None: self._client.debug_line_out( soldier_unit, self.army_controller.attack_target, color=(255, 127, 0)) # Sens the debug info to the game await self._client.send_debug() def get_unit_info(self, unit, field="food_required"): assert isinstance(unit, (Unit, UnitTypeId)) if isinstance(unit, Unit): unit = unit._type_data._proto else: unit = self._game_data.units[unit.value]._proto if hasattr(unit, field): return getattr(unit, field) else: return None
def runTest(self): manager = EventManager(["./pkgs/"]) for i in xrange(30): manager.notify()
def __init__(self, window): self.window = window self.client = Client.get_instance() self.event_manager = EventManager.get_instance()
def main(): # Config is a wrapper for a socket, and a channel (for now) _config = config.Config(socketutils.connect_to_config(cf), cf.CHANNEL) # This is to determine whether we log information or not if cf.DO_LOG: print("Doing logging.") logging.set_logfile_func(cf.get_log_filename) if not cf.DO_STDOUT: logging.set_print_function(logging.no_print) else: print("Doing printing.") log = logging.log log_all = False # API takes an object with socket and channel members _api = ut.API(_config) _manager = EventManager(_api) # _manager.add_event(EveryLoopEvent(_callable=None, _api=_api, _manager=_manager, runs_till_event=30, # extra_event=functools.partial(_api.send, "There have been 10 loops!"))) can_make_commanders = [ 'dfolder' ] # This could be loaded from a configuration file & saved back to there commanders = ['dfolder'] log('Starting bot. Information:\n\tSocket:', str(_api.socket), '\n\tChannel:', _api.channel) while True: do_events(_api, _manager) full_response = _api.resp() _api.extend_resp_list(full_response) while full_response is not None and len(full_response) > 0: response = full_response.pop(0) did_something = False # We got a response from the server! # First, let's clean it up if we're in full mode. # This means that the response looks really ugly & includes a bunch of unnecessary information at the start. if _api.full_mode: try: full_information = re.search( r'^@badges=[\w/0-9,]*;color=[\w/0-9,]*;display-name=(\w*);.*?user-type=[\w/0-9,]* (.*)', response) log('[FULL RESPONSE]', full_information.strip('\r\n')) except TypeError: full_information = None log("Got erroneous response: ") log(str(response)) if full_information is not None: log('[SENDER]', full_information.group(1)) response = full_information.group(2) log('[RESPONSE]', response.strip('\r\n')) command = re.search( r':(\w*)!\1@\1\.tmi\.twitch\.tv PRIVMSG #\w* : *~(.+)$', response) if command is not None: _command = command.group(2).strip('\r\n ') _caller = command.group(1) _args = None if len(_command.split( ' ', 1)) <= 1 else _command.split(' ', 1)[1] _command = _command.split(' ')[0].lower() if _caller in can_make_commanders: if log_all: log('[2] Executing command: ' + _command + ' with args: ' + str(_args)) if _command == 'conscript': commanders.append(_args.lower()) did_something = True elif _command == 'decommission': commanders.remove(_args.lower()) did_something = True if _caller in commanders: # This should be improved later, but we're going to just check the command here if log_all: log('[1] Executing command: ' + _command + ' with args: ' + str(_args)) if _command == 'stop': _manager.add_event_t( SendMessageEvent, message="Why don't you love me...", after_run=functools.partial( ut.safe_exit, _config, 0)) elif _command == 'print_full_debug': log_all = True log("Enabled full debugging mode.") elif _command == 'no_full_debug': log_all = False elif _command == 'debug': log("Attempting to print debug messages:") log("Manager debug:") log(_manager.dump_debug()) log("Command arguments:") log(str(_args)) log("Current commanders:") log(str(commanders)) # _manager.add_event_t(GetNoticesEvent) elif _command == 'say' and _args is not None: _manager.add_event_t(SendMessageEvent, message=_args) elif _command == 'cap_req' and _args is not None: _manager.add_event_t(SendCapReqEvent, message=_args) elif _command == 'send_exact' or _command == 'say_exact' and _args is not None: _manager.add_event_t(SendExactEvent, message=_args) elif _command == 'enable_full': _manager.add_event( Event(_event=ut.enable_full, _api=_api, _manager=_manager)) elif _command == 'flush_log': log("Flushing log.") logging.flush() elif not did_something: # We didn't set moderator privileges and we don't have command use if log_all: log('The user ' + _caller + ' attempted to use ' + _command + ' with args: ' + str(_args)) _manager.add_event_t( SendMessageEvent, message="Please stop trying to abuse me, " + _caller + ".") # This is to avoid making Twitch angry time.sleep(0.75)
class PokemonGoBot(Datastore): @property def position(self): return self.api.actual_lat, self.api.actual_lng, self.api.actual_alt @property def noised_position(self): return self.api.noised_lat, self.api.noised_lng, self.api.noised_alt #@position.setter # these should be called through api now that gps replication is there... #def position(self, position_tuple): # self.api._position_lat, self.api._position_lng, self.api._position_alt = position_tuple @property def player_data(self): """ Returns the player data as received from the API. :return: The player data. :rtype: dict """ return self._player def __init__(self, config): # Database connection MUST be setup before migrations will work self.database = _init_database('/data/{}.db'.format(config.username)) self.config = config super(PokemonGoBot, self).__init__() self.fort_timeouts = dict() self.pokemon_list = json.load( open(os.path.join(_base_dir, 'data', 'pokemon.json')) ) self.item_list = json.load(open(os.path.join(_base_dir, 'data', 'items.json'))) # @var Metrics self.metrics = Metrics(self) self.latest_inventory = None self.cell = None self.recent_forts = [None] * config.forts_max_circle_size self.tick_count = 0 self.softban = False self.start_position = None self.last_map_object = None self.last_time_map_object = 0 self.logger = logging.getLogger(type(self).__name__) self.alt = self.config.gps_default_altitude # Make our own copy of the workers for this instance self.workers = [] # Theading setup for file writing self.web_update_queue = Queue.Queue(maxsize=1) self.web_update_thread = threading.Thread(target=self.update_web_location_worker) self.web_update_thread.start() # Heartbeat limiting self.heartbeat_threshold = self.config.heartbeat_threshold self.heartbeat_counter = 0 self.last_heartbeat = time.time() self.capture_locked = False # lock catching while moving to VIP pokemon client_id_file_path = os.path.join(_base_dir, 'data', 'mqtt_client_id') saved_info = shelve.open(client_id_file_path) key = 'client_id'.encode('utf-8') if key in saved_info: self.config.client_id = saved_info[key] else: self.config.client_id = str(uuid.uuid4()) saved_info[key] = self.config.client_id saved_info.close() def start(self): self._setup_event_system() self._setup_logging() self.sleep_schedule = SleepSchedule(self, self.config.sleep_schedule) if self.config.sleep_schedule else None if self.sleep_schedule: self.sleep_schedule.work() self._setup_api() self._load_recent_forts() init_inventory(self) self.display_player_info() self._print_character_info() if self.config.pokemon_bag_show_at_start and self.config.pokemon_bag_pokemon_info: self._print_list_pokemon() random.seed() def _setup_event_system(self): handlers = [] if self.config.logging and 'color' in self.config.logging and self.config.logging['color']: handlers.append(ColoredLoggingHandler(self)) else: handlers.append(LoggingHandler(self)) if self.config.enable_social: handlers.append(SocialHandler(self)) if self.config.websocket_server_url: if self.config.websocket_start_embedded_server: self.sio_runner = SocketIoRunner(self.config.websocket_server_url) self.sio_runner.start_listening_async() websocket_handler = SocketIoHandler( self, self.config.websocket_server_url ) handlers.append(websocket_handler) if self.config.websocket_remote_control: remote_control = WebsocketRemoteControl(self).start() # @var EventManager self.event_manager = EventManager(self.config.walker_limit_output, *handlers) self._register_events() if self.config.show_events: self.event_manager.event_report() sys.exit(1) # Registering event: # self.event_manager.register_event("location", parameters=['lat', 'lng']) # # Emitting event should be enough to add logging and send websocket # message: : # self.event_manager.emit('location', 'level'='info', data={'lat': 1, 'lng':1}), def _register_events(self): self.event_manager.register_event( 'location_found', parameters=('position', 'location') ) self.event_manager.register_event('api_error') self.event_manager.register_event('config_error') self.event_manager.register_event('login_started') self.event_manager.register_event('login_failed') self.event_manager.register_event('login_successful') self.event_manager.register_event('set_start_location') self.event_manager.register_event('load_cached_location') self.event_manager.register_event('location_cache_ignored') self.event_manager.register_event('debug') # ignore candy above threshold self.event_manager.register_event( 'ignore_candy_above_thresold', parameters=( 'name', 'amount', 'threshold' ) ) self.event_manager.register_event( 'position_update', parameters=( 'current_position', 'last_position', 'distance', # optional 'distance_unit' # optional ) ) self.event_manager.register_event( 'path_lap_update', parameters=( 'number_lap', 'number_lap_max' ) ) self.event_manager.register_event( 'path_lap_end', parameters=( 'duration', 'resume' ) ) self.event_manager.register_event('location_cache_error') self.event_manager.register_event('bot_start') self.event_manager.register_event('bot_exit') self.event_manager.register_event('bot_interrupted') # sleep stuff self.event_manager.register_event( 'next_sleep', parameters=( 'time', 'duration' ) ) self.event_manager.register_event( 'bot_sleep', parameters=( 'time_hms', 'wake' ) ) # random pause self.event_manager.register_event( 'next_random_pause', parameters=( 'time', 'duration' ) ) self.event_manager.register_event( 'bot_random_pause', parameters=( 'time_hms', 'resume' ) ) # recycle stuff self.event_manager.register_event( 'next_force_recycle', parameters=( 'time' ) ) self.event_manager.register_event('force_recycle') # random alive pause self.event_manager.register_event( 'next_random_alive_pause', parameters=( 'time', 'duration' ) ) self.event_manager.register_event( 'bot_random_alive_pause', parameters=( 'time_hms', 'resume' ) ) # fort stuff self.event_manager.register_event( 'spun_fort', parameters=( 'fort_id', 'latitude', 'longitude' ) ) self.event_manager.register_event( 'lured_pokemon_found', parameters=( 'fort_id', 'fort_name', 'encounter_id', 'latitude', 'longitude' ) ) self.event_manager.register_event( 'moving_to_fort', parameters=( 'fort_name', 'distance' ) ) self.event_manager.register_event( 'moving_to_lured_fort', parameters=( 'fort_name', 'distance', 'lure_distance' ) ) self.event_manager.register_event( 'spun_pokestop', parameters=( 'pokestop', 'exp', 'items' ) ) self.event_manager.register_event( 'pokestop_empty', parameters=('pokestop',) ) self.event_manager.register_event( 'pokestop_out_of_range', parameters=('pokestop',) ) self.event_manager.register_event( 'pokestop_on_cooldown', parameters=('pokestop', 'minutes_left') ) self.event_manager.register_event( 'unknown_spin_result', parameters=('status_code',) ) self.event_manager.register_event('pokestop_searching_too_often') self.event_manager.register_event('arrived_at_fort') # pokemon stuff self.event_manager.register_event( 'catchable_pokemon', parameters=( 'pokemon_id', 'spawn_point_id', 'encounter_id', 'latitude', 'longitude', 'expiration_timestamp_ms', 'pokemon_name' ) ) self.event_manager.register_event( 'pokemon_appeared', parameters=( 'pokemon', 'ncp', 'cp', 'iv', 'iv_display', 'encounter_id', 'latitude', 'longitude', 'pokemon_id' ) ) self.event_manager.register_event('no_pokeballs') self.event_manager.register_event('enough_ultraballs') self.event_manager.register_event( 'pokemon_catch_rate', parameters=( 'catch_rate', 'ball_name', 'berry_name', 'berry_count' ) ) self.event_manager.register_event( 'threw_berry', parameters=( 'berry_name', 'ball_name', 'new_catch_rate' ) ) self.event_manager.register_event( 'threw_pokeball', parameters=( 'throw_type', 'spin_label', 'ball_name', 'success_percentage', 'count_left' ) ) self.event_manager.register_event( 'pokemon_capture_failed', parameters=('pokemon',) ) self.event_manager.register_event( 'pokemon_vanished', parameters=( 'pokemon', 'encounter_id', 'latitude', 'longitude', 'pokemon_id' ) ) self.event_manager.register_event('pokemon_not_in_range') self.event_manager.register_event('pokemon_inventory_full') self.event_manager.register_event( 'pokemon_caught', parameters=( 'pokemon', 'ncp', 'cp', 'iv', 'iv_display', 'exp', 'encounter_id', 'latitude', 'longitude', 'pokemon_id', 'daily_catch_limit', 'caught_last_24_hour', ) ) self.event_manager.register_event( 'pokemon_evolved', parameters=('pokemon', 'iv', 'cp', 'xp', 'candy') ) self.event_manager.register_event( 'pokemon_upgraded', parameters=('pokemon', 'iv', 'cp', 'candy', 'stardust') ) self.event_manager.register_event('skip_evolve') self.event_manager.register_event('threw_berry_failed', parameters=('status_code',)) self.event_manager.register_event('vip_pokemon') self.event_manager.register_event('gained_candy', parameters=('quantity', 'type')) self.event_manager.register_event('catch_limit') self.event_manager.register_event('show_best_pokemon', parameters=('pokemons')) # level up stuff self.event_manager.register_event( 'level_up', parameters=( 'previous_level', 'current_level' ) ) self.event_manager.register_event( 'level_up_reward', parameters=('items',) ) # lucky egg self.event_manager.register_event( 'used_lucky_egg', parameters=('amount_left',) ) self.event_manager.register_event('lucky_egg_error') # softban self.event_manager.register_event('softban') self.event_manager.register_event('softban_fix') self.event_manager.register_event('softban_fix_done') # egg incubating self.event_manager.register_event( 'incubate_try', parameters=( 'incubator_id', 'egg_id' ) ) self.event_manager.register_event( 'incubate', parameters=('distance_in_km',) ) self.event_manager.register_event( 'next_egg_incubates', parameters=('eggs_left', 'eggs_inc', 'eggs') ) self.event_manager.register_event('incubator_already_used') self.event_manager.register_event('egg_already_incubating') self.event_manager.register_event( 'egg_hatched', parameters=( 'pokemon', 'cp', 'iv', 'exp', 'stardust', 'candy' ) ) # discard item self.event_manager.register_event( 'item_discarded', parameters=( 'amount', 'item', 'maximum' ) ) self.event_manager.register_event( 'item_discard_skipped', parameters=('space',) ) self.event_manager.register_event( 'item_discard_fail', parameters=('item',) ) # inventory self.event_manager.register_event('inventory_full') # release self.event_manager.register_event( 'keep_best_release', parameters=( 'amount', 'pokemon', 'criteria' ) ) self.event_manager.register_event( 'future_pokemon_release', parameters=( 'pokemon', 'cp', 'iv', 'below_iv', 'below_cp', 'cp_iv_logic' ) ) self.event_manager.register_event( 'pokemon_release', parameters=('pokemon', 'iv', 'cp', 'candy') ) # polyline walker self.event_manager.register_event( 'polyline_request', parameters=('url',) ) # cluster self.event_manager.register_event( 'found_cluster', parameters=( 'num_points', 'forts', 'radius', 'distance' ) ) self.event_manager.register_event( 'arrived_at_cluster', parameters=( 'num_points', 'forts', 'radius' ) ) # rename self.event_manager.register_event( 'rename_pokemon', parameters=('old_name', 'current_name',) ) self.event_manager.register_event( 'pokemon_nickname_invalid', parameters=('nickname',) ) self.event_manager.register_event( 'unset_pokemon_nickname', parameters=('old_name',) ) # Move To map pokemon self.event_manager.register_event( 'move_to_map_pokemon_fail', parameters=('message',) ) self.event_manager.register_event( 'move_to_map_pokemon_updated_map', parameters=('lat', 'lon') ) self.event_manager.register_event( 'move_to_map_pokemon_teleport_to', parameters=('poke_name', 'poke_dist', 'poke_lat', 'poke_lon', 'disappears_in') ) self.event_manager.register_event( 'move_to_map_pokemon_encounter', parameters=('poke_name', 'poke_dist', 'poke_lat', 'poke_lon', 'disappears_in') ) self.event_manager.register_event( 'move_to_map_pokemon_move_towards', parameters=('poke_name', 'poke_dist', 'poke_lat', 'poke_lon', 'disappears_in') ) self.event_manager.register_event( 'move_to_map_pokemon_teleport_back', parameters=('last_lat', 'last_lon') ) self.event_manager.register_event( 'moving_to_pokemon_throught_fort', parameters=('fort_name', 'distance','poke_name','poke_dist') ) self.event_manager.register_event( 'move_to_map_pokemon', parameters=('message') ) # cached recent_forts self.event_manager.register_event('loaded_cached_forts') self.event_manager.register_event('cached_fort') self.event_manager.register_event( 'no_cached_forts', parameters=('path', ) ) self.event_manager.register_event( 'error_caching_forts', parameters=('path', ) ) # database shit self.event_manager.register_event('catch_log') self.event_manager.register_event('evolve_log') self.event_manager.register_event('login_log') self.event_manager.register_event('transfer_log') self.event_manager.register_event('pokestop_log') self.event_manager.register_event('softban_log') self.event_manager.register_event( 'badges', parameters=('badge', 'level') ) self.event_manager.register_event( 'player_data', parameters=('player_data', ) ) def tick(self): self.health_record.heartbeat() self.cell = self.get_meta_cell() if self.sleep_schedule: self.sleep_schedule.work() now = time.time() * 1000 for fort in self.cell["forts"]: timeout = fort.get("cooldown_complete_timestamp_ms", 0) if timeout >= now: self.fort_timeouts[fort["id"]] = timeout self.tick_count += 1 # Check if session token has expired self.check_session(self.position) for worker in self.workers: if worker.work() == WorkerResult.RUNNING: return def get_meta_cell(self): location = self.position[0:2] cells = self.find_close_cells(*location) # Combine all cells into a single dict of the items we care about. forts = [] wild_pokemons = [] catchable_pokemons = [] for cell in cells: if "forts" in cell and len(cell["forts"]): forts += cell["forts"] if "wild_pokemons" in cell and len(cell["wild_pokemons"]): wild_pokemons += cell["wild_pokemons"] if "catchable_pokemons" in cell and len(cell["catchable_pokemons"]): catchable_pokemons += cell["catchable_pokemons"] # If there are forts present in the cells sent from the server or we don't yet have any cell data, return all data retrieved if len(forts) > 1 or not self.cell: return { "forts": forts, "wild_pokemons": wild_pokemons, "catchable_pokemons": catchable_pokemons } # If there are no forts present in the data from the server, keep our existing fort data and only update the pokemon cells. else: return { "forts": self.cell["forts"], "wild_pokemons": wild_pokemons, "catchable_pokemons": catchable_pokemons } def update_web_location(self, cells=[], lat=None, lng=None, alt=None): # we can call the function with no arguments and still get the position # and map_cells if lat is None: lat = self.api._position_lat if lng is None: lng = self.api._position_lng if alt is None: alt = self.api._position_alt # dont cache when teleport_to if self.api.teleporting: return if cells == []: location = self.position[0:2] cells = self.find_close_cells(*location) user_data_cells = os.path.join(_base_dir, 'data', 'cells-%s.json' % self.config.username) try: with open(user_data_cells, 'w') as outfile: json.dump(cells, outfile) except IOError as e: self.logger.info('[x] Error while opening location file: %s' % e) user_web_location = os.path.join( _base_dir, 'web', 'location-%s.json' % self.config.username ) # alt is unused atm but makes using *location easier try: with open(user_web_location, 'w') as outfile: json.dump({ 'lat': lat, 'lng': lng, 'alt': alt, 'cells': cells }, outfile) except IOError as e: self.logger.info('[x] Error while opening location file: %s' % e) user_data_lastlocation = os.path.join( _base_dir, 'data', 'last-location-%s.json' % self.config.username ) try: with open(user_data_lastlocation, 'w') as outfile: json.dump({'lat': lat, 'lng': lng, 'alt': alt, 'start_position': self.start_position}, outfile) except IOError as e: self.logger.info('[x] Error while opening location file: %s' % e) def find_close_cells(self, lat, lng): cellid = get_cell_ids(lat, lng) timestamp = [0, ] * len(cellid) response_dict = self.get_map_objects(lat, lng, timestamp, cellid) map_objects = response_dict.get( 'responses', {} ).get('GET_MAP_OBJECTS', {}) status = map_objects.get('status', None) map_cells = [] if status and status == 1: map_cells = map_objects['map_cells'] position = (lat, lng, 0) map_cells.sort( key=lambda x: distance( lat, lng, x['forts'][0]['latitude'], x['forts'][0]['longitude']) if x.get('forts', []) else 1e6 ) return map_cells def _setup_logging(self): log_level = logging.ERROR if self.config.debug: log_level = logging.DEBUG logging.getLogger("requests").setLevel(log_level) logging.getLogger("websocket").setLevel(log_level) logging.getLogger("socketio").setLevel(log_level) logging.getLogger("engineio").setLevel(log_level) logging.getLogger("socketIO-client").setLevel(log_level) logging.getLogger("pgoapi").setLevel(log_level) logging.getLogger("rpc_api").setLevel(log_level) if self.config.logging: logging_format = '%(message)s' logging_format_options = '' if ('show_log_level' not in self.config.logging) or self.config.logging['show_log_level']: logging_format = '[%(levelname)s] ' + logging_format if ('show_process_name' not in self.config.logging) or self.config.logging['show_process_name']: logging_format = '[%(name)10s] ' + logging_format if ('show_datetime' not in self.config.logging) or self.config.logging['show_datetime']: logging_format = '[%(asctime)s] ' + logging_format logging_format_options = '%Y-%m-%d %H:%M:%S' formatter = Formatter(logging_format,logging_format_options) for handler in logging.root.handlers[:]: handler.setFormatter(formatter) def check_session(self, position): # Check session expiry if self.api._auth_provider and self.api._auth_provider._ticket_expire: # prevent crash if return not numeric value if not self.is_numeric(self.api._auth_provider._ticket_expire): self.logger.info("Ticket expired value is not numeric", 'yellow') return remaining_time = \ self.api._auth_provider._ticket_expire / 1000 - time.time() if remaining_time < 60: self.event_manager.emit( 'api_error', sender=self, level='info', formatted='Session stale, re-logging in.' ) self.api = ApiWrapper(config=self.config) self.api.set_position(*position) self.login() self.api.activate_signature(self.get_encryption_lib()) @staticmethod def is_numeric(s): try: float(s) return True except ValueError: return False def login(self): self.event_manager.emit( 'login_started', sender=self, level='info', formatted="Login procedure started." ) lat, lng = self.position[0:2] self.api.set_position(lat, lng, self.alt) # or should the alt kept to zero? while not self.api.login( self.config.auth_service, str(self.config.username), str(self.config.password)): self.event_manager.emit( 'login_failed', sender=self, level='info', formatted="Login error, server busy. Waiting 10 seconds to try again." ) time.sleep(10) with self.database as conn: c = conn.cursor() c.execute("SELECT COUNT(name) FROM sqlite_master WHERE type='table' AND name='login'") result = c.fetchone() while True: if result[0] == 1: conn.execute('''INSERT INTO login (timestamp, message) VALUES (?, ?)''', (time.time(), 'LOGIN_SUCCESS')) break else: self.event_manager.emit( 'login_failed', sender=self, level='info', formatted="Login table not founded, skipping log" ) break self.event_manager.emit( 'login_successful', sender=self, level='info', formatted="Login successful." ) def get_encryption_lib(self): if _platform == "Windows" or _platform == "win32": # Check if we are on 32 or 64 bit if sys.maxsize > 2**32: file_name = 'encrypt_64.dll' else: file_name = 'encrypt.dll' else: file_name = 'encrypt.so' if self.config.encrypt_location == '': path = os.path.abspath(os.path.join(os.path.dirname(__file__), os.pardir)) else: path = self.config.encrypt_location full_path = path + '/'+ file_name if not os.path.isfile(full_path): self.logger.error(file_name + ' is not found! Please place it in the bots root directory or set encrypt_location in config.') self.logger.info('Platform: '+ _platform + ' ' + file_name + ' directory: '+ path) sys.exit(1) else: self.logger.info('Found '+ file_name +'! Platform: ' + _platform + ' ' + file_name + ' directory: ' + path) return full_path def _setup_api(self): # instantiate pgoapi @var ApiWrapper self.api = ApiWrapper(config=self.config) # provide player position on the earth self._set_starting_position() self.login() # chain subrequests (methods) into one RPC call self.api.activate_signature(self.get_encryption_lib()) self.logger.info('') # send empty map_cells and then our position self.update_web_location() def _print_character_info(self): # get player profile call # ---------------------- response_dict = self.api.get_player() # print('Response dictionary: \n\r{}'.format(json.dumps(response_dict, indent=2))) currency_1 = "0" currency_2 = "0" if response_dict: self._player = response_dict['responses']['GET_PLAYER']['player_data'] player = self._player else: self.logger.info( "The API didn't return player info, servers are unstable - " "retrying.", 'red' ) sleep(5) self._print_character_info() # @@@ TODO: Convert this to d/m/Y H:M:S creation_date = datetime.datetime.fromtimestamp( player['creation_timestamp_ms'] / 1e3) creation_date = creation_date.strftime("%Y/%m/%d %H:%M:%S") pokecoins = '0' stardust = '0' items_inventory = inventory.items() if 'amount' in player['currencies'][0]: pokecoins = player['currencies'][0]['amount'] if 'amount' in player['currencies'][1]: stardust = player['currencies'][1]['amount'] self.logger.info('') self.logger.info('--- {username} ---'.format(**player)) self.logger.info( 'Pokemon Bag: {}/{}'.format( inventory.Pokemons.get_space_used(), inventory.get_pokemon_inventory_size() ) ) self.logger.info( 'Items: {}/{}'.format( inventory.Items.get_space_used(), inventory.get_item_inventory_size() ) ) self.logger.info( 'Stardust: {}'.format(stardust) + ' | Pokecoins: {}'.format(pokecoins) ) # Items Output self.logger.info( 'PokeBalls: ' + str(items_inventory.get(1).count) + ' | GreatBalls: ' + str(items_inventory.get(2).count) + ' | UltraBalls: ' + str(items_inventory.get(3).count) + ' | MasterBalls: ' + str(items_inventory.get(4).count)) self.logger.info( 'RazzBerries: ' + str(items_inventory.get(701).count) + ' | BlukBerries: ' + str(items_inventory.get(702).count) + ' | NanabBerries: ' + str(items_inventory.get(703).count)) self.logger.info( 'LuckyEgg: ' + str(items_inventory.get(301).count) + ' | Incubator: ' + str(items_inventory.get(902).count) + ' | TroyDisk: ' + str(items_inventory.get(501).count)) self.logger.info( 'Potion: ' + str(items_inventory.get(101).count) + ' | SuperPotion: ' + str(items_inventory.get(102).count) + ' | HyperPotion: ' + str(items_inventory.get(103).count) + ' | MaxPotion: ' + str(items_inventory.get(104).count)) self.logger.info( 'Incense: ' + str(items_inventory.get(401).count) + ' | IncenseSpicy: ' + str(items_inventory.get(402).count) + ' | IncenseCool: ' + str(items_inventory.get(403).count)) self.logger.info( 'Revive: ' + str(items_inventory.get(201).count) + ' | MaxRevive: ' + str(items_inventory.get(202).count)) self.logger.info('') def _print_list_pokemon(self): # get pokemon list bag = inventory.pokemons().all() id_list =list(set(map(lambda x: x.pokemon_id, bag))) id_list.sort() pokemon_list = [filter(lambda x: x.pokemon_id == y, bag) for y in id_list] show_count = self.config.pokemon_bag_show_count show_candies = self.config.pokemon_bag_show_candies poke_info_displayed = self.config.pokemon_bag_pokemon_info def get_poke_info(info, pokemon): poke_info = { 'cp': 'CP {}'.format(pokemon.cp), 'iv_ads': 'A/D/S {}/{}/{}'.format(pokemon.iv_attack, pokemon.iv_defense, pokemon.iv_stamina), 'iv_pct': 'IV {}'.format(pokemon.iv), 'ivcp': 'IVCP {}'.format(round(pokemon.ivcp,2)), 'ncp': 'NCP {}'.format(round(pokemon.cp_percent,2)), 'level': "Level {}".format(pokemon.level), 'hp': 'HP {}/{}'.format(pokemon.hp, pokemon.hp_max), 'moveset': 'Moves: {}'.format(pokemon.moveset), 'dps': 'DPS {}'.format(round(pokemon.moveset.dps, 2)) } if info not in poke_info: raise ConfigException("info '{}' isn't available for displaying".format(info)) return poke_info[info] self.logger.info('Pokemon:') for pokes in pokemon_list: line_p = '#{} {}'.format(pokes[0].pokemon_id, pokes[0].name) if show_count: line_p += '[{}]'.format(len(pokes)) if show_candies: line_p += '[{} candies]'.format(pokes[0].candy_quantity) line_p += ': ' poke_info = ['({})'.format(', '.join([get_poke_info(x, p) for x in poke_info_displayed])) for p in pokes] self.logger.info(line_p + ' | '.join(poke_info)) self.logger.info('') def use_lucky_egg(self): return self.api.use_item_xp_boost(item_id=301) def _set_starting_position(self): self.event_manager.emit( 'set_start_location', sender=self, level='info', formatted='Setting start location.' ) has_position = False if self.config.test: # TODO: Add unit tests return if self.config.location: location_str = self.config.location location = self.get_pos_by_name(location_str.replace(" ", "")) msg = "Location found: {location} {position}" self.event_manager.emit( 'location_found', sender=self, level='info', formatted=msg, data={ 'location': location_str, 'position': location } ) self.api.set_position(*location) self.event_manager.emit( 'position_update', sender=self, level='info', formatted="Now at {current_position}", data={ 'current_position': self.position, 'last_position': '', 'distance': '', 'distance_unit': '' } ) self.start_position = self.position has_position = True if self.config.location_cache: try: # save location flag used to pull the last known location from # the location.json self.event_manager.emit( 'load_cached_location', sender=self, level='debug', formatted='Loading cached location...' ) json_file = os.path.join(_base_dir, 'data', 'last-location-%s.json' % self.config.username) try: with open(json_file, "r") as infile: location_json = json.load(infile) except (IOError, ValueError): # Unable to read json file. # File may be corrupt. Create a new one. location_json = [] except: raise FileIOException("Unexpected error reading from {}".web_inventory) location = ( location_json['lat'], location_json['lng'], location_json['alt'], ) # If location has been set in config, only use cache if starting position has not differed if has_position and 'start_position' in location_json: last_start_position = tuple(location_json.get('start_position', [])) # Start position has to have been set on a previous run to do this check if last_start_position and last_start_position != self.start_position: msg = 'Going to a new place, ignoring cached location.' self.event_manager.emit( 'location_cache_ignored', sender=self, level='debug', formatted=msg ) return self.api.set_position(*location) self.event_manager.emit( 'position_update', sender=self, level='debug', formatted='Loaded location {current_position} from cache', data={ 'current_position': location, 'last_position': '', 'distance': '', 'distance_unit': '' } ) has_position = True except Exception: if has_position is False: sys.exit( "No cached Location. Please specify initial location." ) self.event_manager.emit( 'location_cache_error', sender=self, level='debug', formatted='Parsing cached location failed.' ) def get_pos_by_name(self, location_name): # Check if given location name, belongs to favorite_locations favorite_location_coords = self._get_pos_by_fav_location(location_name) if favorite_location_coords is not None: return favorite_location_coords # Check if the given location is already a coordinate. if ',' in location_name: possible_coordinates = re.findall( "[-]?\d{1,3}[.]\d{3,7}", location_name ) if len(possible_coordinates) >= 2: # 2 matches, this must be a coordinate. We'll bypass the Google # geocode so we keep the exact location. self.logger.info( '[x] Coordinates found in passed in location, ' 'not geocoding.' ) return float(possible_coordinates[0]), float(possible_coordinates[1]), (float(possible_coordinates[2]) if len(possible_coordinates) == 3 else self.alt) geolocator = GoogleV3(api_key=self.config.gmapkey) loc = geolocator.geocode(location_name, timeout=10) return float(loc.latitude), float(loc.longitude), float(loc.altitude) def _get_pos_by_fav_location(self, location_name): location_name = location_name.lower() coords = None for location in self.config.favorite_locations: if location.get('name').lower() == location_name: coords = re.findall( "[-]?\d{1,3}[.]\d{3,7}", location.get('coords').strip() ) if len(coords) >= 2: self.logger.info('Favorite location found: {} ({})'.format(location_name, coords)) break #TODO: This is real bad if coords is None: return coords else: return float(coords[0]), float(coords[1]), (float(coords[2]) if len(coords) == 3 else self.alt) def heartbeat(self): # Remove forts that we can now spin again. now = time.time() self.fort_timeouts = {id: timeout for id, timeout in self.fort_timeouts.iteritems() if timeout >= now * 1000} if now - self.last_heartbeat >= self.heartbeat_threshold: self.last_heartbeat = now request = self.api.create_request() request.get_player() request.check_awarded_badges() responses = request.call() if responses['responses']['GET_PLAYER']['success'] == True: # we get the player_data anyway, might as well store it self._player = responses['responses']['GET_PLAYER']['player_data'] self.event_manager.emit( 'player_data', sender=self, level='debug', formatted='player_data: {player_data}', data={'player_data': self._player} ) if responses['responses']['CHECK_AWARDED_BADGES']['success'] == True: # store awarded_badges reponse to be used in a task or part of heartbeat self._awarded_badges = responses['responses']['CHECK_AWARDED_BADGES'] if self._awarded_badges.has_key('awarded_badges'): i = 0 for badge in self._awarded_badges['awarded_badges']: badgelevel = self._awarded_badges['awarded_badge_levels'][i] badgename = BadgeType_pb2._BADGETYPE.values_by_number[badge].name i += 1 self.event_manager.emit( 'badges', sender=self, level='info', formatted='awarded badge: {badge}, lvl {level}', data={'badge': badgename, 'level': badgelevel} ) human_behaviour.action_delay(3, 10) inventory.refresh_inventory() try: self.web_update_queue.put_nowait(True) # do this outside of thread every tick except Queue.Full: pass def update_web_location_worker(self): while True: self.web_update_queue.get() self.update_web_location() def display_player_info(self): player_stats = player() if player_stats: nextlvlxp = (int(player_stats.next_level_xp) - int(player_stats.exp)) self.logger.info( 'Level: {}'.format(player_stats.level) + ' (Next Level: {} XP)'.format(nextlvlxp) + ' (Total: {} XP)' ''.format(player_stats.exp)) self.logger.info( 'Pokemon Captured: ' '{}'.format(player_stats.pokemons_captured) + ' | Pokestops Visited: ' '{}'.format(player_stats.poke_stop_visits)) def get_forts(self, order_by_distance=False): forts = [fort for fort in self.cell['forts'] if 'latitude' in fort and 'type' in fort] if order_by_distance: forts.sort(key=lambda x: distance( self.position[0], self.position[1], x['latitude'], x['longitude'] )) return forts def get_map_objects(self, lat, lng, timestamp, cellid): if time.time() - self.last_time_map_object < self.config.map_object_cache_time: return self.last_map_object self.last_map_object = self.api.get_map_objects( latitude=f2i(lat), longitude=f2i(lng), since_timestamp_ms=timestamp, cell_id=cellid ) self.last_time_map_object = time.time() return self.last_map_object def _load_recent_forts(self): if not self.config.forts_cache_recent_forts: return cached_forts_path = os.path.join(_base_dir, 'data', 'recent-forts-%s.json' % self.config.username) try: # load the cached recent forts cached_recent_forts = [] try: with open(cached_forts_path) as f: cached_recent_forts = json.load(f) except (IOError, ValueError) as e: self.logger.info('[x] Error while opening cached forts: %s' % e, 'red') pass except: raise FileIOException("Unexpected error opening {}".cached_forts_path) num_cached_recent_forts = len(cached_recent_forts) num_recent_forts = len(self.recent_forts) # Handles changes in max_circle_size if not num_recent_forts: self.recent_forts = [] elif num_recent_forts > num_cached_recent_forts: self.recent_forts[-num_cached_recent_forts:] = cached_recent_forts elif num_recent_forts < num_cached_recent_forts: self.recent_forts = cached_recent_forts[-num_recent_forts:] else: self.recent_forts = cached_recent_forts self.event_manager.emit( 'loaded_cached_forts', sender=self, level='debug', formatted='Loaded cached forts...' ) except IOError: self.event_manager.emit( 'no_cached_forts', sender=self, level='debug', formatted='Starting new cached forts for {path}', data={'path': cached_forts_path} )
class ActionMachine(object): # DIO def __init__(self, novel_helper, robot_army): self.nh = novel_helper self.novel_helper = novel_helper self.book_warehouse = self.nh.book_warehouse self.robot_army = robot_army self.user_map = dict() self.init_user_map() self.book_map = dict() self.init_book_map() self.offline_uid_set = set(list(self.user_map.keys())) self.recommend_uid_set = set() self.choosing_uid_set = set() self.click_drive_uid_set = set() self.read_drive_uid_set = set() self.reading_uid_set = set() self.has_online_set = set() self._period = 0 self.rec_sys = RecSysRandom(self) self.event_manager = EventManager(self) self.event_manager.clean_all_csv() self.metrics_client = MetricsClient(self) def get_period(self): return self._period def reset_timer(self): self.st = time.time() def timer_cost(self): return time.time() - self.st def emit_timer(self, query): time_cost = self.timer_cost() self.metrics_client.emit_timer(query, time_cost) # 统计查询,会先检查sqlite-in-memory的建表状态 def query(self, sql_text, reprepare=True): r = self.event_manager.query(sql_text, reprepare) return r def connect_rec_sys(self, rec_sys): self.rec_sys = rec_sys def init_user_map(self): for regiment in self.robot_army.regiment: for robot in regiment.robot: uid = robot.uid robot_user = RobotUser(robot) self._init_use_app_info(robot_user) self.user_map[uid] = robot_user def init_book_map(self): for book_def in self.book_warehouse.book: bid = book_def.bid self.book_map[bid] = Book(book_def) def _fill_empty_word_list(self, word_list): word_list = [ word for word in word_list if word in self.novel_helper.wv_word_idx_map ] if not word_list: word_list = ['empty', 'word', 'list'] return word_list # 驱动分值:点击 # click_drive_score, chapter_read_drive_score, open_app_drive_score, detest_drive_score def _get_robot_click_book_score(self, robot_user, book): book_def = book.book_def title_word = list(book_def.title.word) synopsis_word = list(book_def.synopsis.word) book_word_list = self._fill_no_title(title_word + synopsis_word) user_word_list = [ei.word for ei in robot_user.robot_def.ei] book_vector = self._word_list_vector_pooling(book_word_list) user_vector = self._word_list_vector_pooling(user_word_list) score_sum = np.dot(book_vector, user_vector) score = score_sum / (len(book_word_list) * len(user_word_list)) return score # 对word_list取词向量做pooling是常见操作 def _word_list_vector_pooling(self, word_list): wv_word_idx_map = self.nh.wv_word_idx_map wv_vector = self.nh.wv_model.vectors word_idx_list = [wv_word_idx_map[word.lower()] for word in word_list] word_vector_list = [wv_vector[idx] for idx in word_idx_list] sum_vector = np.sum(word_vector_list, axis=0) return sum_vector # book_word多会用到,robot_word会分成多个sub_robot_word_list与book_word_list做 # 点积,这代表每次阅读机器人用户的关注点是不同的,同时也能引入随机量 def _dot_robot_book(self, robot_word_list, book_word_list, sample_loop): robot_word_list = self._fill_empty_word_list(robot_word_list) book_word_list = self._fill_empty_word_list(book_word_list) kb = len(book_word_list) kr = len(robot_word_list) sample_word_count = (kr - 1) // sample_loop + 1 sub_dot_score_list = [] book_vector = self._word_list_vector_pooling(book_word_list) for _ in range(sample_loop): sub_robot_word_list = random.sample(robot_word_list, sample_word_count) krp = len(sub_robot_word_list) sub_robot_vector = self._word_list_vector_pooling( sub_robot_word_list) sub_dot_score = np.dot(sub_robot_vector, book_vector) sub_dot_score /= (kb * krp) sub_dot_score_list.append(sub_dot_score) dot_score = max(sub_dot_score_list) return dot_score # 机器人的点击驱动值计算 def _get_click_drive_score(self, robot_user, book, sample_loop=Args.default_sample_loop): # 传入book而非book_def是因为这样后续能让book中pb_def外的字段来参与算分 robot_def = robot_user._robot_def book_def = book._book_def robot_enlighten_info_list = robot_def.ei robot_enlighten_word_list = [ enlighten_info.word for enlighten_info in robot_enlighten_info_list ] title_word_list = S.sentence_to_string_list(book_def.title) synopsis_word_list = S.sentence_to_string_list(book_def.synopsis) title_synopsis_word_list = title_word_list + synopsis_word_list click_drive_score = self._dot_robot_book(robot_enlighten_word_list, synopsis_word_list, sample_loop=sample_loop) return click_drive_score # 机器人阅读驱动值计算 def _get_read_drive_score(self, robot_user, book, chapter, sample_loop=Args.default_sample_loop): robot_def = robot_user._robot_def book_def = book._book_def robot_enlighten_info_list = robot_def.ei robot_enlighten_word_list = [ enlighten_info.word for enlighten_info in robot_enlighten_info_list ] paragraph_all_count = len(book_def.paragraph) assert paragraph_all_count >= chapter and chapter > 0, \ "chapter must in range %s>=chapter>=1 but get %s" % (paragraph_all_count, chapter) to_read_paragraph = book_def.paragraph[chapter - 1] paragraph_word_list = S.paragraph_to_string_list(to_read_paragraph) read_drive_score = self._dot_robot_book(robot_enlighten_word_list, paragraph_word_list, sample_loop=sample_loop) return read_drive_score # 机器人标题厌恶驱动值计算 def _get_title_detest_drive_score(self, robot_user, book, sample_loop=Args.default_sample_loop): robot_def = robot_user._robot_def book_def = book._book_def robot_detest_info_list = robot_def.detest_ei robot_detest_word_list = [ enlighten_info.word for enlighten_info in robot_detest_info_list ] title_word_list = S.sentence_to_string_list(book_def.title) synopsis_word_list = S.sentence_to_string_list(book_def.synopsis) title_synopsis_word_list = title_word_list + synopsis_word_list detest_drive_score = self._dot_robot_book(robot_detest_word_list, title_synopsis_word_list, sample_loop=sample_loop) return detest_drive_score # 机器人厌恶驱动值计算 def _get_detest_drive_score(self, robot_user, book, chapter, sample_loop=Args.default_sample_loop): robot_def = robot_user._robot_def book_def = book._book_def robot_detest_info_list = robot_def.detest_ei robot_detest_word_list = [ enlighten_info.word for enlighten_info in robot_detest_info_list ] paragraph_all_count = len(book_def.paragraph) assert paragraph_all_count >= chapter and chapter > 0, \ "chapter must in range %s>=chapter>=1 but get %s" % (paragraph_all_count, chapter) to_read_paragraph = book_def.paragraph[chapter - 1] paragraph_word_list = S.paragraph_to_string_list(to_read_paragraph) detest_drive_score = self._dot_robot_book(robot_detest_word_list, paragraph_word_list, sample_loop=sample_loop) return detest_drive_score # 机器人addict驱动值计算 def _get_addict_drive_score(self, robot_user, book, chapter, sample_loop=Args.default_sample_loop): robot_def = robot_user._robot_def book_def = book._book_def robot_addict_info_list = robot_def.addict_ei robot_addict_word_list = [ enlighten_info.word for enlighten_info in robot_addict_info_list ] paragraph_all_count = len(book_def.paragraph) assert paragraph_all_count >= chapter and chapter > 0, \ "chapter must in range %s>=chapter>=1 but get %s" % (paragraph_all_count, chapter) to_read_paragraph = book.paragraph[chapter - 1] paragraph_word_list = S.paragraph_to_string_list(to_read_paragraph) addict_drive_score = self._dot_robot_book(robot_addict_word_list, paragraph_word_list, sample_loop=sample_loop) return addict_drive_score # 计算机器人驱动值时加入的噪音 def _get_normal_noise(self, noise_range=1.): return noise_range * random.gauss(0., 1.) # 维护recent_drive_score的队列并推入新值 def _push_drive_score(self, recent_drive_score_list, drive_score): recent_drive_count = 5 if len(recent_drive_score_list) >= recent_drive_count: recent_drive_score_list.pop(0) recent_drive_score_list.append(drive_score) # 在关闭app时做的收尾工作 def _just_shut_down_app(self, robot_user): robot_user._use_app_impulse_value -= 0.5 # 初始化机器人用户开关app的驱动信息 def _init_use_app_info(self, robot_user): robot_user._use_app_impulse_value = random.random( ) - 0.99 # 有20%的用户会直接开app robot_user._addict_rate = random.random() robot_user._detest_rate = random.random() # 根据_recent_***那些变量俩计算 def _update_addict_rate(self, robot_user): addict_rate_room_decay = .8 addict_rate_room = 1. - robot_user._addict_rate addict_rate_room *= addict_rate_room_decay robot_user._addict_rate = 1. - addict_rate_room # 根据_recent_***那些变量俩计算 def _update_detest_rate(self, robot_user): detest_rate_decay = .8 robot_user._detest_rate *= detest_rate_decay # 打开app的冲动值 def _update_offline_use_app_impulse_value(self, robot_user): for bid, reading_info in robot_user._history_read_map.items(): bid_addict_value = reading_info.addict_value # 尚未想好bid_addict_value怎么影响_use_app_impulse_value delta = (robot_user._addict_rate - robot_user._detest_rate) * 1. robot_user._use_app_impulse_value += delta * Args.use_app_impluse_value_update_rate def _update_use_app_impulse_value(self, robot_user): pass # 第一状态——offline def _run_robot_offline(self, robot_user): if robot_user._use_app_impulse_value > 0: self.metrics_client.emit_counter('offline2recommend', 1) robot_user._status = RobotStatus.RECOMMEND else: robot_user._status = RobotStatus.OFFLINE self._update_offline_use_app_impulse_value(robot_user) self._update_addict_rate(robot_user) self._update_detest_rate(robot_user) # 第二状态——recommend def _run_robot_recommend(self, robot_user): self.rec_sys.recommend(robot_user) robot_user._chosen_bid_set.clear() robot_user._choosing_delay = 2 robot_user._reading_bid = None robot_user._status = RobotStatus.CHOOSING for bid in robot_user._choosing_bid_list: self.event_manager.emit_one_event(uid=robot_user._uid, bid=bid, event='impression') # 第三状态——choosing def _run_robot_choosing(self, robot_user): if robot_user._choosing_delay > 0: robot_user._status = RobotStatus.CHOOSING else: robot_user._status = RobotStatus.CLICK_DRIVE robot_user._choosing_delay -= 1 # 第四状态——click_drive def _run_robot_click_drive(self, robot_user): self.reset_timer() for bid in robot_user._choosing_bid_list: if bid in robot_user._chosen_bid_set: continue book = self.book_map[bid] click_drive_score = self._get_click_drive_score(robot_user, book, sample_loop=1) title_detest_drive_score = self._get_title_detest_drive_score( robot_user, book, sample_loop=1) if bid in robot_user._history_impr_map: suppress_rate = .5 else: suppress_rate = 1. click_drive_score *= suppress_rate if title_detest_drive_score > Args.title_detest_drive_threshold: continue if click_drive_score > Args.click_drive_threshold: robot_user._reading_bid = bid robot_user._chosen_bid_set.add(bid) robot_user._history_read_map[bid] = ReadingInfo( last_period=self._period, chapter=0, addict_value=0) self.event_manager.emit_one_event(uid=robot_user._uid, bid=bid, event='go_detail') break if random.random() < 0.1: # 10%的概率会被机器人记住“给我推过了” robot_user._history_impr_map[bid] = ImpressionInfo( last_period=self._period) if robot_user._reading_bid: robot_user._status = RobotStatus.READ_DRIVE else: # todo: not only OFFLINE, but also RECOMMEND robot_user._status = RobotStatus.OFFLINE self._just_shut_down_app(robot_user) self._update_use_app_impulse_value(robot_user) self.emit_timer('click_drive_delay') # 第五状态——read_drive def _run_robot_read_drive(self, robot_user): robot_user._status = RobotStatus.OFFLINE bid = robot_user._reading_bid book = self.book_map[bid] reading_info = robot_user._history_read_map[bid] # chapter记录的是之前读完哪一章了,之后从下一章开始读 reading_info.chapter += 1 if reading_info.chapter > len(book._book_def.paragraph): # 返回第一章继续阅读 reading_info.chapter = 1 read_drive_score = self._get_read_drive_score( robot_user, book, chapter=reading_info.chapter, sample_loop=1) detest_drive_score = self._get_detest_drive_score(robot_user, book, reading_info.chapter, sample_loop=1) if read_drive_score > Args.read_drive_threshold and detest_drive_score < Args.detest_drive_threshold: robot_user._status = RobotStatus.READING robot_user._chapter_finish_delay = 3 else: robot_user._status = RobotStatus.CHOOSING self._update_use_app_impulse_value(robot_user) # 第六状态——reading def _run_robot_reading(self, robot_user): if robot_user._chapter_finish_delay > 0: robot_user._status = RobotStatus.READING robot_user._chapter_finish_delay -= 1 else: robot_user._status = RobotStatus.READ_DRIVE # 一个period内的运行函数 def run_one_period(self): self._period += 1 for uid in self.offline_uid_set: robot_user = self.user_map[uid] self._run_robot_offline(robot_user) for uid in self.recommend_uid_set: robot_user = self.user_map[uid] self._run_robot_recommend(robot_user) for uid in self.choosing_uid_set: robot_user = self.user_map[uid] self._run_robot_choosing(robot_user) for uid in self.click_drive_uid_set: robot_user = self.user_map[uid] self._run_robot_click_drive(robot_user) for uid in self.read_drive_uid_set: robot_user = self.user_map[uid] self._run_robot_read_drive(robot_user) for uid in self.reading_uid_set: robot_user = self.user_map[uid] self._run_robot_reading(robot_user) self._update_robot_status() self._report_robot_user_status() self._metrics_emit_user_status() self._metrics_post_to_server() def run(self, k=Args.period_threshold): self.metrics_client.clear_all() self._period = 0 try: while self._period + 1 <= k: self.run_one_period() except KeyboardInterrupt: pass # 每个period最后会报告action_machine中各种用户的量 def _report_robot_user_status(self): report_message_list = [] report_message_list.append('period: %s' % self._period) report_message_list.append('offline: %s' % len(self.offline_uid_set)) report_message_list.append('recommend: %s' % len(self.recommend_uid_set)) report_message_list.append('choosing: %s' % len(self.choosing_uid_set)) report_message_list.append('click_drive: %s' % len(self.click_drive_uid_set)) report_message_list.append('read_drive: %s' % len(self.read_drive_uid_set)) report_message_list.append('reading: %s' % len(self.reading_uid_set)) # report_message_list.append('has_online: %s' % len(self.has_online_set)) report_message = ','.join(report_message_list) sys.stdout.write('\r' + report_message + ' ' * 10) # logging.error(report_message) def _metrics_emit_user_status(self): metrics_client = self.metrics_client metrics_client.emit_store('offline_uid', len(self.offline_uid_set)) metrics_client.emit_store('recommend_uid', len(self.recommend_uid_set)) metrics_client.emit_store('choosing_uid', len(self.choosing_uid_set)) metrics_client.emit_store('click_drive_uid', len(self.click_drive_uid_set)) metrics_client.emit_store('read_drive_uid', len(self.read_drive_uid_set)) metrics_client.emit_store('reading_uid', len(self.reading_uid_set)) def _metrics_post_to_server(self): self.metrics_client.post_to_metrics_server(self._period) # 在每一peroid结束时进行 def _update_robot_status(self): self.offline_uid_set.clear() self.recommend_uid_set.clear() self.choosing_uid_set.clear() self.click_drive_uid_set.clear() self.read_drive_uid_set.clear() self.reading_uid_set.clear() for uid, robot_user in self.user_map.items(): status = robot_user._status # sys.stdout.write('%s'%status) if status == RobotStatus.OFFLINE: self.offline_uid_set.add(uid) elif status == RobotStatus.RECOMMEND: self.recommend_uid_set.add(uid) elif status == RobotStatus.CHOOSING: self.choosing_uid_set.add(uid) elif status == RobotStatus.CLICK_DRIVE: self.click_drive_uid_set.add(uid) elif status == RobotStatus.READ_DRIVE: self.read_drive_uid_set.add(uid) elif status == RobotStatus.READING: self.reading_uid_set.add(uid)
if __name__ == '__main__': # init display pygame.init() game_window = pygame.display.set_mode((SCR_WIDTH, SCR_HEIGHT)) pygame.display.set_caption("MotherTrucker") # init closing conditions and time calculation should_close = False dt = 1 / 60 end_time = 0 start_time = get_time() # init first scene current_scene = SingleOrMultiScene(game_window) events_manager = EventManager.get_instance() # main game loop while not should_close: events = pygame.event.get() for event in events: if event.type == pygame.QUIT or events_manager.exit_event: client.close_connection() should_close = True current_scene.draw(events) pygame.display.update() game_window.fill((120, 110, 100)) change = events_manager.get_scene_change() if change:
def register_events(): EventManager().register_handler(HandshakingEvent, on_handshake) EventManager().register_handler(RoomJoinEvent, on_room_join) EventManager().register_handler(UserMessageEvent, on_messaging) EventManager().register_handler(RoomExitEvent, on_exit)
class PokemonGoBot(object): @property def position(self): return self.api._position_lat, self.api._position_lng, 0 @position.setter def position(self, position_tuple): self.api._position_lat, self.api._position_lng, self.api._position_alt = position_tuple @property def player_data(self): """ Returns the player data as received from the API. :return: The player data. :rtype: dict """ return self._player def __init__(self, config): self.config = config self.fort_timeouts = dict() self.pokemon_list = json.load( open(os.path.join('data', 'pokemon.json')) ) self.item_list = json.load(open(os.path.join('data', 'items.json'))) self.metrics = Metrics(self) self.latest_inventory = None self.cell = None self.recent_forts = [None] * config.forts_max_circle_size self.tick_count = 0 self.softban = False self.start_position = None self.last_map_object = None self.last_time_map_object = 0 self.logger = logging.getLogger(type(self).__name__) # Make our own copy of the workers for this instance self.workers = [] def start(self): self._setup_event_system() self._setup_logging() self._setup_api() random.seed() def _setup_event_system(self): handlers = [LoggingHandler()] if self.config.websocket_server_url: if self.config.websocket_start_embedded_server: self.sio_runner = SocketIoRunner(self.config.websocket_server_url) self.sio_runner.start_listening_async() websocket_handler = SocketIoHandler( self, self.config.websocket_server_url ) handlers.append(websocket_handler) if self.config.websocket_remote_control: remote_control = WebsocketRemoteControl(self).start() self.event_manager = EventManager(*handlers) self._register_events() if self.config.show_events: self.event_manager.event_report() sys.exit(1) # Registering event: # self.event_manager.register_event("location", parameters=['lat', 'lng']) # # Emitting event should be enough to add logging and send websocket # message: : # self.event_manager.emit('location', 'level'='info', data={'lat': 1, 'lng':1}), def _register_events(self): self.event_manager.register_event( 'location_found', parameters=('position', 'location') ) self.event_manager.register_event('api_error') self.event_manager.register_event('config_error') self.event_manager.register_event('login_started') self.event_manager.register_event('login_failed') self.event_manager.register_event('login_successful') self.event_manager.register_event('set_start_location') self.event_manager.register_event('load_cached_location') self.event_manager.register_event('location_cache_ignored') self.event_manager.register_event( 'position_update', parameters=( 'current_position', 'last_position', 'distance', # optional 'distance_unit' # optional ) ) self.event_manager.register_event('location_cache_error') self.event_manager.register_event('bot_start') self.event_manager.register_event('bot_exit') # sleep stuff self.event_manager.register_event( 'next_sleep', parameters=('time',) ) self.event_manager.register_event( 'bot_sleep', parameters=('time_in_seconds',) ) # fort stuff self.event_manager.register_event( 'spun_fort', parameters=( 'fort_id', 'latitude', 'longitude' ) ) self.event_manager.register_event( 'lured_pokemon_found', parameters=( 'fort_id', 'fort_name', 'encounter_id', 'latitude', 'longitude' ) ) self.event_manager.register_event( 'moving_to_fort', parameters=( 'fort_name', 'distance' ) ) self.event_manager.register_event( 'moving_to_lured_fort', parameters=( 'fort_name', 'distance', 'lure_distance' ) ) self.event_manager.register_event( 'spun_pokestop', parameters=( 'pokestop', 'exp', 'items' ) ) self.event_manager.register_event( 'pokestop_empty', parameters=('pokestop',) ) self.event_manager.register_event( 'pokestop_out_of_range', parameters=('pokestop',) ) self.event_manager.register_event( 'pokestop_on_cooldown', parameters=('pokestop', 'minutes_left') ) self.event_manager.register_event( 'unknown_spin_result', parameters=('status_code',) ) self.event_manager.register_event('pokestop_searching_too_often') self.event_manager.register_event('arrived_at_fort') # pokemon stuff self.event_manager.register_event( 'catchable_pokemon', parameters=( 'pokemon_id', 'spawn_point_id', 'encounter_id', 'latitude', 'longitude', 'expiration_timestamp_ms' ) ) self.event_manager.register_event( 'pokemon_appeared', parameters=( 'pokemon', 'cp', 'iv', 'iv_display', ) ) self.event_manager.register_event( 'pokemon_catch_rate', parameters=( 'catch_rate', 'berry_name', 'berry_count' ) ) self.event_manager.register_event( 'threw_berry', parameters=( 'berry_name', 'new_catch_rate' ) ) self.event_manager.register_event( 'threw_pokeball', parameters=( 'pokeball', 'success_percentage', 'count_left' ) ) self.event_manager.register_event( 'pokemon_fled', parameters=('pokemon',) ) self.event_manager.register_event( 'pokemon_vanished', parameters=('pokemon',) ) self.event_manager.register_event( 'pokemon_caught', parameters=( 'pokemon', 'cp', 'iv', 'iv_display', 'exp' ) ) self.event_manager.register_event( 'pokemon_evolved', parameters=('pokemon', 'iv', 'cp') ) self.event_manager.register_event( 'pokemon_evolve_fail', parameters=('pokemon',) ) self.event_manager.register_event('skip_evolve') self.event_manager.register_event('threw_berry_failed', parameters=('status_code',)) self.event_manager.register_event('vip_pokemon') # level up stuff self.event_manager.register_event( 'level_up', parameters=( 'previous_level', 'current_level' ) ) self.event_manager.register_event( 'level_up_reward', parameters=('items',) ) # lucky egg self.event_manager.register_event( 'used_lucky_egg', parameters=('amount_left',) ) self.event_manager.register_event('lucky_egg_error') # softban self.event_manager.register_event('softban') self.event_manager.register_event('softban_fix') self.event_manager.register_event('softban_fix_done') # egg incubating self.event_manager.register_event( 'incubate_try', parameters=( 'incubator_id', 'egg_id' ) ) self.event_manager.register_event( 'incubate', parameters=('distance_in_km',) ) self.event_manager.register_event( 'next_egg_incubates', parameters=('distance_in_km',) ) self.event_manager.register_event('incubator_already_used') self.event_manager.register_event('egg_already_incubating') self.event_manager.register_event( 'egg_hatched', parameters=( 'pokemon', 'cp', 'iv', 'exp', 'stardust', 'candy' ) ) # discard item self.event_manager.register_event( 'item_discarded', parameters=( 'amount', 'item', 'maximum' ) ) self.event_manager.register_event( 'item_discard_fail', parameters=('item',) ) # inventory self.event_manager.register_event('inventory_full') # release self.event_manager.register_event( 'keep_best_release', parameters=( 'amount', 'pokemon', 'criteria' ) ) self.event_manager.register_event( 'future_pokemon_release', parameters=( 'pokemon', 'cp', 'iv', 'below_iv', 'below_cp', 'cp_iv_logic' ) ) self.event_manager.register_event( 'pokemon_release', parameters=('pokemon', 'cp', 'iv') ) # polyline walker self.event_manager.register_event( 'polyline_request', parameters=('url',) ) # cluster self.event_manager.register_event( 'found_cluster', parameters=( 'num_points', 'forts', 'radius', 'distance' ) ) self.event_manager.register_event( 'arrived_at_cluster', parameters=( 'forts', 'radius' ) ) # rename self.event_manager.register_event( 'rename_pokemon', parameters=( 'old_name', 'current_name' ) ) self.event_manager.register_event( 'pokemon_nickname_invalid', parameters=('nickname',) ) self.event_manager.register_event('unset_pokemon_nickname') # Move To map pokemon self.event_manager.register_event( 'move_to_map_pokemon_fail', parameters=('message',) ) self.event_manager.register_event( 'move_to_map_pokemon_updated_map', parameters=('lat', 'lon') ) self.event_manager.register_event( 'move_to_map_pokemon_teleport_to', parameters=('poke_name', 'poke_dist', 'poke_lat', 'poke_lon', 'disappears_in') ) self.event_manager.register_event( 'move_to_map_pokemon_encounter', parameters=('poke_name', 'poke_dist', 'poke_lat', 'poke_lon', 'disappears_in') ) self.event_manager.register_event( 'move_to_map_pokemon_move_towards', parameters=('poke_name', 'poke_dist', 'poke_lat', 'poke_lon', 'disappears_in') ) self.event_manager.register_event( 'move_to_map_pokemon_teleport_back', parameters=('last_lat', 'last_lon') ) def tick(self): self.health_record.heartbeat() self.cell = self.get_meta_cell() self.tick_count += 1 # Check if session token has expired self.check_session(self.position[0:2]) for worker in self.workers: if worker.work() == WorkerResult.RUNNING: return def open_bag(self): response = self.get_inventory() self.inventory = list() own_pokemon_list = { int(x['Number']): {'name': x['Name'], 'candies_needed': x.get('Next Evolution Requirements', {'Amount': 18446744073709551615 }).get('Amount'), 'count': 0} for x in self.pokemon_list } inventory_items = response.get('responses', {}).get('GET_INVENTORY', {}).get( 'inventory_delta', {}).get('inventory_items', {}) if inventory_items: for item in inventory_items: item_info = item.get('inventory_item_data', {}) if {"pokemon_family"}.issubset(set(item_info.keys())): pokemon_family = item['inventory_item_data']['pokemon_family'] pokemon_data = own_pokemon_list[pokemon_family['family_id']] pokemon_data['candies_number'] = pokemon_family['candy'] if {"pokemon_data"}.issubset(set(item_info.keys())): pokemon_id = item['inventory_item_data']['pokemon_data'].get('pokemon_id') if pokemon_id: pokemon = own_pokemon_list[pokemon_id] pokemon['count'] += 1 with open('pokemons_process.csv', 'wb') as csvfile: spamwriter = csv.writer( csvfile, delimiter=str(u';'), quotechar=str(u'"'), quoting=csv.QUOTE_MINIMAL ) spamwriter.writerow([ 'pokemon', 'evolution_cost', 'total_candies', 'total_evolutions', 'pokemons_available', 'evolutions_available', 'advice' ]) advice = { True:'{} evolutions are unused. Catch more. Relax restrictions for this pokemon in config.json ("release" field)', False: '{} pokemons are unused. Release more. Enhance restrictions for this pokemon in config.json ("release" field)' } total_upgrade_count = 0 for id, pokemon_info in own_pokemon_list.iteritems(): pokemon_count = pokemon_info['count'] current_candies_number = pokemon_info.get('candies_number', 0) candies_needed = pokemon_info['candies_needed'] if pokemon_count or (current_candies_number): if candies_needed == 18446744073709551615: spamwriter.writerow([ pokemon_info['name'], 'last form', current_candies_number, '-', pokemon_count, '-', advice[False].format(pokemon_count) ]) else: # if count and (candies_needed != 18446744073709551615): current_candies_number = pokemon_info.get('candies_number', 0) count_upgrade = current_candies_number/pokemon_info['candies_needed'] total_upgrade_count += min(pokemon_count, count_upgrade) candies_left = candies_needed - candies_needed*current_candies_number pokemons_left = pokemon_count - total_upgrade_count if candies_left: advice_string = advice[True].format(candies_left) else: advice_string = advice[False].format(pokemons_left) spamwriter.writerow([ pokemon_info['name'], candies_needed, current_candies_number, count_upgrade, pokemon_count, total_upgrade_count, advice_string ]) spamwriter.writerow([ 'Total evolutons can be made: {}'.format(total_upgrade_count) ]) def get_meta_cell(self): location = self.position[0:2] cells = self.find_close_cells(*location) # Combine all cells into a single dict of the items we care about. forts = [] wild_pokemons = [] catchable_pokemons = [] for cell in cells: if "forts" in cell and len(cell["forts"]): forts += cell["forts"] if "wild_pokemons" in cell and len(cell["wild_pokemons"]): wild_pokemons += cell["wild_pokemons"] if "catchable_pokemons" in cell and len(cell["catchable_pokemons"]): catchable_pokemons += cell["catchable_pokemons"] # If there are forts present in the cells sent from the server or we don't yet have any cell data, return all data retrieved if len(forts) > 1 or not self.cell: return { "forts": forts, "wild_pokemons": wild_pokemons, "catchable_pokemons": catchable_pokemons } # If there are no forts present in the data from the server, keep our existing fort data and only update the pokemon cells. else: return { "forts": self.cell["forts"], "wild_pokemons": wild_pokemons, "catchable_pokemons": catchable_pokemons } def update_web_location(self, cells=[], lat=None, lng=None, alt=None): # we can call the function with no arguments and still get the position # and map_cells if lat is None: lat = self.api._position_lat if lng is None: lng = self.api._position_lng if alt is None: alt = 0 if cells == []: location = self.position[0:2] cells = self.find_close_cells(*location) # insert detail info about gym to fort for cell in cells: if 'forts' in cell: for fort in cell['forts']: if fort.get('type') != 1: response_gym_details = self.api.get_gym_details( gym_id=fort.get('id'), player_latitude=lng, player_longitude=lat, gym_latitude=fort.get('latitude'), gym_longitude=fort.get('longitude') ) fort['gym_details'] = response_gym_details.get( 'responses', {} ).get('GET_GYM_DETAILS', None) user_data_cells = "data/cells-%s.json" % self.config.username with open(user_data_cells, 'w') as outfile: json.dump(cells, outfile) user_web_location = os.path.join( 'web', 'location-%s.json' % self.config.username ) # alt is unused atm but makes using *location easier try: with open(user_web_location, 'w') as outfile: json.dump({ 'lat': lat, 'lng': lng, 'alt': alt, 'cells': cells }, outfile) except IOError as e: self.logger.info('[x] Error while opening location file: %s' % e) user_data_lastlocation = os.path.join( 'data', 'last-location-%s.json' % self.config.username ) try: with open(user_data_lastlocation, 'w') as outfile: json.dump({'lat': lat, 'lng': lng, 'start_position': self.start_position}, outfile) except IOError as e: self.logger.info('[x] Error while opening location file: %s' % e) def find_close_cells(self, lat, lng): cellid = get_cell_ids(lat, lng) timestamp = [0, ] * len(cellid) response_dict = self.get_map_objects(lat, lng, timestamp, cellid) map_objects = response_dict.get( 'responses', {} ).get('GET_MAP_OBJECTS', {}) status = map_objects.get('status', None) map_cells = [] if status and status == 1: map_cells = map_objects['map_cells'] position = (lat, lng, 0) map_cells.sort( key=lambda x: distance( lat, lng, x['forts'][0]['latitude'], x['forts'][0]['longitude']) if x.get('forts', []) else 1e6 ) return map_cells def _setup_logging(self): # log settings # log format if self.config.debug: log_level = logging.DEBUG logging.getLogger("requests").setLevel(logging.DEBUG) logging.getLogger("websocket").setLevel(logging.DEBUG) logging.getLogger("socketio").setLevel(logging.DEBUG) logging.getLogger("engineio").setLevel(logging.DEBUG) logging.getLogger("socketIO-client").setLevel(logging.DEBUG) logging.getLogger("pgoapi").setLevel(logging.DEBUG) logging.getLogger("rpc_api").setLevel(logging.DEBUG) else: log_level = logging.ERROR logging.getLogger("requests").setLevel(logging.ERROR) logging.getLogger("websocket").setLevel(logging.ERROR) logging.getLogger("socketio").setLevel(logging.ERROR) logging.getLogger("engineio").setLevel(logging.ERROR) logging.getLogger("socketIO-client").setLevel(logging.ERROR) logging.getLogger("pgoapi").setLevel(logging.ERROR) logging.getLogger("rpc_api").setLevel(logging.ERROR) logging.basicConfig( level=log_level, format='%(asctime)s [%(name)10s] [%(levelname)s] %(message)s' ) def check_session(self, position): # Check session expiry if self.api._auth_provider and self.api._auth_provider._ticket_expire: # prevent crash if return not numeric value if not self.is_numeric(self.api._auth_provider._ticket_expire): self.logger.info("Ticket expired value is not numeric", 'yellow') return remaining_time = \ self.api._auth_provider._ticket_expire / 1000 - time.time() if remaining_time < 60: self.event_manager.emit( 'api_error', sender=self, level='info', formatted='Session stale, re-logging in.' ) position = self.position self.api = ApiWrapper() self.position = position self.login() self.api.activate_signature(self.get_encryption_lib()) @staticmethod def is_numeric(s): try: float(s) return True except ValueError: return False def login(self): self.event_manager.emit( 'login_started', sender=self, level='info', formatted="Login procedure started." ) lat, lng = self.position[0:2] self.api.set_position(lat, lng, 0) while not self.api.login( self.config.auth_service, str(self.config.username), str(self.config.password)): self.event_manager.emit( 'login_failed', sender=self, level='info', formatted="Login error, server busy. Waiting 10 seconds to try again." ) time.sleep(10) self.event_manager.emit( 'login_successful', sender=self, level='info', formatted="Login successful." ) def get_encryption_lib(self): if _platform == "linux" or _platform == "linux2" or _platform == "darwin": file_name = 'encrypt.so' elif _platform == "Windows" or _platform == "win32": # Check if we are on 32 or 64 bit if sys.maxsize > 2**32: file_name = 'encrypt_64.dll' else: file_name = 'encrypt.dll' if self.config.encrypt_location == '': path = os.path.abspath(os.path.join(os.path.dirname(__file__), os.pardir)) else: path = self.config.encrypt_location full_path = path + '/'+ file_name if not os.path.isfile(full_path): self.logger.error(file_name + ' is not found! Please place it in the bots root directory or set libencrypt_location in config.') self.logger.info('Platform: '+ _platform + ' Encrypt.so directory: '+ path) sys.exit(1) else: self.logger.info('Found '+ file_name +'! Platform: ' + _platform + ' Encrypt.so directory: ' + path) return full_path def _setup_api(self): # instantiate pgoapi self.api = ApiWrapper() # provide player position on the earth self._set_starting_position() self.login() # chain subrequests (methods) into one RPC call self._print_character_info() self.api.activate_signature(self.get_encryption_lib()) self.logger.info('') self.update_inventory() # send empty map_cells and then our position self.update_web_location() self.open_bag() def _print_character_info(self): # get player profile call # ---------------------- response_dict = self.api.get_player() # print('Response dictionary: \n\r{}'.format(json.dumps(response_dict, indent=2))) currency_1 = "0" currency_2 = "0" if response_dict: self._player = response_dict['responses']['GET_PLAYER']['player_data'] player = self._player else: self.logger.info( "The API didn't return player info, servers are unstable - " "retrying.", 'red' ) sleep(5) self._print_character_info() # @@@ TODO: Convert this to d/m/Y H:M:S creation_date = datetime.datetime.fromtimestamp( player['creation_timestamp_ms'] / 1e3) creation_date = creation_date.strftime("%Y/%m/%d %H:%M:%S") pokecoins = '0' stardust = '0' items_stock = self.current_inventory() if 'amount' in player['currencies'][0]: pokecoins = player['currencies'][0]['amount'] if 'amount' in player['currencies'][1]: stardust = player['currencies'][1]['amount'] self.logger.info('') self.logger.info('--- {username} ---'.format(**player)) self.get_player_info() self.logger.info( 'Pokemon Bag: {}/{}'.format( self.get_inventory_count('pokemon'), player['max_pokemon_storage'] ) ) self.logger.info( 'Items: {}/{}'.format( self.get_inventory_count('item'), player['max_item_storage'] ) ) self.logger.info( 'Stardust: {}'.format(stardust) + ' | Pokecoins: {}'.format(pokecoins) ) # Items Output self.logger.info( 'PokeBalls: ' + str(items_stock[1]) + ' | GreatBalls: ' + str(items_stock[2]) + ' | UltraBalls: ' + str(items_stock[3])) self.logger.info( 'RazzBerries: ' + str(items_stock[701]) + ' | BlukBerries: ' + str(items_stock[702]) + ' | NanabBerries: ' + str(items_stock[703])) self.logger.info( 'LuckyEgg: ' + str(items_stock[301]) + ' | Incubator: ' + str(items_stock[902]) + ' | TroyDisk: ' + str(items_stock[501])) self.logger.info( 'Potion: ' + str(items_stock[101]) + ' | SuperPotion: ' + str(items_stock[102]) + ' | HyperPotion: ' + str(items_stock[103]) + ' | MaxPotion: ' + str(items_stock[104])) self.logger.info( 'Incense: ' + str(items_stock[401]) + ' | IncenseSpicy: ' + str(items_stock[402]) + ' | IncenseCool: ' + str(items_stock[403])) self.logger.info( 'Revive: ' + str(items_stock[201]) + ' | MaxRevive: ' + str(items_stock[202])) self.logger.info('') def use_lucky_egg(self): return self.api.use_item_xp_boost(item_id=301) def get_inventory(self): if self.latest_inventory is None: self.latest_inventory = self.api.get_inventory() return self.latest_inventory def update_inventory(self): response = self.get_inventory() self.inventory = list() inventory_items = response.get('responses', {}).get('GET_INVENTORY', {}).get( 'inventory_delta', {}).get('inventory_items', {}) if inventory_items: for item in inventory_items: item_info = item.get('inventory_item_data', {}).get('item', {}) if {"item_id", "count"}.issubset(set(item_info.keys())): self.inventory.append(item['inventory_item_data']['item']) def current_inventory(self): inventory_req = self.get_inventory() inventory_dict = inventory_req['responses']['GET_INVENTORY'][ 'inventory_delta']['inventory_items'] user_web_inventory = 'web/inventory-%s.json' % self.config.username with open(user_web_inventory, 'w') as outfile: json.dump(inventory_dict, outfile) # get player items stock # ---------------------- items_stock = {x.value: 0 for x in list(Item)} for item in inventory_dict: item_dict = item.get('inventory_item_data', {}).get('item', {}) item_count = item_dict.get('count') item_id = item_dict.get('item_id') if item_count and item_id: if item_id in items_stock: items_stock[item_id] = item_count return items_stock def item_inventory_count(self, id): inventory_req = self.get_inventory() inventory_dict = inventory_req['responses'][ 'GET_INVENTORY']['inventory_delta']['inventory_items'] if id == 'all': return self._all_items_inventory_count(inventory_dict) else: return self._item_inventory_count_per_id(id, inventory_dict) def _item_inventory_count_per_id(self, id, inventory_dict): item_count = 0 for item in inventory_dict: item_dict = item.get('inventory_item_data', {}).get('item', {}) item_id = item_dict.get('item_id', False) item_count = item_dict.get('count', False) if item_id == int(id) and item_count: return item_count return 0 def _all_items_inventory_count(self, inventory_dict): item_count_dict = {} for item in inventory_dict: item_dict = item.get('inventory_item_data', {}).get('item', {}) item_id = item_dict.get('item_id', False) item_count = item_dict.get('count', False) if item_id and item_count: item_count_dict[item_id] = item_count return item_count_dict def _set_starting_position(self): self.event_manager.emit( 'set_start_location', sender=self, level='info', formatted='Setting start location.' ) has_position = False if self.config.test: # TODO: Add unit tests return if self.config.location: location_str = self.config.location location = self.get_pos_by_name(location_str.replace(" ", "")) msg = "Location found: {location} {position}" self.event_manager.emit( 'location_found', sender=self, level='info', formatted=msg, data={ 'location': location_str, 'position': location } ) self.api.set_position(*location) self.event_manager.emit( 'position_update', sender=self, level='info', formatted="Now at {current_position}", data={ 'current_position': self.position, 'last_position': '', 'distance': '', 'distance_unit': '' } ) self.start_position = self.position has_position = True if self.config.location_cache: try: # save location flag used to pull the last known location from # the location.json self.event_manager.emit( 'load_cached_location', sender=self, level='debug', formatted='Loading cached location...' ) with open('data/last-location-%s.json' % self.config.username) as f: location_json = json.load(f) location = ( location_json['lat'], location_json['lng'], 0.0 ) # If location has been set in config, only use cache if starting position has not differed if has_position and 'start_position' in location_json: last_start_position = tuple(location_json.get('start_position', [])) # Start position has to have been set on a previous run to do this check if last_start_position and last_start_position != self.start_position: msg = 'Going to a new place, ignoring cached location.' self.event_manager.emit( 'location_cache_ignored', sender=self, level='debug', formatted=msg ) return self.api.set_position(*location) self.event_manager.emit( 'position_update', sender=self, level='debug', formatted='Loaded location {current_position} from cache', data={ 'current_position': location, 'last_position': '', 'distance': '', 'distance_unit': '' } ) has_position = True except Exception: if has_position is False: sys.exit( "No cached Location. Please specify initial location." ) self.event_manager.emit( 'location_cache_error', sender=self, level='debug', formatted='Parsing cached location failed.' ) def get_pos_by_name(self, location_name): # Check if the given location is already a coordinate. if ',' in location_name: possible_coordinates = re.findall( "[-]?\d{1,3}[.]\d{3,7}", location_name ) if len(possible_coordinates) == 2: # 2 matches, this must be a coordinate. We'll bypass the Google # geocode so we keep the exact location. self.logger.info( '[x] Coordinates found in passed in location, ' 'not geocoding.' ) return float(possible_coordinates[0]), float(possible_coordinates[1]), float("0.0") geolocator = GoogleV3(api_key=self.config.gmapkey) loc = geolocator.geocode(location_name, timeout=10) return float(loc.latitude), float(loc.longitude), float(loc.altitude) def heartbeat(self): # Remove forts that we can now spin again. self.fort_timeouts = {id: timeout for id, timeout in self.fort_timeouts.iteritems() if timeout >= time.time() * 1000} request = self.api.create_request() request.get_player() request.check_awarded_badges() request.call() self.update_web_location() # updates every tick def get_inventory_count(self, what): response_dict = self.get_inventory() inventory_items = response_dict.get('responses', {}).get('GET_INVENTORY', {}).get( 'inventory_delta', {}).get('inventory_items', {}) if inventory_items: pokecount = 0 itemcount = 1 for item in inventory_items: if 'inventory_item_data' in item: if 'pokemon_data' in item['inventory_item_data']: pokecount += 1 itemcount += item['inventory_item_data'].get('item', {}).get('count', 0) if 'pokemon' in what: return pokecount if 'item' in what: return itemcount return '0' def get_player_info(self): response_dict = self.get_inventory() inventory_items = response_dict.get('responses', {}).get('GET_INVENTORY', {}).get( 'inventory_delta', {}).get('inventory_items', {}) if inventory_items: pokecount = 0 itemcount = 1 for item in inventory_items: # print('item {}'.format(item)) playerdata = item.get('inventory_item_data', {}).get('player_stats') if playerdata: nextlvlxp = (int(playerdata.get('next_level_xp', 0)) - int(playerdata.get('experience', 0))) if 'level' in playerdata and 'experience' in playerdata: self.logger.info( 'Level: {level}'.format( **playerdata) + ' (Next Level: {} XP)'.format( nextlvlxp) + ' (Total: {experience} XP)' ''.format(**playerdata)) if 'pokemons_captured' in playerdata and 'poke_stop_visits' in playerdata: self.logger.info( 'Pokemon Captured: ' '{pokemons_captured}'.format( **playerdata) + ' | Pokestops Visited: ' '{poke_stop_visits}'.format( **playerdata)) def has_space_for_loot(self): number_of_things_gained_by_stop = 5 enough_space = ( self.get_inventory_count('item') < self._player['max_item_storage'] - number_of_things_gained_by_stop ) return enough_space def get_forts(self, order_by_distance=False): forts = [fort for fort in self.cell['forts'] if 'latitude' in fort and 'type' in fort] if order_by_distance: forts.sort(key=lambda x: distance( self.position[0], self.position[1], x['latitude'], x['longitude'] )) return forts def get_map_objects(self, lat, lng, timestamp, cellid): if time.time() - self.last_time_map_object < self.config.map_object_cache_time: return self.last_map_object self.last_map_object = self.api.get_map_objects( latitude=f2i(lat), longitude=f2i(lng), since_timestamp_ms=timestamp, cell_id=cellid ) self.last_time_map_object = time.time() return self.last_map_object
def main_setup(): random.seed(0) globals_.event_manager = EventManager(None) globals_.stats_manager = StatsManager('output')