def process_gym(self, gym): # type: (Events.GymEvent) -> None """ Process a gym event and notify alarms if it passes. """ # Update Gym details (if they exist) gym.gym_name = self.__cache.gym_name(gym.gym_id, gym.gym_name) gym.gym_description = self.__cache.gym_desc(gym.gym_id, gym.gym_description) gym.gym_image = self.__cache.gym_image(gym.gym_id, gym.gym_image) # Ignore changes to neutral if self._ignore_neutral and gym.new_team_id == 0: self._log.debug("%s gym update skipped: new team was neutral", gym.name) return # Update Team Information gym.old_team_id = self.__cache.gym_team(gym.gym_id) self.__cache.gym_team(gym.gym_id, gym.new_team_id) # Check if notifications are on if self._gyms_enabled is False: self._log.debug("Gym ignored: gym notifications are disabled.") return # Doesn't look like anything to me if gym.new_team_id == gym.old_team_id: self._log.debug("%s gym update skipped: no change detected", gym.gym_id) return # Calculate distance and direction if self.__location is not None: gym.distance = get_earth_dist([gym.lat, gym.lng], self.__location, self.__units) gym.direction = get_cardinal_dir([gym.lat, gym.lng], self.__location) # Check for Rules rules = self.__gym_rules if len(rules) == 0: # If no rules, default to all rules = { "default": Rule(self._gym_filters.keys(), self._alarms.keys()) } rule_ct, alarm_ct = 0, 0 for r_name, rule in rules.iteritems(): # For all rules passed = self._check_filters(gym, self._gym_filters, rule.filter_names) if passed: rule_ct += 1 alarm_ct += len(rule.alarm_names) self._notify_alarms(gym, rule.alarm_names, 'gym_alert') if rule_ct > 0: self._rule_log.info( 'Gym %s passed %s rule(s) and triggered %s alarm(s).', gym.name, rule_ct, alarm_ct) else: self._rule_log.info('Gym %s rejected by all rules.', gym.name)
def process_gym(self, gym): # type: (Events.GymEvent) -> None """ Process a gym event and notify alarms if it passes. """ # Update Gym details (if they exist) self.__cache.update_gym_info(gym.gym_id, gym.gym_name, gym.gym_description, gym.gym_image) # Ignore changes to neutral if self.__ignore_neutral and gym.new_team_id == 0: log.debug("%s gym update skipped: new team was neutral") return # Get the old team and update new team gym.old_team_id = self.__cache.get_gym_team(gym.gym_id) self.__cache.update_gym_team(gym.gym_id, gym.new_team_id) # Check if notifications are on if self.__gyms_enabled is False: log.debug("Gym ignored: gym notifications are disabled.") return # Update the cache with the gyms info info = self.__cache.get_gym_info(gym.gym_id) gym.gym_name = info['name'] gym.gym_description = info['description'] gym.gym_image = info['url'] # Doesn't look like anything to me if gym.new_team_id == gym.old_team_id: log.debug("%s gym update skipped: no change detected", gym.gym_id) return # Calculate distance and direction if self.__location is not None: gym.distance = get_earth_dist([gym.lat, gym.lng], self.__location) gym.direction = get_cardinal_dir([gym.lat, gym.lng], self.__location) # Check for Rules rules = self.__gym_rules if len(rules) == 0: # If no rules, default to all rules = { "default": Rule(self.__gym_filters.keys(), self.__alarms.keys()) } for r_name, rule in rules.iteritems(): # For all rules for f_name in rule.filter_names: # Check Filters in Rules f = self.__gym_filters.get(f_name) passed = f.check_event(gym) and self.check_geofences(f, gym) if not passed: continue # go to next filter gym.custom_dts = f.custom_dts if self.__quiet is False: log.info("{} gym notification" " has been triggered in rule '{}'!" "".format(gym.name, r_name)) self._trigger_gym(gym, rule.alarm_names) break # Next rule
def process_egg(self, egg): # type: (Events.EggEvent) -> None """ Process a egg event and notify alarms if it passes. """ # Update Gym details (if they exist) self.__cache.update_gym_info(egg.gym_id, egg.gym_name, egg.gym_description, egg.gym_image) # Make sure that eggs are enabled if self.__eggs_enabled is False: log.debug("Egg ignored: egg notifications are disabled.") return # Skip if previously processed if self.__cache.get_egg_expiration(egg.gym_id) is not None: log.debug("Egg {} was skipped because it was previously " "processed.".format(egg.gym_name)) return self.__cache.update_egg_expiration(egg.gym_id, egg.hatch_time) # Check the time remaining seconds_left = (egg.hatch_time - datetime.utcnow()).total_seconds() if seconds_left < self.__time_limit: log.debug("Egg {} was skipped because only {} seconds remained" "".format(egg.gym_name, seconds_left)) return # Assigned cached info info = self.__cache.get_gym_info(egg.gym_id) egg.gym_name = info['name'] egg.gym_description = info['description'] egg.gym_image = info['url'] # Calculate distance and direction if self.__location is not None: egg.distance = get_earth_dist([egg.lat, egg.lng], self.__location) egg.direction = get_cardinal_dir([egg.lat, egg.lng], self.__location) # Check for Rules rules = self.__egg_rules if len(rules) == 0: # If no rules, default to all rules = { "default": Rule(self.__egg_filters.keys(), self.__alarms.keys()) } for r_name, rule in rules.iteritems(): # For all rules for f_name in rule.filter_names: # Check Filters in Rules f = self.__egg_filters.get(f_name) passed = f.check_event(egg) and self.check_geofences(f, egg) if not passed: continue # go to next filter egg.custom_dts = f.custom_dts if self.__quiet is False: log.info("{} egg notification" " has been triggered to {}!" "".format(egg.gym_name, egg.geofence)) self._trigger_egg(egg, rule.alarm_names) break # Next rule
def process_gym(self, gym): # type: (Events.GymEvent) -> None """ Process a gym event and notify alarms if it passes. """ # Update Gym details (if they exist) gym.gym_name = self.__cache.gym_name(gym.gym_id, gym.gym_name) gym.gym_description = self.__cache.gym_desc( gym.gym_id, gym.gym_description) gym.gym_image = self.__cache.gym_image(gym.gym_id, gym.gym_image) # Ignore changes to neutral if self._ignore_neutral and gym.new_team_id == 0: self._log.debug("%s gym update skipped: new team was neutral") return # Update Team Information gym.old_team_id = self.__cache.gym_team(gym.gym_id) self.__cache.gym_team(gym.gym_id, gym.new_team_id) # Check if notifications are on if self._gyms_enabled is False: self._log.debug("Gym ignored: gym notifications are disabled.") return # Doesn't look like anything to me if gym.new_team_id == gym.old_team_id: self._log.debug( "%s gym update skipped: no change detected", gym.gym_id) return # Calculate distance and direction if self.__location is not None: gym.distance = get_earth_dist( [gym.lat, gym.lng], self.__location, self.__units) gym.direction = get_cardinal_dir( [gym.lat, gym.lng], self.__location) # Check for Rules rules = self.__gym_rules if len(rules) == 0: # If no rules, default to all rules = {"default": Rule( self._gym_filters.keys(), self._alarms.keys())} rule_ct, alarm_ct = 0, 0 for r_name, rule in rules.iteritems(): # For all rules passed = self._check_filters( gym, self._gym_filters, rule.filter_names) if passed: rule_ct += 1 alarm_ct += len(rule.alarm_names) self._notify_alarms( gym, rule.alarm_names, 'gym_alert') if rule_ct > 0: self._rule_log.info( 'Gym %s passed %s rule(s) and triggered %s alarm(s).', gym.name, rule_ct, alarm_ct) else: self._rule_log.info('Gym %s rejected by all rules.', gym.name)
def process_stop(self, stop): # type: (Events.StopEvent) -> None """ Process a stop event and notify alarms if it passes. """ # Make sure that stops are enabled if self._stops_enabled is False: self._log.debug("Stop ignored: stop notifications are disabled.") return # Check for lured if stop.expiration is None: self._log.debug("Stop ignored: stop was not lured") return # Check if previously processed and update expiration if self.__cache.stop_expiration( str(stop.stop_id) + str(stop.lure_type_id)) is not None: self._log.debug("Stop {} was skipped because it was " "previously processed.".format(stop.name)) return self.__cache.stop_expiration( str(stop.stop_id) + str(stop.lure_type_id), stop.expiration) # Check the time remaining seconds_left = (stop.expiration - datetime.utcnow()).total_seconds() if seconds_left < self.__time_limit: self._log.debug("Stop {} was skipped because only {} seconds " "remained".format(stop.name, seconds_left)) return # Calculate distance and direction if self.__location is not None: stop.distance = get_earth_dist([stop.lat, stop.lng], self.__location, self.__units) stop.direction = get_cardinal_dir([stop.lat, stop.lng], self.__location) # Check for Rules rules = self.__stop_rules if len(rules) == 0: # If no rules, default to all rules = { "default": Rule(self._stop_filters.keys(), self._alarms.keys()) } rule_ct, alarm_ct = 0, 0 for r_name, rule in rules.iteritems(): # For all rules passed = self._check_filters(stop, self._stop_filters, rule.filter_names) if passed: rule_ct += 1 alarm_ct += len(rule.alarm_names) self._notify_alarms(stop, rule.alarm_names, 'pokestop_alert') if rule_ct > 0: self._rule_log.info( 'Stop %s passed %s rule(s) and triggered %s alarm(s).', stop.name, rule_ct, alarm_ct) else: self._rule_log.info('Stop %s rejected by all rules.', stop.name)
def process_stop(self, stop): # type: (Events.StopEvent) -> None """ Process a stop event and notify alarms if it passes. """ # Make sure that stops are enabled if self.__stops_enabled is False: log.debug("Stop ignored: stop notifications are disabled.") return # Skip if previously processed if self.__cache.get_pokestop_expiration(stop.stop_id) is not None: log.debug("Stop {} was skipped because it was previously " "processed.".format(stop.name)) return self.__cache.update_pokestop_expiration(stop.stop_id, stop.expiration) # Check the time remaining seconds_left = (stop.expiration - datetime.utcnow()).total_seconds() if seconds_left < self.__time_limit: log.debug("Stop {} was skipped because only {} seconds remained" "".format(stop.name, seconds_left)) return # Calculate distance and direction if self.__location is not None: stop.distance = get_earth_dist([stop.lat, stop.lng], self.__location) stop.direction = get_cardinal_dir([stop.lat, stop.lng], self.__location) # Check the Filters passed = True for name, f in self.__stop_filters.iteritems(): passed = f.check_event(stop) and self.check_geofences(f, stop) if passed: # Stop checking stop.custom_dts = f.custom_dts break if not passed: # Stop was rejected by all filters return # Generate the DTS for the event dts = stop.generate_dts(self.__locale, self.__timezone, self.__units) if self.__loc_service: self.__loc_service.add_optional_arguments(self.__location, [stop.lat, stop.lng], dts) if self.__quiet is False: log.info("Stop {} notification has been triggered!".format( stop.name)) threads = [] # Spawn notifications in threads so they can work in background for alarm in self.__alarms: threads.append(gevent.spawn(alarm.pokestop_alert, dts)) gevent.sleep(0) # explict context yield for thread in threads: thread.join()
def process_monster(self, mon): # type: (Events.MonEvent) -> None """ Process a monster event and notify alarms if it passes. """ # Make sure that monsters are enabled if self._mons_enabled is False: self._log.debug("Monster ignored: monster notifications " "are disabled.") return # Set the name for this event so we can log rejects better mon.name = self.__locale.get_pokemon_name(mon.monster_id) # Check if previously processed and update expiration if self.__cache.monster_expiration(str(mon.enc_id) + str(mon.weight)) is not None: self._log.debug("{} monster was skipped because it was " "previously processed.".format(mon.name)) return self.__cache.monster_expiration( str(mon.enc_id) + str(mon.weight), mon.disappear_time) # Check the time remaining seconds_left = (mon.disappear_time - datetime.utcnow()).total_seconds() if seconds_left < self.__time_limit: self._log.debug("{} monster was skipped because only {} seconds " "remained".format(mon.name, seconds_left)) return # Calculate distance and direction if self.__location is not None: mon.distance = get_earth_dist([mon.lat, mon.lng], self.__location, self.__units) mon.direction = get_cardinal_dir([mon.lat, mon.lng], self.__location) # Check for Rules rules = self.__mon_rules if len(rules) == 0: # If no rules, default to all rules = { "default": Rule(self._mon_filters.keys(), self._alarms.keys()) } rule_ct, alarm_ct = 0, 0 for r_name, rule in rules.iteritems(): # For all rules passed = self._check_filters(mon, self._mon_filters, rule.filter_names) if passed: rule_ct += 1 alarm_ct += len(rule.alarm_names) self._notify_alarms(mon, rule.alarm_names, 'pokemon_alert') if rule_ct > 0: self._rule_log.info( 'Monster %s passed %s rule(s) and triggered %s alarm(s).', mon.name, rule_ct, alarm_ct) else: self._rule_log.info('Monster %s rejected by all rules.', mon.name)
def process_stop(self, stop): # type: (Events.StopEvent) -> None """ Process a stop event and notify alarms if it passes. """ # Make sure that stops are enabled if self._stops_enabled is False: self._log.debug("Stop ignored: stop notifications are disabled.") return # Check for lured if stop.expiration is None: self._log.debug("Stop ignored: stop was not lured") return # Check if previously processed and update expiration if self.__cache.stop_expiration(stop.stop_id) is not None: self._log.debug("Stop {} was skipped because it was " "previously processed.".format(stop.name)) return self.__cache.stop_expiration(stop.stop_id, stop.expiration) # Check the time remaining seconds_left = (stop.expiration - datetime.utcnow()).total_seconds() if seconds_left < self.__time_limit: self._log.debug("Stop {} was skipped because only {} seconds " "remained".format(stop.name, seconds_left)) return # Calculate distance and direction if self.__location is not None: stop.distance = get_earth_dist( [stop.lat, stop.lng], self.__location, self.__units) stop.direction = get_cardinal_dir( [stop.lat, stop.lng], self.__location) # Check for Rules rules = self.__stop_rules if len(rules) == 0: # If no rules, default to all rules = {"default": Rule( self._stop_filters.keys(), self._alarms.keys())} rule_ct, alarm_ct = 0, 0 for r_name, rule in rules.iteritems(): # For all rules passed = self._check_filters( stop, self._stop_filters, rule.filter_names) if passed: rule_ct += 1 alarm_ct += len(rule.alarm_names) self._notify_alarms( stop, rule.alarm_names, 'pokestop_alert') if rule_ct > 0: self._rule_log.info( 'Stop %s passed %s rule(s) and triggered %s alarm(s).', stop.name, rule_ct, alarm_ct) else: self._rule_log.info('Stop %s rejected by all rules.', stop.name)
def process_monster(self, mon): # type: (Events.MonEvent) -> None """ Process a monster event and notify alarms if it passes. """ # Make sure that monsters are enabled if self._mons_enabled is False: self._log.debug("Monster ignored: monster notifications " "are disabled.") return # Set the name for this event so we can log rejects better mon.name = self.__locale.get_pokemon_name(mon.monster_id) # Check if previously processed and update expiration if self.__cache.monster_expiration(mon.enc_id) is not None: self._log.debug("{} monster was skipped because it was " "previously processed.".format(mon.name)) return self.__cache.monster_expiration(mon.enc_id, mon.disappear_time) # Check the time remaining seconds_left = (mon.disappear_time - datetime.utcnow()).total_seconds() if seconds_left < self.__time_limit: self._log.debug("{} monster was skipped because only {} seconds " "remained".format(mon.name, seconds_left)) return # Calculate distance and direction if self.__location is not None: mon.distance = get_earth_dist( [mon.lat, mon.lng], self.__location, self.__units) mon.direction = get_cardinal_dir( [mon.lat, mon.lng], self.__location) # Check for Rules rules = self.__mon_rules if len(rules) == 0: # If no rules, default to all rules = { "default": Rule(self._mon_filters.keys(), self._alarms.keys())} rule_ct, alarm_ct = 0, 0 for r_name, rule in rules.iteritems(): # For all rules passed = self._check_filters( mon, self._mon_filters, rule.filter_names) if passed: rule_ct += 1 alarm_ct += len(rule.alarm_names) self._notify_alarms( mon, rule.alarm_names, 'pokemon_alert') if rule_ct > 0: self._rule_log.info( 'Monster %s passed %s rule(s) and triggered %s alarm(s).', mon.name, rule_ct, alarm_ct) else: self._rule_log.info('Monster %s rejected by all rules.', mon.name)
def process_stop(self, stop): # type: (Events.StopEvent) -> None """ Process a stop event and notify alarms if it passes. """ # Make sure that stops are enabled if self.__stops_enabled is False: log.debug("Stop ignored: stop notifications are disabled.") return # Check for lured if stop.expiration is None: log.debug("Stop ignored: stop was not lured") return # Check if previously processed and update expiration if self.__cache.stop_expiration(stop.stop_id) is not None: log.debug("Stop {} was skipped because it was previously " "processed.".format(stop.name)) return self.__cache.stop_expiration(stop.stop_id, stop.expiration) # Check the time remaining seconds_left = (stop.expiration - datetime.utcnow()).total_seconds() if seconds_left < self.__time_limit: log.debug("Stop {} was skipped because only {} seconds remained" "".format(stop.name, seconds_left)) return # Calculate distance and direction if self.__location is not None: stop.distance = get_earth_dist([stop.lat, stop.lng], self.__location, self.__units) stop.direction = get_cardinal_dir([stop.lat, stop.lng], self.__location) # Check for Rules rules = self.__stop_rules if len(rules) == 0: # If no rules, default to all rules = { "default": Rule(self.__stop_filters.keys(), self.__alarms.keys()) } for r_name, rule in rules.iteritems(): # For all rules for f_name in rule.filter_names: # Check Filters in Rules f = self.__stop_filters.get(f_name) passed = f.check_event(stop) and self.check_geofences(f, stop) if not passed: continue # go to next filter stop.custom_dts = f.custom_dts if self.__quiet is False: log.info("{} stop notification" " has been triggered in rule '{}'!" "".format(stop.name, r_name)) self._trigger_stop(stop, rule.alarm_names) break # Next rule
def process_monster(self, mon): # type: (Events.MonEvent) -> None """ Process a monster event and notify alarms if it passes. """ # Make sure that monsters are enabled if self.__mons_enabled is False: log.debug("Monster ignored: monster notifications are disabled.") return # Set the name for this event so we can log rejects better mon.name = self.__locale.get_pokemon_name(mon.monster_id) # Check if previously processed and update expiration if self.__cache.monster_expiration(mon.enc_id) is not None: log.debug("{} monster was skipped because it was previously " "processed.".format(mon.name)) return self.__cache.monster_expiration(mon.enc_id, mon.disappear_time) # Check the time remaining seconds_left = (mon.disappear_time - datetime.utcnow()).total_seconds() if seconds_left < self.__time_limit: log.debug("{} monster was skipped because only {} seconds remained" "".format(mon.name, seconds_left)) return # Calculate distance and direction if self.__location is not None: mon.distance = get_earth_dist([mon.lat, mon.lng], self.__location, self.__units) mon.direction = get_cardinal_dir([mon.lat, mon.lng], self.__location) # Check for Rules rules = self.__mon_rules if len(rules) == 0: # If no rules, default to all rules = { "default": Rule(self.__mon_filters.keys(), self.__alarms.keys()) } for r_name, rule in rules.iteritems(): # For all rules for f_name in rule.filter_names: # Check Filters in Rules f = self.__mon_filters.get(f_name) passed = f.check_event(mon) and self.check_geofences(f, mon) if not passed: continue # go to next filter mon.custom_dts = f.custom_dts if self.__quiet is False: log.info("{} monster notification" " has been triggered in rule '{}'!" "".format(mon.name, r_name)) self._trigger_mon(mon, rule.alarm_names) break # Next rule
def process_quest(self, quest): # type: (Events.QuestEvent) -> None """ Process a quest event and notify alarms if it passes. """ # Make sure that stops are enabled if self.__quest_enabled is False: log.debug("Quest ignored: quest notifications are disabled.") return # Check if previously processed and update expiration if self.__cache.quest_reward(quest.stop_id) is not None: log.debug("Quest {} was skipped because it was previously " "processed.".format(quest.stop_name)) return self.__cache.quest_reward(quest.stop_id, quest.reward) # Calculate distance and direction if self.__location is not None: quest.distance = get_earth_dist([quest.lat, quest.lng], self.__location, self.__units) quest.direction = get_cardinal_dir([quest.lat, quest.lng], self.__location) # Check for Rules rules = self.__quest_rules if len(rules) == 0: # If no rules, default to all rules = { "default": Rule(self.__quest_filters.keys(), self.__alarms.keys()) } for r_name, rule in rules.iteritems(): # For all rules for f_name in rule.filter_names: # Check Filters in Rules f = self.__quest_filters.get(f_name) passed = f.check_event(quest) and self.check_geofences( f, quest) if not passed: continue # go to next filter quest.custom_dts = f.custom_dts if self.__quiet is False: log.info("{} quest notification" " has been triggered in rule '{}'!" "".format(quest.stop_name, r_name)) self._trigger_quest(quest, rule.alarm_names) break # Next rule
def process_raid(self, raid): # type: (Events.RaidEvent) -> None """ Process a raid event and notify alarms if it passes. """ # Update Gym details (if they exist) raid.gym_name = self.__cache.gym_name(raid.gym_id, raid.gym_name) raid.gym_description = self.__cache.gym_desc(raid.gym_id, raid.gym_description) raid.gym_image = self.__cache.gym_image(raid.gym_id, raid.gym_image) # Update Team if Unknown if Unknown.is_(raid.current_team_id): raid.current_team_id = self.__cache.gym_team(raid.gym_id) # Make sure that raids are enabled if self._raids_enabled is False: self._log.debug("Raid ignored: raid notifications are disabled.") return # Skip if previously processed if self.__cache.raid_expiration(raid.gym_id) is not None: self._log.debug("Raid {} was skipped because it was " "previously processed.".format(raid.name)) return self.__cache.raid_expiration(raid.gym_id, raid.raid_end) # Check the time remaining seconds_left = (raid.raid_end - datetime.utcnow()).total_seconds() if seconds_left < self.__time_limit: self._log.debug("Raid {} was skipped because only {} seconds " "remained".format(raid.name, seconds_left)) return # Calculate distance and direction if self.__location is not None: raid.distance = get_earth_dist([raid.lat, raid.lng], self.__location, self.__units) raid.direction = get_cardinal_dir([raid.lat, raid.lng], self.__location) # Check for Rules rules = self.__raid_rules if len(rules) == 0: # If no rules, default to all rules = { "default": Rule(self._raid_filters.keys(), self._alarms.keys()) } rule_ct, alarm_ct = 0, 0 for r_name, rule in rules.iteritems(): # For all rules passed = self._check_filters(raid, self._raid_filters, rule.filter_names) if passed: rule_ct += 1 alarm_ct += len(rule.alarm_names) self._notify_alarms(raid, rule.alarm_names, 'raid_alert') if rule_ct > 0: self._rule_log.info( 'Raid %s passed %s rule(s) and triggered %s alarm(s).', raid.name, rule_ct, alarm_ct) else: self._rule_log.info('Raid %s rejected by all rules.', raid.name)
def process_weather(self, weather): # type: (Events.WeatherEvent) -> None """ Process a weather event and notify alarms if it passes. """ # Set the name for this event so we can log rejects better weather.name = self.__locale.get_weather_name(weather.s2_cell_id) # Make sure that weather changes are enabled if self._weather_enabled is False: self._log.debug("Weather ignored: weather change " "notifications are disabled.") return # Calculate distance and direction if self.__location is not None: weather.distance = get_earth_dist([weather.lat, weather.lng], self.__location, self.__units) weather.direction = get_cardinal_dir([weather.lat, weather.lng], self.__location) # Store copy of cache info cache_weather_id = self.__cache.cell_weather_id(weather.s2_cell_id) cache_day_or_night_id = self.__cache.day_or_night_id( weather.s2_cell_id) cache_severity_id = self.__cache.severity_id(weather.s2_cell_id) # Update cache info self.__cache.cell_weather_id(weather.s2_cell_id, weather.weather_id) self.__cache.day_or_night_id(weather.s2_cell_id, weather.day_or_night_id) self.__cache.severity_id(weather.s2_cell_id, weather.severity_id) # Check and see if the weather hasn't changed and ignore if weather.weather_id == cache_weather_id and \ weather.day_or_night_id == cache_day_or_night_id and \ weather.severity_id == cache_severity_id: self._log.debug( "weather of %s, alert of %s, and day or night of %s skipped: " "no change detected", weather.weather_id, weather.severity_id, weather.day_or_night_id) return # Check for Rules rules = self.__weather_rules if len(rules) == 0: # If no rules, default to all rules = { "default": Rule(self._weather_filters.keys(), self._alarms.keys()) } rule_ct, alarm_ct = 0, 0 for r_name, rule in rules.iteritems(): # For all rules passed = self._check_filters(weather, self._weather_filters, rule.filter_names) if passed: rule_ct += 1 alarm_ct += len(rule.alarm_names) self._notify_alarms(weather, rule.alarm_names, 'weather_alert') if rule_ct > 0: self._rule_log.info( 'Weather %s passed %s rule(s) and triggered %s alarm(s).', weather.name, rule_ct, alarm_ct) else: self._rule_log.info('Weather %s rejected by all rules.', weather.name)
def process_quest(self, quest): # type: (Events.QuestEvent) -> None """ Process a quest event and notify alarms if it passes. """ # Set the name for this event so we can log rejects better quest.name = quest.stop_id # Make sure that quest changes are enabled if self._quest_enabled is False: self._log.debug("Quest ignored: quest notifications are disabled.") return # Calculate distance and direction if self.__location is not None: quest.distance = get_earth_dist([quest.lat, quest.lng], self.__location, self.__units) quest.direction = get_cardinal_dir([quest.lat, quest.lng], self.__location) # Store a copy of cache info previous_modified = self.__cache.quest_expiration(quest.stop_id) # Check if previously processed if self.__cache.quest_expiration(quest.stop_id, quest.last_modified)\ == previous_modified: self._log.debug("Quest {} was skipped because it was " "previously processed.".format(quest.name)) return # Check against previous copy from cache previous_reward, previous_task, last_modified = \ self.__cache.quest_reward(quest.stop_id) if quest.reward_type_raw == previous_reward \ and quest.quest_type_raw == previous_task: self._log.debug("Quest ignored: Reward previously alerted!") return # Update cache info self.__cache.quest_reward(quest.stop_id, quest.reward_type_raw, quest.quest_type_raw) # Check for Rules rules = self.__quest_rules if len(rules) == 0: # If no rules, default to all rules = { "default": Rule(self._quest_filters.keys(), self._alarms.keys()) } rule_ct, alarm_ct = 0, 0 for r_name, rule in rules.iteritems(): # For all rules passed = self._check_filters(quest, self._quest_filters, rule.filter_names) if passed: rule_ct += 1 alarm_ct += len(rule.alarm_names) self._notify_alarms(quest, rule.alarm_names, 'quest_alert') if rule_ct > 0: self._rule_log.info( 'Quest %s passed %s rule(s) and triggered %s alarm(s).', quest.name, rule_ct, alarm_ct) else: self._rule_log.info('Quest %s rejected by all rules.', quest.name)
def process_raid(self, raid): # type: (Events.RaidEvent) -> None """ Process a raid event and notify alarms if it passes. """ # Update Gym details (if they exist) raid.gym_name = self.__cache.gym_name(raid.gym_id, raid.gym_name) raid.gym_description = self.__cache.gym_desc(raid.gym_id, raid.gym_description) raid.gym_image = self.__cache.gym_image(raid.gym_id, raid.gym_image) # Update Team if Unknown if Unknown.is_(raid.current_team_id): raid.current_team_id = self.__cache.gym_team(raid.gym_id) # Make sure that raids are enabled if self.__raids_enabled is False: log.debug("Raid ignored: raid notifications are disabled.") return # Skip if previously processed if self.__cache.raid_expiration(raid.gym_id) is not None: log.debug("Raid {} was skipped because it was previously " "processed.".format(raid.name)) return self.__cache.raid_expiration(raid.gym_id, raid.raid_end) # Check the time remaining seconds_left = (raid.raid_end - datetime.utcnow()).total_seconds() if seconds_left < self.__time_limit: log.debug("Raid {} was skipped because only {} seconds remained" "".format(raid.name, seconds_left)) return # Calculate distance and direction if self.__location is not None: raid.distance = get_earth_dist([raid.lat, raid.lng], self.__location, self.__units) raid.direction = get_cardinal_dir([raid.lat, raid.lng], self.__location) # Check for Rules rules = self.__raid_rules if len(rules) == 0: # If no rules, default to all rules = { "default": Rule(self.__raid_filters.keys(), self.__alarms.keys()) } for r_name, rule in rules.iteritems(): # For all rules for f_name in rule.filter_names: # Check Filters in Rules f = self.__raid_filters.get(f_name) passed = f.check_event(raid) and self.check_geofences(f, raid) if not passed: continue # go to next filter raid.custom_dts = f.custom_dts if self.__quiet is False: log.info("{} raid notification" " has been triggered in rule '{}'!" "".format(raid.name, r_name)) self._trigger_raid(raid, rule.alarm_names) break # Next rule
def process_raid(self, raid): # type: (Events.RaidEvent) -> None """ Process a raid event and notify alarms if it passes. """ # Update Gym details (if they exist) self.__cache.update_gym_info( raid.gym_id, raid.gym_name, raid.gym_description, raid.gym_image) # Make sure that raids are enabled if self.__raids_enabled is False: log.debug("Raid ignored: raid notifications are disabled.") return # Skip if previously processed if self.__cache.get_raid_expiration(raid.gym_id) is not None: log.debug("Raid {} was skipped because it was previously " "processed.".format(raid.name)) return self.__cache.update_raid_expiration(raid.gym_id, raid.raid_end) # Check the time remaining seconds_left = (raid.raid_end - datetime.utcnow()).total_seconds() if seconds_left < self.__time_limit: log.debug("Raid {} was skipped because only {} seconds remained" "".format(raid.name, seconds_left)) return # Assigned cached info info = self.__cache.get_gym_info(raid.gym_id) raid.current_team_id = self.__cache.get_gym_team(raid.gym_id) raid.gym_name = info['name'] raid.gym_description = info['description'] raid.gym_image = info['url'] # Calculate distance and direction if self.__location is not None: raid.distance = get_earth_dist( [raid.lat, raid.lng], self.__location) raid.direction = get_cardinal_dir( [raid.lat, raid.lng], self.__location) # Check the Filters passed = True for name, f in self.__raid_filters.iteritems(): passed = f.check_event(raid) and self.check_geofences(f, raid) if passed: # Stop checking raid.custom_dts = f.custom_dts break if not passed: # Raid was rejected by all filters return # Generate the DTS for the event dts = raid.generate_dts(self.__locale) dts.update(self.__cache.get_gym_info(raid.gym_id)) # update gym info if self.__loc_service: self.__loc_service.add_optional_arguments( self.__location, [raid.lat, raid.lng], dts) if self.__quiet is False: log.info( "{} raid notification has been triggered!".format(raid.name)) threads = [] # Spawn notifications in threads so they can work in background for alarm in self.__alarms: threads.append(gevent.spawn(alarm.raid_alert, dts)) gevent.sleep(0) # explict context yield for thread in threads: thread.join()
def process_egg(self, egg): # Quick check for enabled if self.__egg_settings['enabled'] is False: log.debug("Egg ignored: notifications are disabled.") return gym_id = egg['id'] raid_end = egg['raid_end'] # raid history will contains any raid processed if gym_id in self.__raid_hist: old_raid_end = self.__raid_hist[gym_id]['raid_end'] if old_raid_end == raid_end: if self.__quiet is False: log.info( "Raid {} ignored. Was previously processed.".format( gym_id)) return self.__raid_hist[gym_id] = dict(raid_end=raid_end, pkmn_id=0) # don't alert about (nearly) hatched eggs seconds_left = (egg['raid_begin'] - datetime.utcnow()).total_seconds() if seconds_left < self.__time_limit: if self.__quiet is False: log.info("Egg {} ignored. Egg hatch in {} seconds".format( gym_id, seconds_left)) return lat, lng = egg['lat'], egg['lng'] dist = get_earth_dist([lat, lng], self.__location) # Check if raid is in geofences egg['geofence'] = self.check_geofences('Raid', lat, lng) if len(self.__geofences) > 0 and egg['geofence'] == 'unknown': if self.__quiet is False: log.info("Egg {} ignored: located outside geofences.".format( gym_id)) return else: log.debug( "Egg inside geofence was not checked because no geofences were set." ) # check if the level is in the filter range or if we are ignoring eggs passed = self.check_egg_filter(self.__egg_settings, egg) if not passed: log.debug("Egg {} did not pass filter check".format(gym_id)) return if self.__loc_service: self.__loc_service.add_optional_arguments(self.__location, [lat, lng], egg) if self.__quiet is False: log.info( "Egg ({}) notification has been triggered!".format(gym_id)) time_str = get_time_as_str(egg['raid_end'], self.__timezone) start_time_str = get_time_as_str(egg['raid_begin'], self.__timezone) gym_info = self.__gym_info.get(gym_id, {}) egg.update({ #"gym_name": self.__gym_info.get(gym_id, {}).get('name', 'unknown'), #"gym_description": self.__gym_info.get(gym_id, {}).get('description', 'unknown'), #"gym_url": self.__gym_info.get(gym_id, {}).get('url', 'https://raw.githubusercontent.com/kvangent/PokeAlarm/master/icons/gym_0.png'), 'time_left': time_str[0], '12h_time': time_str[1], '24h_time': time_str[2], 'begin_time_left': start_time_str[0], 'begin_12h_time': start_time_str[1], 'begin_24h_time': start_time_str[2], "dist": get_dist_as_str(dist), 'dir': get_cardinal_dir([lat, lng], self.__location), #'team': self.__team_name[egg['team_id']] }) threads = [] # Spawn notifications in threads so they can work in background for alarm in self.__alarms: threads.append(gevent.spawn(alarm.raid_egg_alert, egg)) gevent.sleep(0) # explict context yield for thread in threads: thread.join()
def handle_pokemon(self, pkmn): # Quick check for enabled if self.__pokemon_filter['enabled'] is False: log.debug("Pokemon ignored: notifications are disabled.") return id_ = pkmn['id'] pkmn_id = pkmn['pkmn_id'] name = self.__pokemon_name[pkmn_id] # Check for previously processed if id_ in self.__pokemon_hist: if config['QUIET'] is False: log.debug( "{} was skipped because it was previously processed.". format(name)) return self.__pokemon_hist[id_] = pkmn['disappear_time'] # Check that the filter is set if pkmn_id not in self.__pokemon_filter: if config['QUIET'] is False: log.info("{} ignored: filter was not set".format(name)) return # Check the time remaining seconds_left = (pkmn['disappear_time'] - datetime.utcnow()).total_seconds() if seconds_left < self.__time_limit: if config['QUIET'] is False: log.info("{} ignored: {} seconds remaining.".format( name, seconds_left)) return filt = self.__pokemon_filter[pkmn_id] # Check the distance from the set location lat, lng = pkmn['lat'], pkmn['lng'] dist = get_earth_dist([lat, lng], self.__latlng) if dist != 'unkn': if dist < filt['min_dist'] or filt['max_dist'] < dist: if config['QUIET'] is False: log.info( "{} ignored: distance ({:.2f}) was not in range {:.2f} to {:.2f}." .format(name, dist, filt['min_dist'], filt['max_dist'])) return else: log.debug( "Pokemon dist was not checked because no location was set.") # Check the IV's of the Pokemon iv = pkmn['iv'] if iv != 'unkn': if iv < filt['min_iv'] or filt['max_iv'] < iv: if config['QUIET'] is False: log.info( "{} ignored: IVs ({:.2f}) not in range {:.2f} to {:.2f}." .format(name, iv, filt['min_iv'], filt['max_iv'])) return else: log.debug( "Pokemon IV's were not checked because they are unknown.") if filt['ignore_missing'] is True: log.info("{} ignored: IV information was missing".format(name)) return # Check the moves of the Pokemon move_1_id = pkmn['move_1_id'] move_2_id = pkmn['move_2_id'] # TODO: Move damage if move_1_id != 'unknown' and move_2_id != 'unknown': move_1_f, move_2_f, moveset_f = filt['move_1'], filt[ 'move_2'], filt['moveset'] if move_1_f is not None and move_1_id not in move_1_f: # Check Move 1 if config['QUIET'] is False: log.info("{} ignored: Move 1 was incorrect.".format(name)) return if move_2_f is not None and move_2_id not in move_2_f: # Check Move 2 if config['QUIET'] is False: log.info("{} ignored: Move 2 was incorrect.".format(name)) return if moveset_f is not None: # Check for movesets correct_moves = False for filt in moveset_f: correct_moves |= (move_1_id in filt and move_2_id in filt) if correct_moves is False: # Wrong moveset if config['QUIET'] is False: log.info( "{} ignored: Moveset was incorrect.".format(name)) return else: log.debug( "Pokemon moves were not checked because they are unknown.") if filt['ignore_missing'] is True: log.info( "{} ignored: Moves information was missing".format(name)) return # Check if in geofences if len(self.__geofences) > 0: inside = False for gf in self.__geofences: inside |= gf.contains(lat, lng) if not inside: if config['QUIET'] is False: log.info( "{} ignored: located outside geofences.".format(name)) return else: log.debug( "Pokemon inside geofences was not checked because no geofences were set." ) time_str = get_time_as_str(pkmn['disappear_time'], self.__timezone) pkmn.update({ 'pkmn': name, "dist": get_dist_as_str(dist) if dist != 'unkn' else 'unkn', 'time_left': time_str[0], '12h_time': time_str[1], '24h_time': time_str[2], 'dir': get_cardinal_dir([lat, lng], self.__latlng), 'iv_0': "{:.0f}".format(iv) if iv != 'unkn' else 'unkn', 'iv': "{:.1f}".format(iv) if iv != 'unkn' else 'unkn', 'iv_2': "{:.2f}".format(iv) if iv != 'unkn' else 'unkn', 'move_1': self.__move_name.get(move_1_id, 'unknown'), 'move_1_damage': get_move_damage(move_1_id), 'move_1_dps': get_move_dps(move_1_id), 'move_1_duration': get_move_duration(move_1_id), 'move_1_energy': get_move_energy(move_1_id), 'move_2': self.__move_name.get(move_2_id, 'unknown'), 'move_2_damage': get_move_damage(move_2_id), 'move_2_dps': get_move_dps(move_2_id), 'move_2_duration': get_move_duration(move_2_id), 'move_2_energy': get_move_energy(move_2_id) }) # Optional Stuff self.optional_arguments(pkmn) if config['QUIET'] is False: log.info("{} notification has been triggered!".format(name)) threads = [] # Spawn notifications in threads so they can work in background for alarm in self.__alarms: threads.append(gevent.spawn(alarm.pokemon_alert, pkmn)) gevent.sleep(0) # explict context yield for thread in threads: thread.join()
def process_gym_details(self, gym_details): if self.__gym_settings['enabled'] is False: log.debug("Gym ignored: notifications are disabled.") return # Extract some basic information gym_id = gym_details['id'] to_team_id = gym_details['team_id'] from_team_id = self.__gym_hist.get(gym_id) # Doesn't look like anything to me if to_team_id == from_team_id: log.debug("Gym ignored: no change detected") return # Ignore changes to neutral if self.__gym_settings['ignore_neutral'] and to_team_id == 0: log.debug("Gym update ignored: changed to neutral") return # Update gym's last known team self.__gym_hist[gym_id] = to_team_id # Ignore first time updates if from_team_id is None: log.debug("Gym update ignored: first time seeing this gym") return # Get some more info out used to check filters lat, lng = gym_details['lat'], gym_details['lng'] dist = get_earth_dist([lat, lng], self.__latlng) cur_team = self.__team_name[to_team_id] old_team = self.__team_name[from_team_id] filters = self.__gym_settings['filters'] passed = False for filt_ct in range(len(filters)): filt = filters[filt_ct] # Check the distance from the set location if dist != 'unkn': if filt.check_dist(dist) is False: if self.__quiet is False: log.info( "Gym rejected: distance ({:.2f}) was not in range" + " {:.2f} to {:.2f} (F #{})".format( dist, filt.min_dist, filt.max_dist, filt_ct)) continue else: log.debug( "Pokestop dist was not checked because the manager has no location set." ) # Check the old team if filt.check_from_team(from_team_id) is False: if self.__quiet is False: log.info( "Gym rejected: {} as old team is not correct (F #{})". format(old_team, filt_ct)) continue # Check the new team if filt.check_to_team(to_team_id) is False: if self.__quiet is False: log.info( "Gym rejected: {} as current team is not correct (F #{})" .format(cur_team, filt_ct)) continue # Nothing left to check, so it must have passed passed = True log.debug("Gym passed filter #{}".format(filt_ct)) break if not passed: return # Check the geofences gym['geofence'] = self.check_geofences('Gym', lat, lng) if len(self.__geofences) > 0 and gym['geofence'] == 'unknown': log.info("Gym rejected: not inside geofence(s)") return # Check if in geofences if len(self.__geofences) > 0: inside = False for gf in self.__geofences: inside |= gf.contains(lat, lng) if inside is False: if self.__quiet is False: log.info("Gym update ignored: located outside geofences.") return else: log.debug( "Gym inside geofences was not checked because no geofences were set." ) gym_details.update({ 'name': gym_details['name'], "dist": get_dist_as_str(dist), 'dir': get_cardinal_dir([lat, lng], self.__latlng), 'new_team': cur_team, 'old_team': old_team, 'defenders': gym_details['defenders'] }) self.add_optional_travel_arguments(gym_details) if self.__quiet is False: log.info( "Gym ({}) notification has been triggered!".format(gym_id)) threads = [] # Spawn notifications in threads so they can work in background for alarm in self.__alarms: threads.append(gevent.spawn(alarm.gym_alert, gym_details)) gevent.sleep(0) # explict context yield for thread in threads: thread.join()
def process_raid(self, raid): # Quick check for enabled if self.__raid_settings['enabled'] is False: log.debug("Raid ignored: notifications are disabled.") return gym_id = raid['id'] pkmn_id = raid['pkmn_id'] raid_end = raid['raid_end'] # DMS gym control reporting ************************************************************************************* gteam = self.__gym_hist.get(gym_id) log.info("DMS Raid gym control team number:{}".format(gteam)) if gteam == 1: gteamname = "Mystic" elif gteam == 2: gteamname = 'Valor' elif gteam == 3: gteamname = 'Instinct' else: gteamname = 'Unknown/None' log.info("DMS Raid gym control team string:{}".format(gteamname)) #to_team_id = gym['new_team_id'] #cur_team = self.__team_name[to_team_id] # gteam = gym_inf['new_team'] # log.info("Raid gym control team:{}".format(gteam)) # DMS ************************************************************************************* # begin DMS eliminate raids in Great America ************************************************************************************* gname = self.__gym_info.get(gym_id, {}).get('name', 'unknown') log.info("DMS raid gym name {}".format(gname)) if gname=='Ornate Elevated Vase': if self.__quiet is False: log.info("DMS Raid on {} ignored: GA Ornate Elevated Vase".format(gname)) return if gname=='The Demon': if self.__quiet is False: log.info("DMS Raid on {} ignored: GA The Demon".format(gname)) return if gname=='Frog Leg Pinwheel': if self.__quiet is False: log.info("DMS Raid on {} ignored: GA Frog Leg Pinwheel".format(gname)) return if gname=='On the Mic Karaoke': if self.__quiet is False: log.info("DMS Raid on {} ignored: GA On the Mic Karaoke".format(gname)) return if gname=='Boomerang Bay Torches': if self.__quiet is False: log.info("DMS Raid on {} ignored: GA Boomerang Bay Torches".format(gname)) return if gname=='Water Mushrooms': if self.__quiet is False: log.info("Raid on {} ignored: GA Water Mushrooms".format(gname)) return if gname=='Castaway Creek': if self.__quiet is False: log.info("DMS Raid on {} ignored: GA Castaway Creek".format(gname)) return # end DMS changes ************************************************************************************* # raid history will contain the end date and also the pokemon if it has hatched if gym_id in self.__raid_hist: old_raid_end = self.__raid_hist[gym_id]['raid_end'] old_raid_pkmn = self.__raid_hist[gym_id].get('pkmn_id', 0) if old_raid_end == raid_end: if old_raid_pkmn == pkmn_id: # raid with same end time exists and it has same pokemon id, skip it if self.__quiet is False: log.info("Raid {} ignored. Was previously processed.".format(gym_id)) return self.__raid_hist[gym_id] = dict(raid_end=raid_end, pkmn_id=pkmn_id) # don't alert about expired raids seconds_left = (raid_end - datetime.utcnow()).total_seconds() if seconds_left < self.__time_limit: if self.__quiet is False: log.info("Raid {} ignored. Only {} seconds left.".format(gym_id, seconds_left)) return lat, lng = raid['lat'], raid['lng'] dist = get_earth_dist([lat, lng], self.__location) # Check if raid is in geofences raid['geofence'] = self.check_geofences('Raid', lat, lng) if len(self.__geofences) > 0 and raid['geofence'] == 'unknown': if self.__quiet is False: log.info("Raid {} ignored: located outside geofences.".format(gym_id)) return else: log.debug("Raid inside geofence was not checked because no geofences were set.") quick_id = raid['quick_id'] charge_id = raid['charge_id'] # check filters for pokemon name = self.__locale.get_pokemon_name(pkmn_id) if pkmn_id not in self.__raid_settings['filters']: if self.__quiet is False: log.info("Raid on {} ignored: no filters are set".format(name)) return raid_pkmn = { 'pkmn': name, 'cp': raid['cp'], 'iv': 100, 'level': 20, 'def': 15, 'atk': 15, 'sta': 15, 'gender': 'unknown', 'size': 'unknown', 'form_id': '?', 'quick_id': quick_id, 'charge_id': charge_id } filters = self.__raid_settings['filters'][pkmn_id] passed = self.check_pokemon_filter(filters, raid_pkmn, dist) # If we didn't pass any filters if not passed: log.debug("Raid {} did not pass pokemon check".format(gym_id)) return if self.__loc_service: self.__loc_service.add_optional_arguments(self.__location, [lat, lng], raid) if self.__quiet is False: log.info("Raid ({}) notification has been triggered!".format(gym_id)) time_str = get_time_as_str(raid['raid_end'], self.__timezone) start_time_str = get_time_as_str(raid['raid_begin'], self.__timezone) gym_info = self.__gym_info.get(gym_id, {}) raid.update({ 'pkmn': name, "gym_name": gym_info.get('name', 'unknown'), "gym_description": gym_info.get('description', 'unknown'), "gym_url": gym_info.get('url', 'https://raw.githubusercontent.com/RocketMap/PokeAlarm/master/icons/gym_0.png'), 'time_left': time_str[0], '12h_time': time_str[1], '24h_time': time_str[2], 'begin_time_left': start_time_str[0], 'begin_12h_time': start_time_str[1], #DMS raid gym control reporting hack '24h_time': time_str[2], '24h_time': gteamname, "dist": get_dist_as_str(dist), 'dir': get_cardinal_dir([lat, lng], self.__location), 'quick_move': self.__locale.get_move_name(quick_id), 'charge_move': self.__locale.get_move_name(charge_id), 'form': self.__locale.get_form_name(pkmn_id, raid_pkmn['form_id']) }) threads = [] # Spawn notifications in threads so they can work in background for alarm in self.__alarms: threads.append(gevent.spawn(alarm.raid_alert, raid)) gevent.sleep(0) # explict context yield for thread in threads: thread.join()
def process_raid(self, raid): # Quick check for enabled if self.__raid_settings['enabled'] is False: log.debug("Raid ignored: notifications are disabled.") return gym_id = raid['id'] pkmn_id = raid['pkmn_id'] raid_end = raid['raid_end'] # raid history will contain the end date and also the pokemon if it has hatched if gym_id in self.__raid_hist: old_raid_end = self.__raid_hist[gym_id]['raid_end'] old_raid_pkmn = self.__raid_hist[gym_id].get('pkmn_id', 0) if old_raid_end == raid_end: if old_raid_pkmn == pkmn_id: # raid with same end time exists and it has same pokemon id, skip it if self.__quiet is False: log.info("Raid {} ignored. Was previously processed.". format(gym_id)) return self.__raid_hist[gym_id] = dict(raid_end=raid_end, pkmn_id=pkmn_id) # don't alert about expired raids seconds_left = (raid_end - datetime.utcnow()).total_seconds() if seconds_left < self.__time_limit: if self.__quiet is False: log.info("Raid {} ignored. Only {} seconds left.".format( gym_id, seconds_left)) return lat, lng = raid['lat'], raid['lng'] dist = get_earth_dist([lat, lng], self.__location) # Check if raid is in geofences raid['geofence'] = self.check_geofences('Raid', lat, lng) if len(self.__geofences) > 0 and raid['geofence'] == 'unknown': if self.__quiet is False: log.info("Raid {} ignored: located outside geofences.".format( gym_id)) return else: log.debug( "Raid inside geofence was not checked because no geofences were set." ) quick_id = raid['quick_id'] charge_id = raid['charge_id'] # check filters for pokemon name = self.__locale.get_pokemon_name(pkmn_id) if pkmn_id not in self.__raid_settings['filters']: if self.__quiet is False: log.info("Raid on {} ignored: no filters are set".format(name)) return raid_pkmn = { 'pkmn': name, 'cp': raid['cp'], 'iv': 100, 'level': 20, 'def': 15, 'atk': 15, 'sta': 15, 'gender': 'unknown', 'size': 'unknown', 'form_id': '?', 'quick_id': quick_id, 'charge_id': charge_id } filters = self.__raid_settings['filters'][pkmn_id] passed = self.check_pokemon_filter(filters, raid_pkmn, dist) # If we didn't pass any filters if not passed: log.debug("Raid {} did not pass pokemon check".format(gym_id)) return if self.__loc_service: self.__loc_service.add_optional_arguments(self.__location, [lat, lng], raid) if self.__quiet is False: log.info( "Raid ({}) notification has been triggered!".format(gym_id)) time_str = get_time_as_str(raid['raid_end'], self.__timezone) start_time_str = get_time_as_str(raid['raid_begin'], self.__timezone) gym_info = self.__gym_info.get(gym_id, {}) raid.update({ 'pkmn': name, #"gym_name": self.__gym_info.get(gym_id, {}).get('name', 'unknown'), #"gym_description": self.__gym_info.get(gym_id, {}).get('description', 'unknown'), #"gym_url": self.__gym_info.get(gym_id, {}).get('url', 'https://raw.githubusercontent.com/kvangent/PokeAlarm/master/icons/gym_0.png'), 'time_left': time_str[0], '12h_time': time_str[1], '24h_time': time_str[2], 'begin_time_left': start_time_str[0], 'begin_12h_time': start_time_str[1], 'begin_24h_time': start_time_str[2], "dist": get_dist_as_str(dist), 'quick_move': self.__locale.get_move_name(quick_id), 'charge_move': self.__locale.get_move_name(charge_id), #'team': self.__team_name[raid['team_id']], 'dir': get_cardinal_dir([lat, lng], self.__location), 'form': self.__locale.get_form_name(pkmn_id, raid_pkmn['form_id']) }) threads = [] # Spawn notifications in threads so they can work in background for alarm in self.__alarms: threads.append(gevent.spawn(alarm.raid_alert, raid)) gevent.sleep(0) # explict context yield for thread in threads: thread.join()
def process_gym(self, gym): gym_id = gym['id'] # Update Gym details (if they exist) if gym_id not in self.__gym_info or gym['name'] != 'unknown': self.__gym_info[gym_id] = { "name": gym['name'], "description": gym['description'], "url": gym['url'] } # DMS raid control reporting******************************************************************** to_team_id = gym['new_team_id'] # Update gym's last known team self.__gym_hist[gym_id] = to_team_id # DMS raid control reporting ********************************************************************* if self.__gym_settings['enabled'] is False: log.debug("Gym ignored: notifications are disabled.") return # Extract some basic information to_team_id = gym['new_team_id'] from_team_id = self.__gym_hist.get(gym_id) # Doesn't look like anything to me if to_team_id == from_team_id: log.debug("Gym ignored: no change detected") return # Ignore changes to neutral if self.__gym_settings['ignore_neutral'] and to_team_id == 0: log.debug("Gym update ignored: changed to neutral") return # Update gym's last known team self.__gym_hist[gym_id] = to_team_id # Ignore first time updates if from_team_id is None: log.debug("Gym update ignored: first time seeing this gym") return # Get some more info out used to check filters lat, lng = gym['lat'], gym['lng'] dist = get_earth_dist([lat, lng], self.__location) cur_team = self.__locale.get_team_name(to_team_id) old_team = self.__locale.get_team_name(from_team_id) filters = self.__gym_settings['filters'] passed = False for filt_ct in range(len(filters)): filt = filters[filt_ct] # Check the distance from the set location if dist != 'unkn': if filt.check_dist(dist) is False: if self.__quiet is False: log.info("Gym rejected: distance ({:.2f}) was not in range" + " {:.2f} to {:.2f} (F #{})".format(dist, filt.min_dist, filt.max_dist, filt_ct)) continue else: log.debug("Gym dist was not checked because the manager has no location set.") # Check the old team if filt.check_from_team(from_team_id) is False: if self.__quiet is False: log.info("Gym rejected: {} as old team is not correct (F #{})".format(old_team, filt_ct)) continue # Check the new team if filt.check_to_team(to_team_id) is False: if self.__quiet is False: log.info("Gym rejected: {} as current team is not correct (F #{})".format(cur_team, filt_ct)) continue # Nothing left to check, so it must have passed passed = True log.debug("Gym passed filter #{}".format(filt_ct)) break if not passed: return # Check the geofences gym['geofence'] = self.check_geofences('Gym', lat, lng) if len(self.__geofences) > 0 and gym['geofence'] == 'unknown': log.info("Gym rejected: not inside geofence(s)") return # Check if in geofences if len(self.__geofences) > 0: inside = False for gf in self.__geofences: inside |= gf.contains(lat, lng) if inside is False: if self.__quiet is False: log.info("Gym update ignored: located outside geofences.") return else: log.debug("Gym inside geofences was not checked because no geofences were set.") gym_info = self.__gym_info.get(gym_id, {}) gym.update({ "gym_name": gym_info.get('name', 'unknown'), "gym_description": gym_info.get('description', 'unknown'), "gym_url": gym_info.get('url', 'https://raw.githubusercontent.com/RocketMap/PokeAlarm/master/icons/gym_0.png'), "dist": get_dist_as_str(dist), 'dir': get_cardinal_dir([lat, lng], self.__location), 'new_team': cur_team, 'new_team_id': to_team_id, 'old_team': old_team, 'old_team_id': from_team_id, 'new_team_leader': self.__locale.get_leader_name(to_team_id), 'old_team_leader': self.__locale.get_leader_name(from_team_id) }) if self.__loc_service: self.__loc_service.add_optional_arguments(self.__location, [lat, lng], gym) if self.__quiet is False: log.info("Gym ({}) notification has been triggered!".format(gym_id)) threads = [] # Spawn notifications in threads so they can work in background for alarm in self.__alarms: threads.append(gevent.spawn(alarm.gym_alert, gym)) gevent.sleep(0) # explict context yield for thread in threads: thread.join()
def process_pokemon(self, pkmn): # Make sure that pokemon are enabled if self.__pokemon_settings['enabled'] is False: log.debug("Pokemon ignored: pokemon notifications are disabled.") return # Extract some base information id_ = pkmn['id'] pkmn_id = pkmn['pkmn_id'] name = self.__locale.get_pokemon_name(pkmn_id) # Check for previously processed if id_ in self.__pokemon_hist: log.debug( "{} was skipped because it was previously processed.".format( name)) return self.__pokemon_hist[id_] = pkmn['disappear_time'] # Check the time remaining seconds_left = (pkmn['disappear_time'] - datetime.utcnow()).total_seconds() if seconds_left < self.__time_limit: if self.__quiet is False: log.info("{} ignored: Only {} seconds remaining.".format( name, seconds_left)) return # Check that the filter is even set if pkmn_id not in self.__pokemon_settings['filters']: if self.__quiet is False: log.info("{} ignored: no filters are set".format(name)) return # Extract some useful info that will be used in the filters lat, lng = pkmn['lat'], pkmn['lng'] dist = get_earth_dist([lat, lng], self.__location) form_id = pkmn.get('form_id', 0) if form_id == '?': form_id = 0 pkmn['pkmn'] = name filters = self.__pokemon_settings['filters'][pkmn_id] passed = self.check_pokemon_filter(filters, pkmn, dist) # If we didn't pass any filters if not passed: return quick_id = pkmn['quick_id'] charge_id = pkmn['charge_id'] weather_id = pkmn['weather'] # Check all the geofences pkmn['geofence'] = self.check_geofences(name, lat, lng) if len(self.__geofences) > 0 and pkmn['geofence'] == 'unknown': log.info("{} rejected: not inside geofence(s)".format(name)) return # Finally, add in all the extra crap we waited to calculate until now time_str = get_time_as_str(pkmn['disappear_time'], self.__timezone) iv = pkmn['iv'] pkmn.update({ 'pkmn': name, "dist": get_dist_as_str(dist) if dist != 'unkn' else 'unkn', 'time_left': time_str[0], '12h_time': time_str[1], '24h_time': time_str[2], 'dir': get_cardinal_dir([lat, lng], self.__location), 'iv_0': "{:.0f}".format(iv) if iv != '?' else '?', 'iv': "{:.1f}".format(iv) if iv != '?' else '?', 'iv_2': "{:.2f}".format(iv) if iv != '?' else '?', 'quick_move': self.__locale.get_move_name(quick_id), 'charge_move': self.__locale.get_move_name(charge_id), 'form_id': (chr(64 + int(form_id))) if form_id and int(form_id) > 0 else '', 'weather': self.__locale.get_weather_name(weather_id) }) if self.__loc_service: self.__loc_service.add_optional_arguments(self.__location, [lat, lng], pkmn) if self.__quiet is False: log.info("{} notification has been triggered!".format(name)) threads = [] # Spawn notifications in threads so they can work in background for alarm in self.__alarms: threads.append(gevent.spawn(alarm.pokemon_alert, pkmn)) gevent.sleep(0) # explict context yield for thread in threads: thread.join()
def process_monster(self, mon): # type: (Events.MonEvent) -> None """ Process a monster event and notify alarms if it passes. """ # Make sure that monsters are enabled if self.__mons_enabled is False: log.debug("Monster ignored: monster notifications are disabled.") return # Set the name for this event so we can log rejects better mon.name = self.__locale.get_pokemon_name(mon.monster_id) # Skip if previously processed if self.__cache.get_pokemon_expiration(mon.enc_id) is not None: log.debug("{} monster was skipped because it was previously " "processed.".format(mon.name)) return self.__cache.update_pokemon_expiration( mon.enc_id, mon.disappear_time) # Check the time remaining seconds_left = (mon.disappear_time - datetime.utcnow()).total_seconds() if seconds_left < self.__time_limit: log.debug("{} monster was skipped because only {} seconds remained" "".format(mon.name, seconds_left)) return # Calculate distance and direction if self.__location is not None: mon.distance = get_earth_dist( [mon.lat, mon.lng], self.__location) mon.direction = get_cardinal_dir( [mon.lat, mon.lng], self.__location) # Check the Filters passed = False for name, f in self.__mon_filters.iteritems(): passed = f.check_event(mon) and self.check_geofences(f, mon) if passed: # Stop checking mon.custom_dts = f.custom_dts break if not passed: # Monster was rejected by all filters return # Generate the DTS for the event dts = mon.generate_dts(self.__locale) if self.__loc_service: self.__loc_service.add_optional_arguments( self.__location, [mon.lat, mon.lng], dts) if self.__quiet is False: log.info("{} monster notification has been triggered!".format( mon.name)) threads = [] # Spawn notifications in threads so they can work in background for alarm in self.__alarms: threads.append(gevent.spawn(alarm.pokemon_alert, dts)) gevent.sleep(0) # explict context yield for thread in threads: thread.join()
def process_pokemon(self, pkmn): # Make sure that pokemon are enabled if self.__pokemon_settings['enabled'] is False: log.debug("Pokemon ignored: pokemon notifications are disabled.") return # Extract some base information id_ = pkmn['id'] pkmn_id = pkmn['pkmn_id'] name = self.__pokemon_name[pkmn_id] # Check for previously processed if id_ in self.__pokemon_hist: log.debug( "{} was skipped because it was previously processed.".format( name)) return self.__pokemon_hist[id_] = pkmn['disappear_time'] # Check the time remaining seconds_left = (pkmn['disappear_time'] - datetime.utcnow()).total_seconds() if seconds_left < self.__time_limit: if self.__quiet is False: log.info("{} ignored: Only {} seconds remaining.".format( name, seconds_left)) return # Check that the filter is even set if pkmn_id not in self.__pokemon_settings['filters']: if self.__quiet is False: log.info("{} ignored: no filters are set".format(name)) return # Extract some useful info that will be used in the filters passed = False lat, lng = pkmn['lat'], pkmn['lng'] dist = get_earth_dist([lat, lng], self.__latlng) iv = pkmn['iv'] def_ = pkmn['def'] atk = pkmn['atk'] sta = pkmn['sta'] quick_id = pkmn['quick_id'] charge_id = pkmn['charge_id'] size = pkmn['size'] gender = pkmn['gender'] form = pkmn['form'] filters = self.__pokemon_settings['filters'][pkmn_id] for filt_ct in range(len(filters)): filt = filters[filt_ct] # Check the distance from the set location if dist != 'unkn': if filt.check_dist(dist) is False: if self.__quiet is False: log.info( "{} rejected: distance ({:.2f}) was not in range {:.2f} to {:.2f} (F #{})" .format(name, dist, filt.min_dist, filt.max_dist, filt_ct)) continue else: log.debug( "Filter dist was not checked because the manager has no location set." ) # Check the IV percent of the Pokemon if iv != '?': if not filt.check_iv(iv): if self.__quiet is False: log.info( "{} rejected: IV percent ({:.2f}) not in range {:.2f} to {:.2f} - (F #{})" .format(name, iv, filt.min_iv, filt.max_iv, filt_ct)) continue else: if filt.ignore_missing is True: log.info( "{} rejected: 'IV' information was missing (F #{})". format(name, filt_ct)) continue log.debug( "Pokemon IV percent was not checked because it was missing." ) # Check the Attack IV of the Pokemon if atk != '?': if not filt.check_atk(atk): if self.__quiet is False: log.info( "{} rejected: Attack IV ({}) not in range {} to {} - (F #{})" .format(name, atk, filt.min_atk, filt.max_atk, filt_ct)) continue else: if filt.ignore_missing is True: log.info( "{} rejected: Attack IV information was missing - (F #{})" .format(name, filt_ct)) continue log.debug( "Pokemon 'atk' was not checked because it was missing.") # Check the Defense IV of the Pokemon if def_ != '?': if not filt.check_def(def_): if self.__quiet is False: log.info( "{} rejected: Defense IV ({}) not in range {} to {} - (F #{})" .format(name, def_, filt.min_atk, filt.max_atk, filt_ct)) continue else: if filt.ignore_missing is True: log.info( "{} rejected: Defense IV information was missing - (F #{})" .format(name, filt_ct)) continue log.debug( "Pokemon 'def' was not checked because it was missing.") # Check the Stamina IV of the Pokemon if sta != '?': if not filt.check_sta(sta): if self.__quiet is False: log.info( "{} rejected: Stamina IV ({}) not in range {} to {} - (F #{})." .format(name, def_, filt.min_sta, filt.max_sta, filt_ct)) continue else: if filt.ignore_missing is True: log.info( "{} rejected: Stamina IV information was missing - (F #{})" .format(name, filt_ct)) continue log.debug( "Pokemon 'sta' was not checked because it was missing.") # Check the Quick Move of the Pokemon if quick_id != '?': if not filt.check_quick_move(quick_id): if self.__quiet is False: log.info( "{} rejected: Quick move was not correct - (F #{})" .format(name, filt_ct)) continue else: if filt.ignore_missing is True: log.info( "{} rejected: Quick move information was missing - (F #{})" .format(name, filt_ct)) continue log.debug( "Pokemon 'quick_id' was not checked because it was missing." ) # Check the Quick Move of the Pokemon if charge_id != '?': if not filt.check_charge_move(charge_id): if self.__quiet is False: log.info( "{} rejected: Charge move was not correct - (F #{})" .format(name, filt_ct)) continue else: if filt.ignore_missing is True: log.info( "{} rejected: Charge move information was missing - (F #{})" .format(name, filt_ct)) continue log.debug( "Pokemon 'charge_id' was not checked because it was missing." ) # Check for a correct move combo if quick_id != '?' and charge_id != '?': if not filt.check_moveset(quick_id, charge_id): if self.__quiet is False: log.info( "{} rejected: Moveset was not correct - (F #{})". format(name, filt_ct)) continue else: # This will probably never happen? but just to be safe... if filt.ignore_missing is True: log.info( "{} rejected: Moveset information was missing - (F #{})" .format(name, filt_ct)) continue log.debug( "Pokemon 'moveset' was not checked because it was missing." ) # Check for a valid size if size != 'unknown': if not filt.check_size(size): if self.__quiet is False: log.info( "{} rejected: Size ({}) was not correct - (F #{})". format(name, size, filt_ct)) continue else: if filt.ignore_missing is True: log.info( "{} rejected: Size information was missing - (F #{})". format(name, filt_ct)) continue log.debug( "Pokemon 'size' was not checked because it was missing.") # Check for a valid gender if gender != 'unknown': if not filt.check_gender(gender): if self.__quiet is False: log.info( "{} rejected: Gender ({}) was not correct - (F #{})" .format(name, gender, filt_ct)) continue else: if filt.ignore_missing is True: log.info( "{} rejected: Gender information was missing - (F #{})" .format(name, filt_ct)) continue log.debug( "Pokemon 'gender' was not checked because it was missing.") # Nothing left to check, so it must have passed passed = True log.debug("{} passed filter #{}".format(name, filt_ct)) break # If we didn't pass any filters if not passed: return # Check all the geofences pkmn['geofence'] = self.check_geofences(name, lat, lng) if len(self.__geofences) > 0 and pkmn['geofence'] == 'unknown': log.info("{} rejected: not inside geofence(s)".format(name)) return # Finally, add in all the extra crap we waited to calculate until now time_str = get_time_as_str(pkmn['disappear_time'], self.__timezone) # If it has a form it's an unown and append form onto name if form != "unset": name = name + " - " + form pkmn.update({ 'pkmn': name, "dist": get_dist_as_str(dist) if dist != 'unkn' else 'unkn', 'time_left': time_str[0], '12h_time': time_str[1], '24h_time': time_str[2], 'dir': get_cardinal_dir([lat, lng], self.__latlng), 'iv_0': "{:.0f}".format(iv) if iv != '?' else '?', 'iv': "{:.1f}".format(iv) if iv != '?' else '?', 'iv_2': "{:.2f}".format(iv) if iv != '?' else '?', 'quick_move': self.__move_name.get(quick_id, 'unknown'), 'charge_move': self.__move_name.get(charge_id, 'unknown') }) self.add_optional_travel_arguments(pkmn) if self.__quiet is False: log.info("{} notification has been triggered!".format(name)) threads = [] # Spawn notifications in threads so they can work in background for alarm in self.__alarms: threads.append(gevent.spawn(alarm.pokemon_alert, pkmn)) gevent.sleep(0) # explict context yield for thread in threads: thread.join()
def handle_pokestop(self, stop): # Quick check for enabled if self.__pokestop_filter['enabled'] is False: log.debug("Pokestop ignored: notifications are disabled.") return id_ = stop['id'] # Check for previously processed (and make sure previous lure hasn't expired) if id_ in self.__pokestop_hist and self.__pokestop_hist[ id_] >= datetime.utcnow(): if config['QUIET'] is False: log.debug( "Pokestop ({}) ignored: because it was previously notified." .format(id_)) return self.__pokestop_hist[id_] = expire_time = stop['expire_time'] # Check the time remaining seconds_left = (expire_time - datetime.utcnow()).total_seconds() if seconds_left < self.__time_limit: if config['QUIET'] is False: log.info( "Pokestop ({}) ignored: only {} seconds remaining.".format( id_, seconds_left)) return filt = self.__pokestop_filter # Check the distance from the set location lat, lng = stop['lat'], stop['lng'] dist = get_earth_dist([lat, lng], self.__latlng) if dist != 'unkn': if dist < filt['min_dist'] or filt['max_dist'] < dist: if config['QUIET'] is False: log.info( "Pokestop ({}) ignored: distance was not in range {:.2f} to {:.2f}." .format(id_, filt['min_dist'], filt['max_dist'])) return else: log.debug( "Pokestop distance was not checked because no location was set." ) # Check if in geofences if len(self.__geofences) > 0: inside = False for gf in self.__geofences: inside |= gf.contains(lat, lng) if not inside: if config['QUIET'] is False: log.info("Pokestop ignored: located outside geofences.") return else: log.debug( "Pokestop inside geofences was not checked because no geofences were set." ) time_str = get_time_as_str(expire_time, self.__timezone) stop.update({ "dist": get_dist_as_str(dist) if dist != 'unkn' else 'unkn', 'time_left': time_str[0], '12h_time': time_str[1], '24h_time': time_str[2], 'dir': get_cardinal_dir([lat, lng], self.__latlng), }) # Optional Stuff self.optional_arguments(stop) if config['QUIET'] is False: log.info( "Pokestop ({}) notification has been triggered!".format(id_)) threads = [] # Spawn notifications in threads so they can work in background for alarm in self.__alarms: threads.append(gevent.spawn(alarm.pokestop_alert, stop)) gevent.sleep(0) # explict context yield for thread in threads: thread.join()
def process_pokestop(self, stop): # Make sure that pokemon are enabled if self.__pokestop_settings['enabled'] is False: log.debug("Pokestop ignored: pokestop notifications are disabled.") return id_ = stop['id'] # Check for previously processed if id_ in self.__pokestop_hist: log.debug( "Pokestop was skipped because it was previously processed.") return self.__pokestop_hist[id_] = stop['expire_time'] # Check the time remaining seconds_left = (stop['expire_time'] - datetime.utcnow()).total_seconds() if seconds_left < self.__time_limit: if self.__quiet is False: log.info( "Pokestop ({}) ignored: only {} seconds remaining.".format( id_, seconds_left)) return # Extract some basic information lat, lng = stop['lat'], stop['lng'] dist = get_earth_dist([lat, lng], self.__latlng) passed = False filters = self.__pokestop_settings['filters'] for filt_ct in range(len(filters)): filt = filters[filt_ct] # Check the distance from the set location if dist != 'unkn': if filt.check_dist(dist) is False: if self.__quiet is False: log.info( "Pokestop rejected: distance ({:.2f}) was not in range" .format(dist) + " {:.2f} to {:.2f} (F #{})".format( filt.min_dist, filt.max_dist, filt_ct)) continue else: log.debug( "Pokestop dist was not checked because the manager has no location set." ) # Nothing left to check, so it must have passed passed = True log.debug("Pokstop passed filter #{}".format(filt_ct)) break if not passed: return # Check the geofences stop['geofence'] = self.check_geofences('Pokestop', lat, lng) if len(self.__geofences) > 0 and stop['geofence'] == 'unknown': log.info("Pokestop rejected: not within any specified geofence") return time_str = get_time_as_str(stop['expire_time'], self.__timezone) stop.update({ "dist": get_dist_as_str(dist), 'time_left': time_str[0], '12h_time': time_str[1], '24h_time': time_str[2], 'dir': get_cardinal_dir([lat, lng], self.__latlng), }) self.add_optional_travel_arguments(stop) if self.__quiet is False: log.info( "Pokestop ({}) notification has been triggered!".format(id_)) threads = [] # Spawn notifications in threads so they can work in background for alarm in self.__alarms: threads.append(gevent.spawn(alarm.pokestop_alert, stop)) gevent.sleep(0) # explict context yield for thread in threads: thread.join()
def handle_gym(self, gym): # Quick check for enabled if self.__gym_filter['enabled'] is False: log.debug("Gym ignored: notifications are disabled.") return log.debug("Gyms set to {}.".format(self.__gym_filter['enabled'])) id_ = gym['id'] team_id = gym['team_id'] old_team = self.__gym_hist.get(id_) # Ignore gyms when there is no change if old_team == team_id: log.debug("Gym update ignored: team didn't change") return # Ignore changes to neutral if self.__gym_filter['ignore_neutral'] and team_id == 0: log.debug("Gym update ignored: changed to neutral") return self.__gym_hist[id_] = team_id # Ignore first time updates if old_team is None: log.debug("Gym update ignored: first time seeing gym") return if old_team not in self.__gym_filter and team_id not in self.__gym_filter: if config['QUIET'] is False: log.info("Gym update ignored: neither team is enabled") return lat, lng = gym['lat'], gym['lng'] dist = get_earth_dist([lat, lng], self.__latlng) if dist != 'unkn': old_range, new_range = False, False old_f = self.__gym_filter.get(old_team) if old_f is not None: old_range = old_f['min_dist'] <= dist <= old_f['max_dist'] new_f = self.__gym_filter.get(team_id) if new_f is not None: new_range = new_f['min_dist'] <= dist <= new_f['max_dist'] if old_range is False and new_range is False: if config['QUIET'] is False: log.info("Gym update ignored: both teams outside range") return else: log.debug( "Gym distance was not checked because no location was set.") # Check if in geofences if len(self.__geofences) > 0: inside = False for gf in self.__geofences: inside |= gf.contains(lat, lng) if inside is False: if config['QUIET'] is False: log.info("Gym update ignored: located outside geofences.") return else: log.debug( "Gym inside geofences was not checked because no geofences were set." ) # Optional Stuff self.optional_arguments(gym) if config['QUIET'] is False: log.info("Gym ({}) notification has been triggered!".format(id_)) gym.update({ "dist": get_dist_as_str(dist) if dist != 'unkn' else 'unkn', 'new_team': self.__team_name[team_id], 'old_team': self.__team_name[old_team], 'dir': get_cardinal_dir([lat, lng], self.__latlng), }) threads = [] # Spawn notifications in threads so they can work in background for alarm in self.__alarms: threads.append(gevent.spawn(alarm.gym_alert, gym)) gevent.sleep(0) # explict context yield for thread in threads: thread.join()
def process_raid(self, raid): # type: (Events.RaidEvent) -> None """ Process a raid event and notify alarms if it passes. """ # Update Gym details (if they exist) raid.gym_name = self.__cache.gym_name(raid.gym_id, raid.gym_name) raid.gym_description = self.__cache.gym_desc( raid.gym_id, raid.gym_description) raid.gym_image = self.__cache.gym_image(raid.gym_id, raid.gym_image) # Update Team if Unknown if Unknown.is_(raid.current_team_id): raid.current_team_id = self.__cache.gym_team(raid.gym_id) # Make sure that raids are enabled if self._raids_enabled is False: self._log.debug("Raid ignored: raid notifications are disabled.") return # Skip if previously processed if self.__cache.raid_expiration(raid.gym_id) is not None: self._log.debug("Raid {} was skipped because it was " "previously processed.".format(raid.name)) return self.__cache.raid_expiration(raid.gym_id, raid.raid_end) # Check the time remaining seconds_left = (raid.raid_end - datetime.utcnow()).total_seconds() if seconds_left < self.__time_limit: self._log.debug("Raid {} was skipped because only {} seconds " "remained".format(raid.name, seconds_left)) return # Calculate distance and direction if self.__location is not None: raid.distance = get_earth_dist( [raid.lat, raid.lng], self.__location, self.__units) raid.direction = get_cardinal_dir( [raid.lat, raid.lng], self.__location) # Check for Rules rules = self.__raid_rules if len(rules) == 0: # If no rules, default to all rules = {"default": Rule( self._raid_filters.keys(), self._alarms.keys())} rule_ct, alarm_ct = 0, 0 for r_name, rule in rules.iteritems(): # For all rules passed = self._check_filters( raid, self._raid_filters, rule.filter_names) if passed: rule_ct += 1 alarm_ct += len(rule.alarm_names) self._notify_alarms( raid, rule.alarm_names, 'raid_alert') if rule_ct > 0: self._rule_log.info( 'Raid %s passed %s rule(s) and triggered %s alarm(s).', raid.name, rule_ct, alarm_ct) else: self._rule_log.info('Raid %s rejected by all rules.', raid.name)
def process_gym(self, gym): # type: (Events.GymEvent) -> None """ Process a gym event and notify alarms if it passes. """ # Update Gym details (if they exist) self.__cache.update_gym_info( gym.gym_id, gym.gym_name, gym.gym_description, gym.gym_image) # Ignore changes to neutral if self.__ignore_neutral and gym.new_team_id == 0: log.debug("%s gym update skipped: new team was neutral") return # Get the old team and update new team gym.old_team_id = self.__cache.get_gym_team(gym.gym_id) self.__cache.update_gym_team(gym.gym_id, gym.new_team_id) # Check if notifications are on if self.__gyms_enabled is False: log.debug("Gym ignored: gym notifications are disabled.") return # Update the cache with the gyms info info = self.__cache.get_gym_info(gym.gym_id) gym.gym_name = info['name'] gym.gym_description = info['description'] gym.gym_image = info['url'] # Doesn't look like anything to me if gym.new_team_id == gym.old_team_id: log.debug("%s gym update skipped: no change detected", gym.gym_id) return # Calculate distance and direction if self.__location is not None: gym.distance = get_earth_dist( [gym.lat, gym.lng], self.__location) gym.direction = get_cardinal_dir( [gym.lat, gym.lng], self.__location) # Check the Filters passed = True for name, f in self.__gym_filters.iteritems(): passed = f.check_event(gym) and self.check_geofences(f, gym) if passed: # Stop checking gym.custom_dts = f.custom_dts break if not passed: # Gym was rejected by all filters return # Generate the DTS for the event dts = gym.generate_dts(self.__locale) dts.update(self.__cache.get_gym_info(gym.gym_id)) # update gym info if self.__loc_service: self.__loc_service.add_optional_arguments( self.__location, [gym.lat, gym.lng], dts) if self.__quiet is False: log.info( "{} gym notification has been triggered!".format(gym.name)) threads = [] # Spawn notifications in threads so they can work in background for alarm in self.__alarms: threads.append(gevent.spawn(alarm.gym_alert, dts)) gevent.sleep(0) # explict context yield for thread in threads: thread.join()
def process_raid(self, raid): # Make sure that pokemon are enabled if self.__raid_settings['enabled'] is False: log.debug("Raid ignored: raid notifications are disabled.") return id_ = raid['id'] # Check for previously processed if id_ in self.__raid_hist: log.debug("Raid was skipped because it was previously processed.") return # Ignore if the Pokemon ID is still missing (it is an egg). # Store the raid start time in this case. if raid['pkmn_id'] == '?': log.info("Raid ({}) ignored: No pokemon exists.".format(id_)) return else: # Store the raid end time and continue processing self.__raid_hist[id_] = raid['raid_end'] # Extract some useful info that will be used in the filters passed = False lat, lng = raid['lat'], raid['lng'] dist = get_earth_dist([lat, lng], self.__latlng) level = raid['level'] pkmn_id = raid['pkmn_id'] name = self.__pokemon_name[pkmn_id] filters = self.__raid_settings['filters'] for filt_ct in range(len(filters)): filt = filters[filt_ct] # Check the distance from the set location if dist != 'unkn': if filt.check_dist(dist) is False: if self.__quiet is False: log.info( "Raid rejected: distance ({:.2f}) was not in range" .format(dist) + " {:.2f} to {:.2f} (F #{})".format( filt.min_dist, filt.max_dist, filt_ct)) continue else: log.debug( "Raid dist was not checked because the manager has no location set." ) if not filt.check_level(level): if self.__quiet is False: log.info( "Raid rejected: Level ({}) not in range {} to {} - (F #{})" .format(level, filt.min_level, filt.max_level, filt_ct)) continue # Nothing left to check, so it must have passed passed = True log.debug("Raid passed filter #{}".format(filt_ct)) break if not passed: return # Check the geofences raid['geofence'] = self.check_geofences('Raid', lat, lng) if len(self.__geofences) > 0 and raid['geofence'] == 'unknown': log.info("Raid rejected: not within any specified geofence") return time_str = get_time_as_str(raid['raid_end'], self.__timezone) raid.update({ "dist": get_dist_as_str(dist), 'pkmn': name, 'time_left': time_str[0], '12h_time': time_str[1], '24h_time': time_str[2], 'dir': get_cardinal_dir([lat, lng], self.__latlng), }) self.add_optional_travel_arguments(raid) if self.__quiet is False: log.info("Raid ({}/{}) notification has been triggered!".format( id_, name)) threads = [] # Spawn notifications in threads so they can work in background for alarm in self.__alarms: threads.append(gevent.spawn(alarm.raid_alert, raid)) gevent.sleep(0) # explict context yield for thread in threads: thread.join()
def process_weather(self, weather): # type: (Events.WeatherEvent) -> None """ Process a weather event and notify alarms if it passes. """ # Set the name for this event so we can log rejects better weather.name = self.__locale.get_weather_name(weather.s2_cell_id) # Make sure that weather changes are enabled if self._weather_enabled is False: self._log.debug("Weather ignored: weather change " "notifications are disabled.") return # Calculate distance and direction if self.__location is not None: weather.distance = get_earth_dist( [weather.lat, weather.lng], self.__location, self.__units) weather.direction = get_cardinal_dir( [weather.lat, weather.lng], self.__location) # Store copy of cache info cache_weather_id = self.__cache.cell_weather_id(weather.s2_cell_id) cache_day_or_night_id = self.__cache.day_or_night_id( weather.s2_cell_id) cache_severity_id = self.__cache.severity_id(weather.s2_cell_id) # Update cache info self.__cache.cell_weather_id(weather.s2_cell_id, weather.weather_id) self.__cache.day_or_night_id( weather.s2_cell_id, weather.day_or_night_id) self.__cache.severity_id(weather.s2_cell_id, weather.severity_id) # Check and see if the weather hasn't changed and ignore if weather.weather_id == cache_weather_id and \ weather.day_or_night_id == cache_day_or_night_id and \ weather.severity_id == cache_severity_id: self._log.debug( "weather of %s, alert of %s, and day or night of %s skipped: " "no change detected", weather.weather_id, weather.severity_id, weather.day_or_night_id) return # Check for Rules rules = self.__weather_rules if len(rules) == 0: # If no rules, default to all rules = {"default": Rule( self._weather_filters.keys(), self._alarms.keys())} rule_ct, alarm_ct = 0, 0 for r_name, rule in rules.iteritems(): # For all rules passed = self._check_filters( weather, self._weather_filters, rule.filter_names) if passed: rule_ct += 1 alarm_ct += len(rule.alarm_names) self._notify_alarms( weather, rule.alarm_names, 'weather_alert') if rule_ct > 0: self._rule_log.info( 'Weather %s passed %s rule(s) and triggered %s alarm(s).', weather.name, rule_ct, alarm_ct) else: self._rule_log.info( 'Weather %s rejected by all rules.', weather.name)