diff --git a/.gitignore b/.gitignore index e87d91f4f..dc41b5b73 100644 --- a/.gitignore +++ b/.gitignore @@ -16,7 +16,7 @@ _build # pa runtime files *.pyc -cache/*.cache +cache/* # OS files .DS_Store diff --git a/PokeAlarm/Alarms/Discord/DiscordAlarm.py b/PokeAlarm/Alarms/Discord/DiscordAlarm.py index 10ab383aa..fd556bccc 100644 --- a/PokeAlarm/Alarms/Discord/DiscordAlarm.py +++ b/PokeAlarm/Alarms/Discord/DiscordAlarm.py @@ -28,9 +28,9 @@ class DiscordAlarm(Alarm): 'username': "", 'content': "", 'icon_url': get_image_url( - "regular/monsters/_.png"), + "regular/monsters/.png"), 'avatar_url': get_image_url( - "regular/monsters/_.png"), + "regular/monsters/.png"), 'title': "A wild has appeared!", 'url': "", 'body': "Available until <24h_time> ()." @@ -107,7 +107,8 @@ def __init__(self, settings, max_attempts, static_map_key): # Set Alert Parameters self.__monsters = self.create_alert_settings( - settings.pop('monsters', {}), self._defaults['monsters'], 'monsters') + settings.pop('monsters', {}), + self._defaults['monsters'], 'monsters') self.__stops = self.create_alert_settings( settings.pop('stops', {}), self._defaults['stops'], 'stops') self.__gyms = self.create_alert_settings( diff --git a/PokeAlarm/Alarms/FacebookPage/FacebookPageAlarm.py b/PokeAlarm/Alarms/FacebookPage/FacebookPageAlarm.py index ba977ddf2..a20b61088 100644 --- a/PokeAlarm/Alarms/FacebookPage/FacebookPageAlarm.py +++ b/PokeAlarm/Alarms/FacebookPage/FacebookPageAlarm.py @@ -28,7 +28,7 @@ class FacebookPageAlarm(Alarm): 'monsters': { 'message': "A wild has appeared!", 'image': get_image_url( - "regular/monsters/_.png"), + "regular/monsters/.png"), 'link': "", 'name': "", 'description': "Available until <24h_time> ().", diff --git a/PokeAlarm/Alarms/Slack/SlackAlarm.py b/PokeAlarm/Alarms/Slack/SlackAlarm.py index 436c2fc64..20372b211 100644 --- a/PokeAlarm/Alarms/Slack/SlackAlarm.py +++ b/PokeAlarm/Alarms/Slack/SlackAlarm.py @@ -28,7 +28,7 @@ class SlackAlarm(Alarm): 'monsters': { 'username': "", 'icon_url': get_image_url( - "regular/monsters/_.png"), + "regular/monsters/.png"), 'title': "A wild has appeared!", 'url': "", 'body': "Available until <24h_time> ()." diff --git a/PokeAlarm/Alarms/Telegram/TelegramAlarm.py b/PokeAlarm/Alarms/Telegram/TelegramAlarm.py index 25333aa8a..009ecad52 100644 --- a/PokeAlarm/Alarms/Telegram/TelegramAlarm.py +++ b/PokeAlarm/Alarms/Telegram/TelegramAlarm.py @@ -28,14 +28,15 @@ class TelegramAlarm(Alarm): Alert = namedtuple( "Alert", ['bot_token', 'chat_id', 'sticker', 'sticker_url', 'sticker_notify', 'message', 'message_notify', 'venue', - 'venue_notify', 'map', 'map_notify', 'max_attempts']) + 'venue_notify', 'map', 'map_notify', 'max_attempts', + 'web_preview']) _defaults = { # No touchy!!! Edit alarms.json! 'monsters': { 'message': "*A wild has appeared!*\n" "Available until <24h_time> ().", 'sticker_url': get_image_url( - "telegram/monsters/_.webp") + "telegram/monsters/.webp") }, 'stops': { 'message': "*Someone has placed a lure on a Pokestop!*\n" @@ -93,6 +94,8 @@ def __init__(self, settings): settings, 'map_notify', utils.parse_bool, False), 'max_attempts': self.pop_type( settings, 'max_attempts', int, 3), + 'web_preview': self.pop_type( + settings, 'web_preview', utils.parse_bool, False) } # Alert Settings @@ -152,7 +155,10 @@ def create_alert_settings(self, kind, settings, alert_defaults): settings, 'map_notify', utils.parse_bool, default['map_notify']), max_attempts=Alarm.pop_type( - settings, 'max_attempts', int, default['max_attempts']) + settings, 'max_attempts', int, default['max_attempts']), + web_preview=Alarm.pop_type( + settings, 'web_preview', utils.parse_bool, + default['web_preview']) ) # Reject leftover parameters @@ -190,7 +196,8 @@ def generic_alert(self, alert, dts): return # Don't send message or map # Send Message - self.send_message(bot_token, chat_id, replace(message, dts)) + self.send_message(bot_token, chat_id, replace(message, dts), + web_preview=alert.web_preview) # Send Map if alert.map: @@ -231,14 +238,14 @@ def send_sticker(self, token, chat_id, sticker_url, max_attempts) def send_message(self, token, chat_id, message, - max_attempts=3, notify=True): + max_attempts=3, notify=True, web_preview=False): args = { 'url': "https://api.telegram.org/bot{}/sendMessage".format(token), 'payload': { 'chat_id': chat_id, 'text': message, 'parse_mode': 'Markdown', - 'disable_web_page_preview': True, + 'disable_web_page_preview': not web_preview, 'disable_notification': not notify } } diff --git a/PokeAlarm/Alarms/Twitter/__init__.py b/PokeAlarm/Alarms/Twitter/__init__.py index 58a7dade4..1d4d9679c 100644 --- a/PokeAlarm/Alarms/Twitter/__init__.py +++ b/PokeAlarm/Alarms/Twitter/__init__.py @@ -1,8 +1,8 @@ -from TwitterAlarm import TwitterAlarm # noqa F401 - try: import twitter # noqa F401 except ImportError: from PokeAlarm.Utils import pip_install pip_install('twitter', '1.17.1') + +from TwitterAlarm import TwitterAlarm # noqa F401 diff --git a/PokeAlarm/Cache/Cache.py b/PokeAlarm/Cache/Cache.py index 3ce6e9c4c..5edd152b7 100644 --- a/PokeAlarm/Cache/Cache.py +++ b/PokeAlarm/Cache/Cache.py @@ -3,7 +3,8 @@ from datetime import datetime # 3rd Party Imports # Local Imports -from ..Utils import get_image_url +from PokeAlarm import Unknown +from PokeAlarm.Utils import get_image_url log = logging.getLogger('Cache') @@ -15,71 +16,67 @@ class Cache(object): be lost between run times if save has not been implemented correctly. """ - _default_gym_info = { - "name": "unknown", - "description": "unknown", - "url": get_image_url('icons/gym_0.png') - } + default_image_url = get_image_url("regular/gyms/0.png"), def __init__(self): """ Initializes a new cache object for storing data between events. """ - self._pokemon_hist = {} - self._pokestop_hist = {} - self._gym_team = {} - self._gym_info = {} + self._mon_hist = {} + self._stop_hist = {} self._egg_hist = {} self._raid_hist = {} self._weather_hist = {} - - def get_pokemon_expiration(self, pkmn_id): - """ Get the datetime that the pokemon expires.""" - return self._pokemon_hist.get(pkmn_id) - - def update_pokemon_expiration(self, pkmn_id, expiration): - """ Updates the datetime that the pokemon expires. """ - self._pokemon_hist[pkmn_id] = expiration - - def get_pokestop_expiration(self, stop_id): - """ Returns the datetime that the pokemon expires. """ - return self._pokestop_hist.get(stop_id) - - def update_pokestop_expiration(self, stop_id, expiration): - """ Updates the datetime that the pokestop expires. """ - self._pokestop_hist[stop_id] = expiration - - def get_gym_team(self, gym_id): - """ Get the current team that owns the gym. """ - return self._gym_team.get(gym_id, '?') - - def update_gym_team(self, gym_id, team): - """ Update the current team of the gym. """ - self._gym_team[gym_id] = team - - def get_gym_info(self, gym_id): - """ Gets the information about the gym. """ - return self._gym_info.get(gym_id, self._default_gym_info) - - def update_gym_info(self, gym_id, name, desc, url): - """ Updates the information about the gym. """ - if name != 'unknown': # Don't update if the gym info is missing - self._gym_info[gym_id] = { - "name": name, "description": desc, "url": url} - - def get_egg_expiration(self, gym_id): - """ Returns the datetime that the egg expires. """ - return self._egg_hist.get(gym_id) - - def update_egg_expiration(self, gym_id, expiration): - """ Updates the datetime that the egg expires. """ - self._egg_hist[gym_id] = expiration - - def get_raid_expiration(self, gym_id): - """ Returns the datetime that the raid expires. """ - return self._raid_hist.get(gym_id) - - def update_raid_expiration(self, gym_id, expiration): - """ Updates the datetime that the raid expires. """ - self._raid_hist[gym_id] = expiration + self._gym_team = {} + self._gym_name = {} + self._gym_desc = {} + self._gym_image = {} + + def monster_expiration(self, mon_id, expiration=None): + """ Update and return the datetime that a monster expires.""" + if expiration is not None: + self._mon_hist[mon_id] = expiration + return self._mon_hist.get(mon_id) + + def stop_expiration(self, stop_id, expiration=None): + """ Update and return the datetime that a stop expires.""" + if expiration is not None: + self._stop_hist[stop_id] = expiration + return self._stop_hist.get(stop_id) + + def egg_expiration(self, egg_id, expiration=None): + """ Update and return the datetime that an egg expires.""" + if expiration is not None: + self._egg_hist[egg_id] = expiration + return self._egg_hist.get(egg_id) + + def raid_expiration(self, raid_id, expiration=None): + """ Update and return the datetime that a raid expires.""" + if expiration is not None: + self._raid_hist[raid_id] = expiration + return self._raid_hist.get(raid_id) + + def gym_team(self, gym_id, team_id=Unknown.TINY): + """ Update and return the team_id of a gym. """ + if Unknown.is_not(team_id): + self._gym_team[gym_id] = team_id + return self._gym_team.get(gym_id, Unknown.TINY) + + def gym_name(self, gym_id, gym_name=Unknown.REGULAR): + """ Update and return the gym_name for a gym. """ + if Unknown.is_not(gym_name): + self._gym_name[gym_id] = gym_name + return self._gym_name.get(gym_id, Unknown.REGULAR) + + def gym_desc(self, gym_id, gym_desc=Unknown.REGULAR): + """ Update and return the gym_desc for a gym. """ + if Unknown.is_not(gym_desc): + self._gym_desc[gym_id] = gym_desc + return self._gym_desc.get(gym_id, Unknown.REGULAR) + + def gym_image(self, gym_id, gym_image=Unknown.REGULAR): + """ Update and return the gym_image for a gym. """ + if Unknown.is_not(gym_image): + self._gym_image[gym_id] = gym_image + return self._gym_image.get(gym_id, get_image_url('icons/gym_0.png')) def get_cell_weather(self, weather_cell_id): """ Returns the weather for the S2 cell. """ @@ -101,7 +98,7 @@ def _save(self): def _clean_hist(self): """ Clean expired objects to free up memory. """ for hist in ( - self._pokemon_hist, self._pokestop_hist, self._egg_hist, + self._mon_hist, self._stop_hist, self._egg_hist, self._raid_hist): old = [] now = datetime.utcnow() diff --git a/PokeAlarm/Cache/FileCache.py b/PokeAlarm/Cache/FileCache.py index 1638fe9b1..b258dfcba 100644 --- a/PokeAlarm/Cache/FileCache.py +++ b/PokeAlarm/Cache/FileCache.py @@ -21,42 +21,59 @@ def __init__(self, name): self._file = get_path(os.path.join("cache", "{}.cache".format(name))) log.debug("Checking for previous cache at {}".format(self._file)) + cache_folder = get_path("cache") + if not os.path.exists(cache_folder): + os.makedirs(cache_folder) if os.path.isfile(self._file): self._load() else: - with portalocker.Lock(self._file, mode="wb+") as f: - pickle.dump({}, f, protocol=pickle.HIGHEST_PROTOCOL) + self._save() def _load(self): - with portalocker.Lock(self._file, mode="rb") as f: - data = pickle.load(f) - self._pokemon_hist = data.get('pokemon_hist', {}) - self._pokestop_hist = data.get('pokestop_hist', {}) - self._gym_team = data.get('gym_team', {}) - self._gym_info = data.get('gym_info', {}) - self._egg_hist = data.get('egg_hist', {}) - self._raid_hist = data.get('raid_hist', {}) - self._weather_hist = data.get('weather_hist', {}) - log.debug("LOADED: \n {}".format(data)) + try: + with portalocker.Lock(self._file, mode="rb") as f: + data = pickle.load(f) + self._mon_hist = data.get('mon_hist', {}) + self._stop_hist = data.get('stop_hist', {}) + self._egg_hist = data.get('egg_hist', {}) + self._raid_hist = data.get('raid_hist', {}) + self._weather_hist = data.get('weather_hist', {}) + self._gym_team = data.get('gym_team', {}) + self._gym_name = data.get('gym_name', {}) + self._gym_desc = data.get('gym_desc', {}) + self._gym_image = data.get('gym_image', {}) + + log.debug("Cache loaded successfully.") + except Exception as e: + log.error("There was an error attempting to load the cache. The " + "old cache will be overwritten.") + log.error("{}: {}".format(type(e).__name__, e)) def _save(self): """ Export the data to a more permanent location. """ log.debug("Writing cache to file...") data = { - 'pokemon_hist': self._pokemon_hist, - 'pokestop_hist': self._pokestop_hist, - 'gym_team': self._gym_team, - 'gym_info': self._gym_info, + 'mon_hist': self._mon_hist, + 'stop_hist': self._stop_hist, 'egg_hist': self._egg_hist, 'raid_hist': self._raid_hist, - 'weather_hist': self._weather_hist + 'weather_hist': self._weather_hist, + 'gym_team': self._gym_team, + 'gym_name': self._gym_name, + 'gym_desc': self._gym_desc, + 'gym_image': self._gym_image } - log.debug(self._pokestop_hist) - log.debug("SAVED: {}".format(data)) try: - with portalocker.Lock(self._file, timeout=5, mode="wb+") as f: - pickle.dump(data, f, protocol=pickle.HIGHEST_PROTOCOL) + # Write to temporary file and then rename + temp = self._file + ".new" + with portalocker.Lock(self._file + ".lock", timeout=5, mode="wb+"): + with portalocker.Lock(temp, timeout=5, mode="wb+") as f: + pickle.dump(data, f, protocol=pickle.HIGHEST_PROTOCOL) + if os.path.exists(self._file): + os.remove(self._file) # Required for Windows + os.rename(temp, self._file) + log.debug("Cache saved successfully.") except Exception as e: log.error("Encountered error while saving cache: " + "{}: {}".format(type(e).__name__, e)) - log.debug("Stack trace: \n {}".format(traceback.format_exc())) + log.error("Stack trace: \n {}".format(traceback.format_exc())) diff --git a/PokeAlarm/Events/EggEvent.py b/PokeAlarm/Events/EggEvent.py index 43881e20d..53eb2d0cf 100644 --- a/PokeAlarm/Events/EggEvent.py +++ b/PokeAlarm/Events/EggEvent.py @@ -3,7 +3,8 @@ # 3rd Party Imports # Local Imports from PokeAlarm.Utils import get_time_as_str, get_seconds_remaining, \ - get_gmaps_link, get_applemaps_link, get_dist_as_str, get_weather_emoji + get_gmaps_link, get_applemaps_link, get_pokego2_link, get_dist_as_str, \ + get_weather_emoji from . import BaseEvent from PokeAlarm import Unknown @@ -44,14 +45,14 @@ def __init__(self, data): str, data.get('description'), Unknown.REGULAR).strip() self.gym_image = check_for_none( str, data.get('url'), Unknown.REGULAR) - self.gym_sponsor = check_for_none( - int, data.get('sponsor'), Unknown.SMALL) - self.gym_park = check_for_none( + self.sponsor_id = check_for_none( + int, data.get('sponsor'), Unknown.TINY) + self.park = check_for_none( str, data.get('park'), Unknown.REGULAR) # Gym Team (this is only available from cache) self.current_team_id = check_for_none( - int, data.get('team'), Unknown.TINY) + int, data.get('team_id', data.get('team')), Unknown.TINY) self.name = self.gym_id self.geofence = Unknown.REGULAR @@ -99,8 +100,11 @@ def generate_dts(self, locale, timezone, units): 'gym_name': self.gym_name, 'gym_description': self.gym_description, 'gym_image': self.gym_image, - 'gym_sponsor': self.gym_sponsor, - 'gym_park': self.gym_park, + 'sponsor_id': self.sponsor_id, + 'sponsored': + self.sponsor_id > 0 + if Unknown.is_not(self.sponsor_id) else Unknown.REGULAR, + 'park': self.park, 'team_id': self.current_team_id, 'team_name': locale.get_team_name(self.current_team_id), 'team_leader': locale.get_leader_name(self.current_team_id) diff --git a/PokeAlarm/Events/GymEvent.py b/PokeAlarm/Events/GymEvent.py index f826478c7..966f61d0e 100644 --- a/PokeAlarm/Events/GymEvent.py +++ b/PokeAlarm/Events/GymEvent.py @@ -1,7 +1,8 @@ # Standard Library Imports # 3rd Party Imports # Local Imports -from PokeAlarm.Utils import get_gmaps_link, get_applemaps_link, get_dist_as_str +from PokeAlarm.Utils import get_gmaps_link, get_applemaps_link, get_pokego2_link, \ + get_dist_as_str from . import BaseEvent from PokeAlarm import Unknown @@ -65,6 +66,7 @@ def generate_dts(self, locale, timezone, units): 'direction': self.direction, 'gmaps': get_gmaps_link(self.lat, self.lng), 'applemaps': get_applemaps_link(self.lat, self.lng), + 'pokego2': get_pokego2_link(self.lat, self.lng, self.gym_name), 'geofence': self.geofence, # Team Info diff --git a/PokeAlarm/Events/MonEvent.py b/PokeAlarm/Events/MonEvent.py index ebab3c090..d03f4b667 100644 --- a/PokeAlarm/Events/MonEvent.py +++ b/PokeAlarm/Events/MonEvent.py @@ -5,8 +5,8 @@ from PokeAlarm import Unknown from PokeAlarm.Utilities import MonUtils from PokeAlarm.Utils import ( - get_gmaps_link, get_move_damage, get_move_dps, - get_move_duration, get_move_energy, get_pokemon_size, + get_gmaps_link, get_pokego2_link, get_move_type, get_move_damage, + get_move_dps, get_move_duration, get_move_energy, get_pokemon_size, get_applemaps_link, get_time_as_str, get_seconds_remaining, get_base_types, get_dist_as_str, get_weather_emoji, get_type_emoji) @@ -44,12 +44,14 @@ def __init__(self, data): self.weather_id = check_for_none( int, data.get('weather'), Unknown.TINY) self.boosted_weather_id = check_for_none( - int, data.get('boosted_weather'), Unknown.TINY) + int, data.get('boosted_weather') + or data.get('weather_boosted_condition'), 0) # Encounter Stats self.mon_lvl = check_for_none( int, data.get('pokemon_level'), Unknown.TINY) self.cp = check_for_none(int, data.get('cp'), Unknown.TINY) + # IVs self.atk_iv = check_for_none( int, data.get('individual_attack'), Unknown.TINY) @@ -62,28 +64,42 @@ def __init__(self, data): 100 * (self.atk_iv + self.def_iv + self.sta_iv) / float(45) else: self.iv = Unknown.SMALL - # Form - self.form_id = check_for_none(int, data.get('form'), 0) # Quick Move - self.quick_move_id = check_for_none( + self.quick_id = check_for_none( int, data.get('move_1'), Unknown.TINY) - self.quick_damage = get_move_damage(self.quick_move_id) - self.quick_dps = get_move_dps(self.quick_move_id) - self.quick_duration = get_move_duration(self.quick_move_id) - self.quick_energy = get_move_energy(self.quick_move_id) + self.quick_type = get_move_type(self.quick_id) + self.quick_damage = get_move_damage(self.quick_id) + self.quick_dps = get_move_dps(self.quick_id) + self.quick_duration = get_move_duration(self.quick_id) + self.quick_energy = get_move_energy(self.quick_id) + # Charge Move - self.charge_move_id = check_for_none( + self.charge_id = check_for_none( int, data.get('move_2'), Unknown.TINY) - self.charge_damage = get_move_damage(self.charge_move_id) - self.charge_dps = get_move_dps(self.charge_move_id) - self.charge_duration = get_move_duration(self.quick_move_id) - self.charge_energy = get_move_energy(self.charge_move_id) + self.charge_type = get_move_type(self.charge_id) + self.charge_damage = get_move_damage(self.charge_id) + self.charge_dps = get_move_dps(self.charge_id) + self.charge_duration = get_move_duration(self.charge_id) + self.charge_energy = get_move_energy(self.charge_id) + + # Catch Probs + self.base_catch = check_for_none( + float, data.get('base_catch'), Unknown.TINY) + self.great_catch = check_for_none( + float, data.get('great_catch'), Unknown.TINY) + self.ultra_catch = check_for_none( + float, data.get('ultra_catch'), Unknown.TINY) + + # Attack Rating + self.atk_grade = check_for_none( + str, data.get('atk_grade'), Unknown.TINY) + self.def_grade = check_for_none( + str, data.get('def_grade'), Unknown.TINY) # Cosmetic self.gender = MonUtils.get_gender_sym( check_for_none(int, data.get('gender'), Unknown.TINY)) - self.height = check_for_none(float, data.get('height'), Unknown.SMALL) self.weight = check_for_none(float, data.get('weight'), Unknown.SMALL) if Unknown.is_not(self.height, self.weight): @@ -93,6 +109,12 @@ def __init__(self, data): self.size_id = Unknown.SMALL self.types = get_base_types(self.monster_id) + # Form + self.form_id = check_for_none(int, data.get('form'), 0) + + # Costume + self.costume_id = check_for_none(int, data.get('costume'), 0) + # Correct this later self.name = self.monster_id self.geofence = Unknown.REGULAR @@ -102,6 +124,12 @@ def generate_dts(self, locale, timezone, units): """ Return a dict with all the DTS for this event. """ time = get_time_as_str(self.disappear_time, timezone) form_name = locale.get_form_name(self.monster_id, self.form_id) + form_id_3 = "{:03d}".format(self.form_id) + mon_id_3 = "{:03}".format(self.monster_id) + form_for_image = '000' if self.monster_id == 132 else form_id_3 + costume_name = locale.get_costume_name( + self.monster_id, self.costume_id) + weather_name = locale.get_weather_name(self.weather_id) boosted_weather_name = locale.get_weather_name(self.boosted_weather_id) @@ -114,7 +142,7 @@ def generate_dts(self, locale, timezone, units): 'encounter_id': self.enc_id, 'mon_name': locale.get_pokemon_name(self.monster_id), 'mon_id': self.monster_id, - 'mon_id_3': "{:03}".format(self.monster_id), + 'mon_id_3': mon_id_3, # Time Remaining 'time_left': time[0], @@ -137,6 +165,8 @@ def generate_dts(self, locale, timezone, units): 'direction': self.direction, 'gmaps': get_gmaps_link(self.lat, self.lng), 'applemaps': get_applemaps_link(self.lat, self.lng), + 'pokego2': get_pokego2_link( + self.lat, self.lng, locale.get_pokemon_name(self.monster_id)), 'geofence': self.geofence, # Weather @@ -193,19 +223,31 @@ def generate_dts(self, locale, timezone, units): 'form': form_name, 'form_or_empty': Unknown.or_empty(form_name), 'form_id': self.form_id, - 'form_id_3': "{:03d}".format(self.form_id), + 'form_id_3': form_id_3, + + # Costume + 'costume': costume_name, + 'costume_or_empty': Unknown.or_empty(costume_name), + 'costume_id': self.costume_id, + 'costume_id_3': "{:03d}".format(self.costume_id), # Quick Move - 'quick_move': locale.get_move_name(self.quick_move_id), - 'quick_id': self.quick_move_id, + 'quick_move': locale.get_move_name(self.quick_id), + 'quick_id': self.quick_id, + 'quick_type_id': self.quick_type, + 'quick_type': locale.get_type_name(self.quick_type), + 'quick_type_emoji': get_type_emoji(self.quick_type), 'quick_damage': self.quick_damage, 'quick_dps': self.quick_dps, 'quick_duration': self.quick_duration, 'quick_energy': self.quick_energy, # Charge Move - 'charge_move': locale.get_move_name(self.charge_move_id), - 'charge_id': self.charge_move_id, + 'charge_move': locale.get_move_name(self.charge_id), + 'charge_id': self.charge_id, + 'charge_type_id': self.charge_type, + 'charge_type': locale.get_type_name(self.charge_type), + 'charge_type_emoji': get_type_emoji(self.charge_type), 'charge_damage': self.charge_damage, 'charge_dps': self.charge_dps, 'charge_duration': self.charge_duration, @@ -213,16 +255,77 @@ def generate_dts(self, locale, timezone, units): # Cosmetic 'gender': self.gender, - 'height': self.height, - 'weight': self.weight, + 'height_0': ( + "{:.0f}".format(self.height) if Unknown.is_not(self.height) + else Unknown.TINY), + 'height': ( + "{:.1f}".format(self.height) if Unknown.is_not(self.height) + else Unknown.SMALL), + 'height_2': ( + "{:.2f}".format(self.height) if Unknown.is_not(self.height) + else Unknown.SMALL), + 'weight_0': ( + "{:.0f}".format(self.weight) if Unknown.is_not(self.weight) + else Unknown.TINY), + 'weight': ( + "{:.1f}".format(self.weight) if Unknown.is_not(self.weight) + else Unknown.SMALL), + 'weight_2': ( + "{:.2f}".format(self.weight) if Unknown.is_not(self.weight) + else Unknown.SMALL), 'size': locale.get_size_name(self.size_id), + # Attack rating + 'atk_grade': ( + Unknown.or_empty(self.atk_grade, Unknown.TINY)), + 'def_grade': ( + Unknown.or_empty(self.def_grade, Unknown.TINY)), + + # Catch Prob + 'base_catch_0': ( + "{:.0f}".format(self.base_catch * 100) + if Unknown.is_not(self.base_catch) + else Unknown.TINY), + 'base_catch': ( + "{:.1f}".format(self.base_catch * 100) + if Unknown.is_not(self.base_catch) + else Unknown.SMALL), + 'base_catch_2': ( + "{:.2f}".format(self.base_catch * 100) + if Unknown.is_not(self.base_catch) + else Unknown.SMALL), + 'great_catch_0': ( + "{:.0f}".format(self.great_catch * 100) + if Unknown.is_not(self.great_catch) + else Unknown.TINY), + 'great_catch': ( + "{:.1f}".format(self.great_catch * 100) + if Unknown.is_not(self.great_catch) + else Unknown.SMALL), + 'great_catch_2': ( + "{:.2f}".format(self.great_catch * 100) + if Unknown.is_not(self.great_catch) + else Unknown.SMALL), + 'ultra_catch_0': ( + "{:.0f}".format(self.ultra_catch * 100) + if Unknown.is_not(self.ultra_catch) + else Unknown.TINY), + 'ultra_catch': ( + "{:.1f}".format(self.ultra_catch * 100) + if Unknown.is_not(self.ultra_catch) + else Unknown.SMALL), + 'ultra_catch_2': ( + "{:.2f}".format(self.ultra_catch * 100) + if Unknown.is_not(self.ultra_catch) + else Unknown.SMALL), + # Misc 'big_karp': ( 'big' if self.monster_id == 129 and Unknown.is_not(self.weight) and self.weight >= 13.13 else ''), 'tiny_rat': ( 'tiny' if self.monster_id == 19 and Unknown.is_not(self.weight) - and self.weight <= 2.41 else '') + and self.weight <= 2.41 else ''), + 'image_suffix': mon_id_3 + '_' + form_for_image }) return dts diff --git a/PokeAlarm/Events/RaidEvent.py b/PokeAlarm/Events/RaidEvent.py index 80d21a18a..52d0aa629 100644 --- a/PokeAlarm/Events/RaidEvent.py +++ b/PokeAlarm/Events/RaidEvent.py @@ -5,8 +5,8 @@ from PokeAlarm import Unknown from . import BaseEvent from PokeAlarm.Utils import get_gmaps_link, get_applemaps_link, \ - get_time_as_str, get_move_damage, get_move_dps, \ - get_move_duration, get_move_energy, get_seconds_remaining, \ + get_pokego2_link, get_time_as_str, get_move_type, get_move_damage, \ + get_move_dps, get_move_duration, get_move_energy, get_seconds_remaining, \ get_dist_as_str, get_pokemon_cp_range, is_weather_boosted, \ get_base_types, get_weather_emoji, get_type_emoji @@ -32,27 +32,45 @@ def __init__(self, data): self.lng = float(data['longitude']) self.distance = Unknown.SMALL # Completed by Manager self.direction = Unknown.TINY # Completed by Manager - self.weather_id = check_for_none( - int, data.get('weather'), Unknown.TINY) # Monster Info self.raid_lvl = int(data['level']) self.mon_id = int(data['pokemon_id']) self.cp = int(data['cp']) self.types = get_base_types(self.mon_id) + self.boss_level = 20 + + # Form + self.form_id = check_for_none(int, data.get('form'), 0) + + # Costume + self.costume_id = check_for_none(int, data.get('costume'), 0) + + # Weather Info + self.weather_id = check_for_none( + int, data.get('weather'), Unknown.TINY) + self.boosted_weather_id = \ + 0 if Unknown.is_not(self.weather_id) else Unknown.TINY + if is_weather_boosted(self.mon_id, self.weather_id): + self.boosted_weather_id = self.weather_id + self.boss_level = 25 # Quick Move - self.quick_id = check_for_none(int, data.get('move_1'), Unknown.TINY) + self.quick_id = check_for_none( + int, data.get('move_1'), Unknown.TINY) + self.quick_type = get_move_type(self.quick_id) self.quick_damage = get_move_damage(self.quick_id) self.quick_dps = get_move_dps(self.quick_id) self.quick_duration = get_move_duration(self.quick_id) self.quick_energy = get_move_energy(self.quick_id) # Charge Move - self.charge_id = check_for_none(int, data.get('move_2'), Unknown.TINY) + self.charge_id = check_for_none( + int, data.get('move_2'), Unknown.TINY) + self.charge_type = get_move_type(self.charge_id) self.charge_damage = get_move_damage(self.charge_id) self.charge_dps = get_move_dps(self.charge_id) - self.charge_duration = get_move_duration(self.quick_id) + self.charge_duration = get_move_duration(self.charge_id) self.charge_energy = get_move_energy(self.charge_id) # Gym Details (currently only sent from Monocle) @@ -62,14 +80,14 @@ def __init__(self, data): str, data.get('description'), Unknown.REGULAR).strip() self.gym_image = check_for_none( str, data.get('url'), Unknown.REGULAR) - self.gym_sponsor = check_for_none( - int, data.get('sponsor'), Unknown.SMALL) - self.gym_park = check_for_none( + self.sponsor_id = check_for_none( + int, data.get('sponsor'), Unknown.TINY) + self.park = check_for_none( str, data.get('park'), Unknown.REGULAR) # Gym Team (this is only available from cache) self.current_team_id = check_for_none( - int, int(data.get('team')), Unknown.TINY) + int, data.get('team_id', data.get('team')), Unknown.TINY) self.name = self.gym_id self.geofence = Unknown.REGULAR @@ -80,19 +98,17 @@ def generate_dts(self, locale, timezone, units): raid_end_time = get_time_as_str(self.raid_end, timezone) dts = self.custom_dts.copy() - boss_level = 20 - boosted_weather_id = \ - 0 if Unknown.is_not(self.weather_id) else Unknown.TINY, - if is_weather_boosted(self.mon_id, self.weather_id): - boss_level = 25 - boosted_weather_id = self.weather_id - boosted_weather_name = locale.get_weather_name(boosted_weather_id) + form_name = locale.get_form_name(self.mon_id, self.form_id) + costume_name = locale.get_costume_name( + self.mon_id, self.costume_id) + + boosted_weather_name = locale.get_weather_name(self.boosted_weather_id) weather_name = locale.get_weather_name(self.weather_id) type1 = locale.get_type_name(self.types[0]) type2 = locale.get_type_name(self.types[1]) - cp_range = get_pokemon_cp_range(self.mon_id, boss_level) + cp_range = get_pokemon_cp_range(self.mon_id, self.boss_level) dts.update({ # Identification 'gym_id': self.gym_id, @@ -118,6 +134,18 @@ def generate_dts(self, locale, timezone, units): get_type_emoji(self.types[1])) if Unknown.is_not(type2) else get_type_emoji(self.types[0])), + # Form + 'form': form_name, + 'form_or_empty': Unknown.or_empty(form_name), + 'form_id': self.form_id, + 'form_id_3': "{:03d}".format(self.form_id), + + # Costume + 'costume': costume_name, + 'costume_or_empty': Unknown.or_empty(costume_name), + 'costume_id': self.costume_id, + 'costume_id_3': "{:03d}".format(self.costume_id), + # Location 'lat': self.lat, 'lng': self.lng, @@ -129,19 +157,23 @@ def generate_dts(self, locale, timezone, units): 'direction': self.direction, 'gmaps': get_gmaps_link(self.lat, self.lng), 'applemaps': get_applemaps_link(self.lat, self.lng), + 'pokego2': get_pokego2_link(self.lat, self.lng, self.gym_name), 'geofence': self.geofence, + + # Weather 'weather_id': self.weather_id, 'weather': weather_name, 'weather_or_empty': Unknown.or_empty(weather_name), 'weather_emoji': get_weather_emoji(self.weather_id), - 'boosted_weather_id': boosted_weather_id, + 'boosted_weather_id': self.boosted_weather_id, 'boosted_weather': boosted_weather_name, 'boosted_weather_or_empty': ( - '' if boosted_weather_id == 0 + '' if self.boosted_weather_id == 0 else Unknown.or_empty(boosted_weather_name)), - 'boosted_weather_emoji': get_weather_emoji(boosted_weather_id), + 'boosted_weather_emoji': get_weather_emoji( + self.boosted_weather_id), 'boosted_or_empty': - locale.get_boosted_text() if boss_level == 25 else '', + locale.get_boosted_text() if self.boss_level == 25 else '', # Raid Info 'raid_lvl': self.raid_lvl, @@ -153,6 +185,9 @@ def generate_dts(self, locale, timezone, units): # Quick Move 'quick_move': locale.get_move_name(self.quick_id), 'quick_id': self.quick_id, + 'quick_type_id': self.quick_type, + 'quick_type': locale.get_type_name(self.quick_type), + 'quick_type_emoji': get_type_emoji(self.quick_type), 'quick_damage': self.quick_damage, 'quick_dps': self.quick_dps, 'quick_duration': self.quick_duration, @@ -161,6 +196,9 @@ def generate_dts(self, locale, timezone, units): # Charge Move 'charge_move': locale.get_move_name(self.charge_id), 'charge_id': self.charge_id, + 'charge_type_id': self.charge_type, + 'charge_type': locale.get_type_name(self.charge_type), + 'charge_type_emoji': get_type_emoji(self.charge_type), 'charge_damage': self.charge_damage, 'charge_dps': self.charge_dps, 'charge_duration': self.charge_duration, @@ -175,8 +213,11 @@ def generate_dts(self, locale, timezone, units): 'gym_name': self.gym_name, 'gym_description': self.gym_description, 'gym_image': self.gym_image, - 'gym_sponsor': self.gym_sponsor, - 'gym_park': self.gym_park, + 'sponsor_id': self.sponsor_id, + 'sponsored': + self.sponsor_id > 0 if Unknown.is_not(self.sponsor_id) + else Unknown.REGULAR, + 'park': self.park, 'team_id': self.current_team_id, 'team_name': locale.get_team_name(self.current_team_id), 'team_leader': locale.get_leader_name(self.current_team_id) diff --git a/PokeAlarm/Events/StopEvent.py b/PokeAlarm/Events/StopEvent.py index 425a94c44..ae7380ce1 100644 --- a/PokeAlarm/Events/StopEvent.py +++ b/PokeAlarm/Events/StopEvent.py @@ -5,7 +5,7 @@ from PokeAlarm import Unknown from . import BaseEvent from PokeAlarm.Utils import get_gmaps_link, get_applemaps_link, \ - get_time_as_str, get_seconds_remaining, get_dist_as_str + get_pokego2_link, get_time_as_str, get_seconds_remaining, get_dist_as_str class StopEvent(BaseEvent): @@ -19,8 +19,11 @@ def __init__(self, data): self.stop_id = data['pokestop_id'] # Time left - self.expiration = datetime.utcfromtimestamp(data['lure_expiration']) - self.time_left = get_seconds_remaining(self.expiration) + self.expiration = data['lure_expiration'] + self.time_left = None + if self.expiration is not None: + self.expiration = datetime.utcfromtimestamp(self.expiration) + self.time_left = get_seconds_remaining(self.expiration) # Location self.lat = float(data['latitude']) @@ -37,7 +40,7 @@ def __init__(self, data): def generate_dts(self, locale, timezone, units): """ Return a dict with all the DTS for this event. """ - time = get_time_as_str(self.expiration) + time = get_time_as_str(self.expiration, timezone) dts = self.custom_dts.copy() dts.update({ # Identification @@ -59,6 +62,7 @@ def generate_dts(self, locale, timezone, units): 'direction': self.direction, 'gmaps': get_gmaps_link(self.lat, self.lng), 'applemaps': get_applemaps_link(self.lat, self.lng), + 'pokego2': get_pokego2_link(self.lat, self.lng, self.stop_id), 'geofence': self.geofence }) return dts diff --git a/PokeAlarm/Events/WeatherEvent.py b/PokeAlarm/Events/WeatherEvent.py index 9711b9e8e..cab1fb88d 100644 --- a/PokeAlarm/Events/WeatherEvent.py +++ b/PokeAlarm/Events/WeatherEvent.py @@ -4,7 +4,7 @@ # Local Imports from PokeAlarm import Unknown from . import BaseEvent -from PokeAlarm.Utils import get_time_as_str +from PokeAlarm.Utils import get_time_as_str, get_weather_emoji class WeatherEvent(BaseEvent): @@ -40,7 +40,7 @@ def __init__(self, data): self.geofence = Unknown.REGULAR self.custom_dts = {} - def generate_dts(self, locale): + def generate_dts(self, locale, timezone, units): """ Return a dict with all the DTS for this event. """ time_changed = get_time_as_str(self.time_changed) dts = self.custom_dts.copy() @@ -61,6 +61,7 @@ def generate_dts(self, locale): # Weather info 'condition': self.condition, 'weather': locale.get_weather_name(self.condition), + 'weather_emoji': get_weather_emoji(self.condition), 'alert_severity': self.alert_severity, 'warn': self.warn, 'day': self.day diff --git a/PokeAlarm/Filters/BaseFilter.py b/PokeAlarm/Filters/BaseFilter.py index 91ebbe304..ca19d4ca3 100644 --- a/PokeAlarm/Filters/BaseFilter.py +++ b/PokeAlarm/Filters/BaseFilter.py @@ -79,6 +79,25 @@ def parse_as_type(kind, param_name, data): 'Unable to interpret the value "{}" as a '.format(value) + 'valid {} for parameter {}.", '.format(kind, param_name)) + @staticmethod + def parse_as_list(value_type, param_name, data): + """ Parse and convert a list of values into a list.""" + # Validate Input + values = data.pop(param_name, None) + if values is None or len(values) == 0: + return None + if not isinstance(values, list): + raise ValueError( + 'The "{0}" parameter must formatted as a list containing ' + 'different values. Example: "{0}": ' + '[ "value1", "value2", "value3" ] '.format(param_name)) + # Generate Allowed Set + allowed = [] + for value in values: + # Value type should throw the correct error + allowed.append(value_type(value)) + return allowed + @staticmethod def parse_as_set(value_type, param_name, data): """ Parse and convert a list of values into a set.""" @@ -131,6 +150,7 @@ def __call__(self, filtr, event): if Unknown.is_(value): return Unknown.TINY # Cannot check - missing attribute result = self._eval_func(self._limit, value) # compare value to limit + if result is False: # Log rejection filtr.reject(event, "{} incorrect ({} to {})".format( self._attr_name, value, self._limit)) diff --git a/PokeAlarm/Filters/EggFilter.py b/PokeAlarm/Filters/EggFilter.py index 15c1d4ddc..a61baeed2 100644 --- a/PokeAlarm/Filters/EggFilter.py +++ b/PokeAlarm/Filters/EggFilter.py @@ -1,6 +1,5 @@ # Standard Library Imports import operator -import re # 3rd Party Imports # Local Imports from . import BaseFilter @@ -46,18 +45,22 @@ def __init__(self, name, data): event_attribute='gym_name', eval_func=GymUtils.match_regex_dict, limit=BaseFilter.parse_as_set( GymUtils.create_regex, 'gym_name_contains', data)) + self.gym_name_excludes = self.evaluate_attribute( # f.gn no-match e.gn + event_attribute='gym_name', + eval_func=GymUtils.not_match_regex_dict, + limit=BaseFilter.parse_as_set( + GymUtils.create_regex, 'gym_name_excludes', data)) # Gym sponsor - self.gym_sponsor_index_contains = self.evaluate_attribute( - event_attribute='gym_sponsor', eval_func=GymUtils.match_regex_dict, - limit=BaseFilter.parse_as_set( - re.compile, 'gym_sponsor_index_contains', data)) + self.sponsored = self.evaluate_attribute( + event_attribute='sponsor_id', eval_func=lambda y, x: (x > 0) == y, + limit=BaseFilter.parse_as_type(bool, 'sponsored', data)) # Gym park - self.gym_park_contains = self.evaluate_attribute( # f.gp matches e.gp - event_attribute='gym_park', eval_func=GymUtils.match_regex_dict, + self.park_contains = self.evaluate_attribute( # f.gp matches e.gp + event_attribute='park', eval_func=GymUtils.match_regex_dict, limit=BaseFilter.parse_as_set( - re.compile, 'gym_park_contains', data)) + GymUtils.create_regex, 'park_contains', data)) # Team Info self.old_team = self.evaluate_attribute( # f.ctis contains m.cti @@ -66,7 +69,7 @@ def __init__(self, name, data): GymUtils.get_team_id, 'current_teams', data)) # Geofences - self.geofences = BaseFilter.parse_as_set(str, 'geofences', data) + self.geofences = BaseFilter.parse_as_list(str, 'geofences', data) # Custom DTS self.custom_dts = BaseFilter.parse_as_dict( @@ -99,15 +102,18 @@ def to_dict(self): # Gym Name if self.gym_name_contains is not None: - settings['gym_name_matches'] = self.gym_name_contains + settings['gym_name_contains'] = self.gym_name_contains + + if self.gym_name_excludes is not None: + settings['gym_name_excludes'] = self.gym_name_excludes # Gym Sponsor - if self.gym_sponsor_index_contains is not None: - settings['gym_sponsor_matches'] = self.gym_sponsor_index_contains + if self.sponsored is not None: + settings['sponsored'] = self.sponsored # Gym Park - if self.gym_park_contains is not None: - settings['gym_park_matches'] = self.gym_park_contains + if self.park_contains is not None: + settings['park_contains'] = self.park_contains # Geofences if self.geofences is not None: @@ -115,6 +121,6 @@ def to_dict(self): # Missing Info if self.is_missing_info is not None: - settings['missing_info'] = self.is_missing_info + settings['is_missing_info'] = self.is_missing_info return settings diff --git a/PokeAlarm/Filters/GymFilter.py b/PokeAlarm/Filters/GymFilter.py index 8f94226c0..e95dee8b8 100644 --- a/PokeAlarm/Filters/GymFilter.py +++ b/PokeAlarm/Filters/GymFilter.py @@ -36,6 +36,11 @@ def __init__(self, name, data): event_attribute='gym_name', eval_func=GymUtils.match_regex_dict, limit=BaseFilter.parse_as_set( GymUtils.create_regex, 'gym_name_contains', data)) + self.gym_name_excludes = self.evaluate_attribute( # f.gn no-match e.gn + event_attribute='gym_name', + eval_func=GymUtils.not_match_regex_dict, + limit=BaseFilter.parse_as_set( + GymUtils.create_regex, 'gym_name_excludes', data)) # Slots Available self.min_slots = self.evaluate_attribute( @@ -48,7 +53,7 @@ def __init__(self, name, data): limit=BaseFilter.parse_as_type(int, 'max_slots', data)) # Geofences - self.geofences = BaseFilter.parse_as_set(str, 'geofences', data) + self.geofences = BaseFilter.parse_as_list(str, 'geofences', data) # Custom DTS self.custom_dts = BaseFilter.parse_as_dict( diff --git a/PokeAlarm/Filters/MonFilter.py b/PokeAlarm/Filters/MonFilter.py index 9635b7b92..228e35fb1 100644 --- a/PokeAlarm/Filters/MonFilter.py +++ b/PokeAlarm/Filters/MonFilter.py @@ -14,12 +14,19 @@ def __init__(self, name, data): """ Initializes base parameters for a filter. """ super(MonFilter, self).__init__(name) - # Monster ID - f.monster_ids in m.monster_id + # Monster ID - f.monster_ids contains m.monster_id self.monster_ids = self.evaluate_attribute( # event_attribute='monster_id', eval_func=operator.contains, limit=BaseFilter.parse_as_set( MonUtils.get_monster_id, 'monsters', data)) + # Exclude Monsters - f.monster_ids not contains m.ex_mon_id + self.exclude_monster_ids = self.evaluate_attribute( # + event_attribute='monster_id', + eval_func=lambda d, v: not operator.contains(d, v), + limit=BaseFilter.parse_as_set( + MonUtils.get_monster_id, 'monsters_exclude', data)) + # Distance self.min_dist = self.evaluate_attribute( # f.min_dist <= m.distance event_attribute='distance', eval_func=operator.le, @@ -85,15 +92,20 @@ def __init__(self, name, data): self.forms = self.evaluate_attribute( # f.forms in m.form_id event_attribute='form_id', eval_func=operator.contains, limit=BaseFilter.parse_as_set(int, 'form_ids', data)) + # Costume TODO: names + self.costumes = self.evaluate_attribute( # f.costumes in m.costume_id + event_attribute='costume_id', eval_func=operator.contains, + limit=BaseFilter.parse_as_set(int, 'costume_ids', data)) # Quick Move self.quick_moves = self.evaluate_attribute( # f.q_ms contains m.q_m - event_attribute='quick_move_id', eval_func=operator.contains, + event_attribute='quick_id', eval_func=operator.contains, limit=BaseFilter.parse_as_set( MonUtils.get_move_id, 'quick_moves', data)) + # Charge Move self.charge_moves = self.evaluate_attribute( # f.c_ms contains m.c_m - event_attribute='charge_move_id', eval_func=operator.contains, + event_attribute='charge_id', eval_func=operator.contains, limit=BaseFilter.parse_as_set( MonUtils.get_move_id, 'charge_moves', data)) @@ -129,7 +141,7 @@ def __init__(self, name, data): limit=BaseFilter.parse_as_set(get_weather_id, 'weather', data)) # Geofences - self.geofences = BaseFilter.parse_as_set(str, 'geofences', data) + self.geofences = BaseFilter.parse_as_list(str, 'geofences', data) # Custom DTS self.custom_dts = BaseFilter.parse_as_dict( @@ -185,6 +197,9 @@ def to_dict(self): # Form if self.forms is not None: settings['forms'] = self.forms + # Costume + if self.forms is not None: + settings['costumes'] = self.costumes # Quick Move if self.quick_moves is not None: diff --git a/PokeAlarm/Filters/RaidFilter.py b/PokeAlarm/Filters/RaidFilter.py index 612c4a54d..a1ff9755f 100644 --- a/PokeAlarm/Filters/RaidFilter.py +++ b/PokeAlarm/Filters/RaidFilter.py @@ -1,6 +1,5 @@ # Standard Library Imports import operator -import re # 3rd Party Imports # Local Imports from . import BaseFilter @@ -22,6 +21,13 @@ def __init__(self, name, data): limit=BaseFilter.parse_as_set( MonUtils.get_monster_id, 'monsters', data)) + # Exclude Monster ID - f.monster_ids not contains r.ex_mon_id + self.exclude_mon_ids = self.evaluate_attribute( # + event_attribute='mon_id', + eval_func=lambda d, v: not operator.contains(d, v), + limit=BaseFilter.parse_as_set( + MonUtils.get_monster_id, 'monsters_exclude', data)) + # Distance self.min_dist = self.evaluate_attribute( # f.min_dist <= r.distance event_attribute='distance', eval_func=operator.le, @@ -61,6 +67,7 @@ def __init__(self, name, data): event_attribute='quick_id', eval_func=operator.contains, limit=BaseFilter.parse_as_set( MonUtils.get_move_id, 'quick_moves', data)) + # Charge Move self.charge_moves = self.evaluate_attribute( # f.c_ms contains r.c_m event_attribute='charge_id', eval_func=operator.contains, @@ -72,18 +79,22 @@ def __init__(self, name, data): event_attribute='gym_name', eval_func=GymUtils.match_regex_dict, limit=BaseFilter.parse_as_set( GymUtils.create_regex, 'gym_name_contains', data)) + self.gym_name_excludes = self.evaluate_attribute( # f.gn no-match e.gn + event_attribute='gym_name', + eval_func=GymUtils.not_match_regex_dict, + limit=BaseFilter.parse_as_set( + GymUtils.create_regex, 'gym_name_excludes', data)) # Gym sponsor - self.gym_sponsor_index_contains = self.evaluate_attribute( - event_attribute='gym_sponsor', eval_func=GymUtils.match_regex_dict, - limit=BaseFilter.parse_as_set( - re.compile, 'gym_sponsor_index_contains', data)) + self.sponsored = self.evaluate_attribute( # + event_attribute='sponsor_id', eval_func=lambda y, x: (x > 0) == y, + limit=BaseFilter.parse_as_type(bool, 'sponsored', data)) # Gym park - self.gym_park_contains = self.evaluate_attribute( - event_attribute='gym_park', eval_func=GymUtils.match_regex_dict, + self.park_contains = self.evaluate_attribute( # f.gp matches e.gp + event_attribute='park', eval_func=GymUtils.match_regex_dict, limit=BaseFilter.parse_as_set( - re.compile, 'gym_park_contains', data)) + GymUtils.create_regex, 'park_contains', data)) # Team Info self.old_team = self.evaluate_attribute( # f.ctis contains m.cti @@ -97,7 +108,7 @@ def __init__(self, name, data): limit=BaseFilter.parse_as_set(get_weather_id, 'weather', data)) # Geofences - self.geofences = BaseFilter.parse_as_set(str, 'geofences', data) + self.geofences = BaseFilter.parse_as_list(str, 'geofences', data) # Custom DTS self.custom_dts = BaseFilter.parse_as_dict( @@ -137,7 +148,18 @@ def to_dict(self): # Gym Name if self.gym_name_contains is not None: - settings['gym_name_matches'] = self.gym_name_contains + settings['gym_name_contains'] = self.gym_name_contains + + if self.gym_name_excludes is not None: + settings['gym_name_excludes'] = self.gym_name_excludes + + # Gym Sponsor + if self.sponsored is not None: + settings['sponsored'] = self.sponsored + + # Gym Park + if self.park_contains is not None: + settings['park_contains'] = self.park_contains # Geofences if self.geofences is not None: @@ -145,6 +167,6 @@ def to_dict(self): # Missing Info if self.is_missing_info is not None: - settings['missing_info'] = self.is_missing_info + settings['is_missing_info'] = self.is_missing_info return settings diff --git a/PokeAlarm/Filters/StopFilter.py b/PokeAlarm/Filters/StopFilter.py index 6ad2eae7c..879c74257 100644 --- a/PokeAlarm/Filters/StopFilter.py +++ b/PokeAlarm/Filters/StopFilter.py @@ -31,7 +31,7 @@ def __init__(self, name, data): limit=BaseFilter.parse_as_type(int, 'max_time_left', data)) # Geofences - self.geofences = BaseFilter.parse_as_set(str, 'geofences', data) + self.geofences = BaseFilter.parse_as_list(str, 'geofences', data) # Custom DTS self.custom_dts = BaseFilter.parse_as_dict( diff --git a/PokeAlarm/Load.py b/PokeAlarm/Load.py index e0f67d13a..a04471b1a 100644 --- a/PokeAlarm/Load.py +++ b/PokeAlarm/Load.py @@ -47,6 +47,8 @@ def parse_rules_file(manager, filename): load_rules_section(manager.add_egg_rule, rules.pop('eggs', {})) log.debug("Parsing 'raids' section.") load_rules_section(manager.add_raid_rule, rules.pop('raids', {})) + log.debug("Parsing 'weather' section.") + load_rules_section(manager.add_weather_rule, rules.pop('weather', {})) for key in rules: raise ValueError("Unknown Event type '{}'. Rules must be defined " diff --git a/PokeAlarm/Locale.py b/PokeAlarm/Locale.py index 73e18bccb..91dfed1f5 100644 --- a/PokeAlarm/Locale.py +++ b/PokeAlarm/Locale.py @@ -65,6 +65,16 @@ def __init__(self, language): for id_, val in default["types"].iteritems(): self.__type_names[int(id_)] = types.get(id_, val) + # Pokemon ID -> { Costume ID -> Costume Name) + self.__costume_names = {} + all_costumes = info.get("costumes", {}) + for pkmn_id, costumes in default["costumes"].iteritems(): + self.__costume_names[int(pkmn_id)] = {} + pkmn_costumes = all_costumes.get(pkmn_id, {}) + for costume_id, costume_name in costumes.iteritems(): + self.__costume_names[int(pkmn_id)][int( + costume_id)] = pkmn_costumes.get(costume_id, costume_name) + # Pokemon ID -> { Form ID -> Form Name) self.__form_names = {} all_forms = info.get("forms", {}) @@ -74,6 +84,7 @@ def __init__(self, language): for form_id, form_name in forms.iteritems(): self.__form_names[int(pkmn_id)][int(form_id)] = pkmn_forms.get( form_id, form_name) + log.debug("Loaded '{}' locale successfully!".format(language)) self.__misc = info.get('misc', {}) @@ -108,7 +119,14 @@ def get_type_name(self, type_id): # Returns the name of the form of for the given Pokemon ID and Form ID def get_form_name(self, pokemon_id, form_id): - return self.__form_names.get(pokemon_id, {}).get(form_id, 'unknown') + return self.__pokemon_names.get(form_id, 'unknown') if ( + pokemon_id == 132) else self.__form_names.get( + pokemon_id, {}).get(form_id, 'unknown') + + # Returns the name of the costume for the given Pokemon ID and Costume ID + def get_costume_name(self, pokemon_id, costume_id): + return self.__costume_names.get( + pokemon_id, {}).get(costume_id, 'unknown') def get_boosted_text(self): return self.__misc.get('boosted', '') diff --git a/PokeAlarm/LocationServices/GMaps.py b/PokeAlarm/LocationServices/GMaps.py new file mode 100644 index 000000000..b6ff25e46 --- /dev/null +++ b/PokeAlarm/LocationServices/GMaps.py @@ -0,0 +1,279 @@ +# Standard Library Imports +import collections +from datetime import datetime, timedelta +import logging +import time +import json +import traceback +import itertools +# 3rd Party Imports +import requests +from requests.packages.urllib3.util.retry import Retry +from gevent.lock import Semaphore +# Local Imports +from PokeAlarm import Unknown +from PokeAlarm.Utilities.GenUtils import synchronize_with + +log = logging.getLogger('Gmaps') + + +class GMaps(object): + + # Available travel modes for Distance Matrix calls + TRAVEL_MODES = frozenset(['walking', 'biking', 'driving', 'transit']) + + # Maximum number of requests per second + _queries_per_second = 50 + # How often to warn about going over query limit + _warning_window = timedelta(minutes=1) + + def __init__(self, api_key): + self._key = itertools.cycle(api_key) + self._lock = Semaphore + + # Create a session to handle connections + self._session = self._create_session() + + # Sliding window for rate limiting + self._window = collections.deque(maxlen=self._queries_per_second) + self._time_limit = datetime.utcnow() + + # Memoization dicts + self._geocode_hist = {} + self._reverse_geocode_hist = {} + self._dm_hist = {key: dict() for key in self.TRAVEL_MODES} + + # TODO: Move into utilities + @staticmethod + def _create_session(retry_count=3, pool_size=3, backoff=.25): + """ Create a session to use connection pooling. """ + + # Create a session for connection pooling and + session = requests.Session() + + # Reattempt connection on these statuses + status_forcelist = [500, 502, 503, 504] + + # Define a Retry object to handle failures + retry_policy = Retry( + total=retry_count, + backoff_factor=backoff, + status_forcelist=status_forcelist + ) + + # Define an Adapter, to limit pool and implement retry policy + adapter = requests.adapters.HTTPAdapter( + max_retries=retry_policy, + pool_connections=pool_size, + pool_maxsize=pool_size + ) + + # Apply Adapter for all HTTPS (no HTTP for you!) + session.mount('https://', adapter) + + return session + + def _make_request(self, service, params=None): + """ Make a request to the GMAPs API. """ + # Rate Limit - All APIs use the same quota + if len(self._window) == self._queries_per_second: + # Calculate elapsed time since start of window + elapsed_time = time.time() - self._window[0] + if elapsed_time < 1: + # Sleep off the difference + time.sleep(1 - elapsed_time) + + # Create the correct url + url = u'https://maps.googleapis.com/maps/api/{}/json'.format(service) + + # Add in the API key + if params is None: + params = {} + params['key'] = next(self._key) + + # Use the session to send the request + log.debug(u'{} request sending.'.format(service)) + self._window.append(time.time()) + request = self._session.get(url, params=params, timeout=3) + + if not request.ok: + log.debug(u'Response body: {}'.format( + json.dumps(request.json(), indent=4, sort_keys=True))) + # Raise HTTPError + request.raise_for_status() + + log.debug(u'{} request completed successfully with response {}.' + u''.format(service, request.status_code)) + body = request.json() + if body['status'] == "OK" or body['status'] == "ZERO_RESULTS": + return body + elif body['status'] == "OVER_QUERY_LIMIT": + # self._time_limit = datetime.utcnow() + _warning_window + raise UserWarning(u'API Quota exceeded.') + else: + raise ValueError(u'Unexpected response status:\n {}'.format(body)) + + @synchronize_with() + def geocode(self, address, language='en'): + # type: (str, str) -> tuple + """ Returns 'lat,lng' associated with the name of the place. """ + # Check for memoized results + address = address.lower() + if address in self._geocode_hist: + return self._geocode_hist[address] + # Set default in case something happens + latlng = None + try: + # Set parameters and make the request + params = {'address': address, 'language': language} + response = self._make_request('geocode', params) + # Extract the results and format into a dict + response = response.get('results', []) + response = response[0] if len(response) > 0 else {} + response = response.get('geometry', {}) + response = response.get('location', {}) + if 'lat' in response and 'lng' in response: + latlng = float(response['lat']), float(response['lng']) + + # Memoize the results + self._geocode_hist[address] = latlng + except requests.exceptions.HTTPError as e: + log.error(u"Geocode failed with " + u"HTTPError: {}".format(e.message)) + except requests.exceptions.Timeout as e: + log.error(u"Geocode failed with " + u"connection issues: {}".format(e.message)) + except UserWarning: + log.error(u"Geocode failed because of exceeded quota.") + except Exception as e: + log.error(u"Geocode failed because " + u"unexpected error has occurred: " + u"{} - {}".format(type(e).__name__, e.message)) + log.error(u"Stack trace: \n {}".format(traceback.format_exc())) + # Send back tuple + return latlng + + _reverse_geocode_defaults = { + 'street_num': Unknown.SMALL, + 'street': Unknown.REGULAR, + 'address': Unknown.REGULAR, + 'address_eu': Unknown.REGULAR, + 'postal': Unknown.REGULAR, + 'neighborhood': Unknown.REGULAR, + 'sublocality': Unknown.REGULAR, + 'city': Unknown.REGULAR, + 'county': Unknown.REGULAR, + 'state': Unknown.REGULAR, + 'country': Unknown.REGULAR + } + + @synchronize_with() + def reverse_geocode(self, latlng, language='en'): + # type: (tuple) -> dict + """ Returns the reverse geocode DTS associated with 'lat,lng'. """ + latlng = u'{:.5f},{:.5f}'.format(latlng[0], latlng[1]) + # Check for memoized results + if latlng in self._reverse_geocode_hist: + return self._reverse_geocode_hist[latlng] + # Get defaults in case something happens + dts = self._reverse_geocode_defaults.copy() + try: + # Set parameters and make the request + params = {'latlng': latlng, 'language': language} + response = self._make_request('geocode', params) + # Extract the results and format into a dict + response = response.get('results', []) + response = response[0] if len(response) > 0 else {} + details = {} + for item in response.get('address_components'): + for category in item['types']: + details[category] = item['short_name'] + + # Note: for addresses on unnamed roads, EMPTY is preferred for + # 'street_num' and 'street' to avoid DTS looking weird + dts['street_num'] = details.get('street_number', Unknown.EMPTY) + dts['street'] = details.get('route', Unknown.EMPTY) + dts['address'] = u"{} {}".format(dts['street_num'], dts['street']) + dts['address_eu'] = u"{} {}".format( + dts['street'], dts['street_num']) # Europeans are backwards + dts['postal'] = details.get('postal_code', Unknown.REGULAR) + dts['neighborhood'] = details.get('neighborhood', Unknown.REGULAR) + dts['sublocality'] = details.get('sublocality', Unknown.REGULAR) + dts['city'] = details.get( + 'locality', details.get('postal_town', Unknown.REGULAR)) + dts['county'] = details.get( + 'administrative_area_level_2', Unknown.REGULAR) + dts['state'] = details.get( + 'administrative_area_level_1', Unknown.REGULAR) + dts['country'] = details.get('country', Unknown.REGULAR) + + # Memoize the results + self._reverse_geocode_hist[latlng] = dts + except requests.exceptions.HTTPError as e: + log.error(u"Reverse Geocode failed with " + u"HTTPError: {}".format(e.message)) + except requests.exceptions.Timeout as e: + log.error(u"Reverse Geocode failed with " + u"connection issues: {}".format(e.message)) + except UserWarning: + log.error(u"Reverse Geocode failed because of exceeded quota.") + except Exception as e: + log.error(u"Reverse Geocode failed because " + u"unexpected error has occurred: " + u"{} - {}".format(type(e).__name__, e.message)) + log.error(u"Stack trace: \n {}".format(traceback.format_exc())) + # Send back dts + return dts + + @synchronize_with() + def distance_matrix(self, mode, origin, dest, lang, units): + # Check for valid mode + if mode not in self.TRAVEL_MODES: + raise ValueError(u"DM doesn't support mode '{}'.".format(mode)) + # Estimate to about ~1 meter of accuracy + origin = u'{:.5f},{:.5f}'.format(origin[0], origin[1]) + dest = u'{:.5f},{:.5f}'.format(dest[0], dest[1]) + + # Check for memoized results + key = origin + u':' + dest + if key in self._dm_hist: + return self._dm_hist[key] + + # Set defaults in case something happens + dist_key = '{}_distance'.format(mode) + dur_key = '{}_duration'.format(mode) + dts = {dist_key: Unknown.REGULAR, dur_key: Unknown.REGULAR} + try: + # Set parameters and make the request + params = { + 'mode': mode, 'origins': origin, 'destinations': dest, + 'language': lang, 'units': units + } + + # Extract the results and format into a dict + response = self._make_request('distancematrix', params) + response = response.get('rows', []) + response = response[0] if len(response) > 0 else {} + response = response.get('elements', []) + response = response[0] if len(response) > 0 else {} + + # Set the DTS + dts[dist_key] = response.get( + 'distance', {}).get('text', Unknown.REGULAR) + dts[dur_key] = response.get( + 'duration', {}).get('text', Unknown.REGULAR) + except requests.exceptions.HTTPError as e: + log.error(u"Distance Matrix failed with " + u"HTTPError: {}".format(e.message)) + except requests.exceptions.Timeout as e: + log.error(u"Distance Matrix failed with " + u"connection issues: {}".format(e.message)) + except UserWarning: + log.error(u"Distance Matrix failed because of exceeded quota.") + except Exception as e: + log.error(u"Distance Matrix failed because " + u"unexpected error has occurred: " + u"{} - {}".format(type(e).__name__, e.message)) + log.error(u"Stack trace: \n {}".format(traceback.format_exc())) + # Send back DTS + return dts diff --git a/PokeAlarm/LocationServices/GoogleMaps.py b/PokeAlarm/LocationServices/GoogleMaps.py deleted file mode 100644 index 401488f8d..000000000 --- a/PokeAlarm/LocationServices/GoogleMaps.py +++ /dev/null @@ -1,215 +0,0 @@ -# Standard Library Imports -import logging -import traceback -# 3rd Party Imports -import googlemaps -import itertools -# Local Imports - -log = logging.getLogger('LocService') - - -# Class to handle Location Services -class GoogleMaps(object): - - # Initialize the APIs - def __init__(self, api_key, locale, units): - - self.__locale = locale # Language to use for Geocoding results - self.__units = units # imperial or metric - self.__google_key = itertools.cycle(api_key) - - # For Reverse Location API - self.__reverse_location = False - self.__reverse_location_history = {} - # Walking Dist/Time - self.__walk_data = False - self.__walk_data_history = {} - # Bike Dist/Time - self.__biking_data = False - self.__bike_data_history = {} - # Drive Dist/Time - self.__driving_data = False - self.__driving_data_history = {} - - # Add any API-dependant DTS as required - def add_optional_arguments(self, origin, dest, data): - if self.__reverse_location: - data.update(**self.__get_reverse_location(dest)) - if self.__walk_data: - data.update(**self.__get_walking_data(origin, dest)) - if self.__biking_data: - data.update(**self.__get_biking_data(origin, dest)) - if self.__driving_data: - data.update(**self.__get_driving_data(origin, dest)) - - # Returns an array in the format [ Lat, Lng ], or exit if an error occurs. - def get_location_from_name(self, location_name): - try: - result = googlemaps.Client( - key=next(self.__google_key), - timeout=3, retry_timeout=5).geocode( - location_name, language=self.__locale) - # Get the first (most likely) result - loc = result[0]['geometry']['location'] - latitude, longitude = loc.get("lat"), loc.get("lng") - log.debug("Coordinates found for name '{}': {:f},{:f}".format( - location_name, latitude, longitude)) - return [latitude, longitude] - except Exception as e: - log.error("Encountered error attempting to receive location " - + "from name{}: {})".format(type(e).__name__, e)) - log.debug("Stack trace: \n {}".format(traceback.format_exc())) - return None - - # Enable the Reverse Location call in optional arguments - def enable_reverse_location(self): - if not self.__reverse_location: - self.__reverse_location = True - log.info("Reverse Location DTS detected - API has been enabled!") - - # Returns details about a location from coordinates in format [Lat, Lng] - def __get_reverse_location(self, location): - # Memoize the results to ~1 meter of precision - key = "{:.5f},{:.5f}".format(location[0], location[1]) - if key in self.__reverse_location_history: - return self.__reverse_location_history[key] - - details = { # Set some defaults in case something goes wrong - 'street_num': '???', 'street': 'unknown', 'address': 'unknown', - 'postal': 'unknown', 'neighborhood': 'unknown', - 'sublocality': 'unknown', 'city': 'unknown', 'county': 'unknown', - 'state': 'unknown', 'country': 'country' - } - try: - result = googlemaps.Client( - key=next(self.__google_key), - timeout=3, retry_timeout=5).reverse_geocode( - location, language=self.__locale)[0] - loc = {} - for item in result['address_components']: - for category in item['types']: - loc[category] = item['short_name'] - - # Note: for addresses in squares and on unnamed roads, it is - # correct with blank numbers/streetnames so we leave this as blank - # instead of unknown/??? to avoid DTS looking weird - details['street_num'] = loc.get('street_number', '') - details['street'] = loc.get('route', '') - details['address'] = "{} {}".format( - details['street_num'], details['street']) - details['address_eu'] = "{} {}".format( - details['street'], details['street_num']) # EU use Street 123 - details['postal'] = loc.get('postal_code', 'unknown') - details['neighborhood'] = loc.get('neighborhood', "unknown") - details['sublocality'] = loc.get('sublocality', "unknown") - details['city'] = loc.get( - 'locality', loc.get('postal_town', 'unknown')) - details['county'] = loc.get( - 'administrative_area_level_2', 'unknown') - details['state'] = loc.get( - 'administrative_area_level_1', 'unknown') - details['country'] = loc.get('country', 'unknown') - self.__reverse_location_history[key] = details # memoize - except Exception as e: - log.error("Encountered error while getting reverse " - + "location data ({}: {})".format(type(e).__name__, e)) - log.debug("Stack trace: \n {}".format(traceback.format_exc())) - # Return results, even if unable to complete - return details - - # Enable the Walking Distance Matrix call in optional arguments - def enable_walking_data(self): - if not self.__walk_data: - self.__walk_data = True - log.info("Walking Data DTS detected - API has been enabled!") - - # Returns set with walking dist and duration via Google Distance Matrix API - def __get_walking_data(self, origin, dest): - origin = "{:.5f},{:.5f}".format(origin[0], origin[1]) - dest = "{:.5f},{:.5f}".format(dest[0], dest[1]) - key = origin + "to" + dest - if key in self.__walk_data_history: - return self.__walk_data_history[key] - data = {'walk_dist': "unknown", 'walk_time': "unknown"} - try: - result = googlemaps.Client( - key=next(self.__google_key), - timeout=3, retry_timeout=5).distance_matrix( - origin, dest, mode='walking', - units=self.__units, language=self.__locale) - result = result.get('rows')[0].get('elements')[0] - data['walk_dist'] = result.get( - 'distance').get('text').encode('utf-8') - data['walk_time'] = result.get( - 'duration').get('text').encode('utf-8') - self.__walk_data_history[key] = data - except Exception as e: - log.error("Encountered error while getting walking data " - + " ({}: {})".format(type(e).__name__, e)) - log.debug("Stack trace: \n {}".format(traceback.format_exc())) - return data - - # Enable the Biking Distance Matrix call in optional arguments - def enable_biking_data(self): - if not self.__biking_data: - self.__biking_data = True - log.info("Biking Data DTS detected - API has been enabled!") - - # Returns set with biking dist and duration via Google Distance Matrix API - def __get_biking_data(self, origin, dest): - origin = "{:.5f},{:.5f}".format(origin[0], origin[1]) - dest = "{:.5f},{:.5f}".format(dest[0], dest[1]) - key = origin + "to" + dest - if key in self.__bike_data_history: - return self.__bike_data_history[key] - data = {'bike_dist': "unknown", 'bike_time': "unknown"} - try: - result = googlemaps.Client( - key=next(self.__google_key), - timeout=3, retry_timeout=5).distance_matrix( - origin, dest, mode='bicycling', - units=self.__units, language=self.__locale) - result = result.get('rows')[0].get('elements')[0] - data['bike_dist'] = result.get( - 'distance').get('text').encode('utf-8') - data['bike_time'] = result.get( - 'duration').get('text').encode('utf-8') - self.__bike_data_history[key] = data - except Exception as e: - log.error("Encountered error while getting biking data " - + "({}: {})".format(type(e).__name__, e)) - log.debug("Stack trace: \n {}".format(traceback.format_exc())) - return data - - # Enable the Biking Distance Matrix call in optional arguments - def enable_driving_data(self): - if not self.__driving_data: - self.__driving_data = True - log.info("Driving Data DTS detected - API has been enabled!") - - # Returns set with walking dist and duration via Google Distance Matrix API - def __get_driving_data(self, origin, dest): - origin = "{:.5f},{:.5f}".format(origin[0], origin[1]) - dest = "{:.5f},{:.5f}".format(dest[0], dest[1]) - key = origin + "to" + dest - if key in self.__driving_data_history: - return self.__driving_data_history[key] - data = {'drive_dist': "unknown", 'drive_time': "unknown"} - try: - result = googlemaps.Client( - key=next(self.__google_key), - timeout=3, retry_timeout=5).distance_matrix( - origin, dest, mode='driving', - units=self.__units, language=self.__locale) - result = result.get('rows')[0].get('elements')[0] - data['drive_dist'] = result.get( - 'distance').get('text').encode('utf-8') - data['drive_time'] = result.get( - 'duration').get('text').encode('utf-8') - self.__driving_data_history[key] = data - except Exception as e: - log.error("Encountered error while getting driving data " - + "({}: {})".format(type(e).__name__, e)) - log.debug("Stack trace: \n {}".format(traceback.format_exc())) - return data diff --git a/PokeAlarm/LocationServices/__init__.py b/PokeAlarm/LocationServices/__init__.py index be9cb95b7..a90205623 100644 --- a/PokeAlarm/LocationServices/__init__.py +++ b/PokeAlarm/LocationServices/__init__.py @@ -1,9 +1 @@ -from GoogleMaps import GoogleMaps - - -def location_service_factory(kind, api_key, locale, units): - if kind == "GoogleMaps": - return GoogleMaps(api_key, locale, units) - else: - raise ValueError( - "%s is not a valid location service!".format(kind)) +from GMaps import GMaps # noqa: F401 diff --git a/PokeAlarm/Manager.py b/PokeAlarm/Manager.py index 744531bc3..700c4c49f 100644 --- a/PokeAlarm/Manager.py +++ b/PokeAlarm/Manager.py @@ -20,9 +20,10 @@ from Cache import cache_factory from Geofence import load_geofence_file from Locale import Locale -from LocationServices import location_service_factory +from LocationServices import GMaps +from PokeAlarm import Unknown from Utils import (get_earth_dist, get_path, require_and_remove_key, - parse_boolean, contains_arg, get_cardinal_dir) + parse_boolean, get_cardinal_dir) from . import config Rule = namedtuple('Rule', ['filter_names', 'alarm_names']) @@ -40,11 +41,12 @@ def __init__(self, name, google_key, locale, units, timezone, time_limit, self.__debug = debug # Get the Google Maps API - self.__google_key = google_key - - self.__loc_service = location_service_factory( - "GoogleMaps", self.__google_key, locale, units) + self._google_key = google_key + self._gmaps_service = GMaps(google_key) + self._gmaps_reverse_geocode = False + self._gmaps_distance_matrix = set() + self._language = locale self.__locale = Locale(locale) # Setup the language-specific stuff self.__units = units # type of unit used for distances self.__timezone = timezone # timezone for time calculations @@ -79,7 +81,7 @@ def __init__(self, name, google_key, locale, units, timezone, time_limit, if str(geofence_file).lower() != 'none': self.geofences = load_geofence_file(get_path(geofence_file)) # Create the alarms to send notifications out with - self.__alarms = [] + self.__alarms = {} self.load_alarms_file(get_path(alarm_file), int(max_attempts)) # Initialize Rules @@ -88,6 +90,7 @@ def __init__(self, name, google_key, locale, units, timezone, time_limit, self.__gym_rules = {} self.__egg_rules = {} self.__raid_rules = {} + self.__weather_rules = {} # Initialize the queue and start the process self.__queue = Queue() @@ -124,7 +127,42 @@ def join(self): # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ CONTROL API ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ GMAPS API ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + def enable_gmaps_reverse_geocoding(self): + """Enable GMaps Reverse Geocoding DTS for triggered Events. """ + if not self._gmaps_service: + raise ValueError("Unable to enable Google Maps Reverse Geocoding." + "No GMaps API key has been set.") + self._gmaps_reverse_geocode = True + + def disable_gmaps_reverse_geocoding(self): + """Disable GMaps Reverse Geocoding DTS for triggered Events. """ + self._gmaps_reverse_geocode = False + + def enable_gmaps_distance_matrix(self, mode): + """Enable 'mode' Distance Matrix DTS for triggered Events. """ + if not self.__location: + raise ValueError("Unable to enable Google Maps Reverse Geocoding." + "No Manager location has been set.") + elif not self._gmaps_service: + raise ValueError("Unable to enable Google Maps Reverse Geocoding." + "No GMaps API key has been provided.") + elif mode not in GMaps.TRAVEL_MODES: + raise ValueError("Unable to enable distance matrix mode: " + "{} is not a valid mode.".format(mode)) + self._gmaps_distance_matrix.add(mode) + + def disable_gmaps_dm_walking(self, mode): + """Disable 'mode' Distance Matrix DTS for triggered Events. """ + if mode not in GMaps.TRAVEL_MODES: + raise ValueError("Unable to disable distance matrix mode: " + "Invalid mode specified.") + self._gmaps_distance_matrix.discard(mode) + + # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ RULES API ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ # Add new Monster Rule def add_monster_rule(self, name, filters, alarms): @@ -216,6 +254,24 @@ def add_raid_rule(self, name, filters, alarms): self.__raid_rules[name] = Rule(filters, alarms) + # Add new Weather Rule + def add_weather_rule(self, name, filters, alarms): + if name in self.__weather_rules: + raise ValueError("Unable to add Rule: Weather Rule with the name " + "{} already exists!".format(name)) + + for filt in filters: + if filt not in self.__weather_filters: + raise ValueError("Unable to create Rule: No weather Filter " + "named {}!".format(filt)) + + for alarm in alarms: + if alarm not in self.__alarms: + raise ValueError("Unable to create Rule: No Alarm " + "named {}!".format(alarm)) + + self.__weather_rules[name] = Rule(filters, alarms) + # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ MANAGER LOADING ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ @@ -223,10 +279,15 @@ def add_raid_rule(self, name, filters, alarms): @staticmethod def load_filter_section(section, sect_name, filter_type): defaults = section.pop('defaults', {}) + default_dts = defaults.pop('custom_dts', {}) filter_set = OrderedDict() for name, settings in section.pop('filters', {}).iteritems(): settings = dict(defaults.items() + settings.items()) try: + local_dts = dict(default_dts.items() + + settings.pop('custom_dts', {}).items()) + if len(local_dts) > 0: + settings['custom_dts'] = local_dts filter_set[name] = filter_type(name, settings) log.debug( "Filter '%s' set as the following: %s", name, @@ -334,9 +395,8 @@ def load_alarms_file(self, file_path, max_attempts): for name, alarm in alarm_settings.iteritems(): if parse_boolean(require_and_remove_key( 'active', alarm, "Alarm objects in file.")) is True: - self.set_optional_args(str(alarm)) self.__alarms[name] = Alarms.alarm_factory( - alarm, max_attempts, self.__google_key) + alarm, max_attempts, self._google_key) else: log.debug("Alarm not activated: {}".format(alarm['type']) + " because value not set to \"True\"") @@ -362,71 +422,6 @@ def load_alarms_file(self, file_path, max_attempts): log.debug("Stack trace: \n {}".format(traceback.format_exc())) sys.exit(1) - # Check for optional arguments and enable APIs as needed - def set_optional_args(self, line): - # Reverse Location - args = {'street', 'street_num', 'address', 'postal', 'neighborhood', - 'sublocality', 'city', 'county', 'state', 'country'} - if contains_arg(line, args): - if self.__loc_service is None: - log.critical("Reverse location DTS were detected but " - + "no API key was provided!") - log.critical("Please either remove the DTS, add an API key, " - + "or disable the alarm and try again.") - sys.exit(1) - self.__loc_service.enable_reverse_location() - - # Walking Dist Matrix - args = {'walk_dist', 'walk_time'} - if contains_arg(line, args): - if self.__location is None: - log.critical("Walking Distance Matrix DTS were detected but " - + " no location was set!") - log.critical("Please either remove the DTS, set a location, " - + "or disable the alarm and try again.") - sys.exit(1) - if self.__loc_service is None: - log.critical("Walking Distance Matrix DTS were detected " - + "but no API key was provided!") - log.critical("Please either remove the DTS, add an API key, " - + "or disable the alarm and try again.") - sys.exit(1) - self.__loc_service.enable_walking_data() - - # Biking Dist Matrix - args = {'bike_dist', 'bike_time'} - if contains_arg(line, args): - if self.__location is None: - log.critical("Biking Distance Matrix DTS were detected but " - + " no location was set!") - log.critical("Please either remove the DTS, set a location, " - + " or disable the alarm and try again.") - sys.exit(1) - if self.__loc_service is None: - log.critical("Biking Distance Matrix DTS were detected " - + " but no API key was provided!") - log.critical("Please either remove the DTS, add an API key, " - + " or disable the alarm and try again.") - sys.exit(1) - self.__loc_service.enable_biking_data() - - # Driving Dist Matrix - args = {'drive_dist', 'drive_time'} - if contains_arg(line, args): - if self.__location is None: - log.critical("Driving Distance Matrix DTS were detected but " - + "no location was set!") - log.critical("Please either remove the DTS, set a location, " - + "or disable the alarm and try again.") - sys.exit(1) - if self.__loc_service is None: - log.critical("Driving Distance Matrix DTS were detected but " - + "no API key was provided!") - log.critical("Please either remove the DTS, add an API key, " - + " or disable the alarm and try again.") - sys.exit(1) - self.__loc_service.enable_driving_data() - # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ HANDLE EVENTS ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ @@ -513,20 +508,19 @@ def set_location(self, location): if res: # If location is in a Lat,Lng coordinate self.__location = [float(res.group(1)), float(res.group(2))] else: - if self.__loc_service is None: # Check if key was provided - log.error("Unable to find location coordinates by name - " - + "no Google API key was provided.") - return None - self.__location = self.__loc_service.get_location_from_name( - location) - - if self.__location is None: - log.error("Unable to set location - " - + "Please check your settings and try again.") - sys.exit(1) - else: + # Check if key was provided + if self._gmaps_service is None: + raise ValueError("Unable to find location coordinates by name" + " - no Google API key was provided.") + # Attempt to geocode location + location = self._gmaps_service.geocode(location) + if location is None: + raise ValueError("Unable to geocode coordinates from {}. " + "Location will not be set.".format(location)) + + self.__location = location log.info("Location successfully set to '{},{}'.".format( - self.__location[0], self.__location[1])) + location[0], location[1])) # Process new Monster data and decide if a notification needs to be sent def process_monster(self, mon): @@ -541,13 +535,12 @@ def process_monster(self, mon): # 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: + # 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.update_pokemon_expiration( - mon.enc_id, mon.disappear_time) + self.__cache.monster_expiration(mon.enc_id, mon.disappear_time) # Check the time remaining seconds_left = (mon.disappear_time @@ -560,7 +553,7 @@ def process_monster(self, mon): # Calculate distance and direction if self.__location is not None: mon.distance = get_earth_dist( - [mon.lat, mon.lng], self.__location) + [mon.lat, mon.lng], self.__location, self.__units) mon.direction = get_cardinal_dir( [mon.lat, mon.lng], self.__location) @@ -587,10 +580,15 @@ def process_monster(self, mon): def _trigger_mon(self, mon, alarms): # Generate the DTS for the event dts = mon.generate_dts(self.__locale, self.__timezone, self.__units) - # Get reverse geocoding - if self.__loc_service: - self.__loc_service.add_optional_arguments( - self.__location, [mon.lat, mon.lng], dts) + + # Get GMaps Triggers + if self._gmaps_reverse_geocode: + dts.update(self._gmaps_service.reverse_geocode( + (mon.lat, mon.lng), self._language)) + for mode in self._gmaps_distance_matrix: + dts.update(self._gmaps_service.distance_matrix( + mode, (mon.lat, mon.lng), self.__location, + self._language, self.__units)) threads = [] # Spawn notifications in threads so they can work in background @@ -613,12 +611,17 @@ def process_stop(self, stop): 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: + # 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.update_pokestop_expiration(stop.stop_id, stop.expiration) + self.__cache.stop_expiration(stop.stop_id, stop.expiration) # Check the time remaining seconds_left = (stop.expiration - datetime.utcnow()).total_seconds() @@ -630,7 +633,7 @@ def process_stop(self, stop): # Calculate distance and direction if self.__location is not None: stop.distance = get_earth_dist( - [stop.lat, stop.lng], self.__location) + [stop.lat, stop.lng], self.__location, self.__units) stop.direction = get_cardinal_dir( [stop.lat, stop.lng], self.__location) @@ -657,10 +660,15 @@ def process_stop(self, stop): def _trigger_stop(self, stop, alarms): # Generate the DTS for the event dts = stop.generate_dts(self.__locale, self.__timezone, self.__units) - # Get reverse geocoding - if self.__loc_service: - self.__loc_service.add_optional_arguments( - self.__location, [stop.lat, stop.lng], dts) + + # Get GMaps Triggers + if self._gmaps_reverse_geocode: + dts.update(self._gmaps_service.reverse_geocode( + (stop.lat, stop.lng), self._language)) + for mode in self._gmaps_distance_matrix: + dts.update(self._gmaps_service.distance_matrix( + mode, (stop.lat, stop.lng), self.__location, + self._language, self.__units)) threads = [] # Spawn notifications in threads so they can work in background @@ -679,29 +687,25 @@ def process_gym(self, gym): """ 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) + 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: 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) + # 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: 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) @@ -710,7 +714,7 @@ def process_gym(self, gym): # Calculate distance and direction if self.__location is not None: gym.distance = get_earth_dist( - [gym.lat, gym.lng], self.__location) + [gym.lat, gym.lng], self.__location, self.__units) gym.direction = get_cardinal_dir( [gym.lat, gym.lng], self.__location) @@ -737,11 +741,15 @@ def process_gym(self, gym): def _trigger_gym(self, gym, alarms): # Generate the DTS for the event dts = gym.generate_dts(self.__locale, self.__timezone, self.__units) - dts.update(self.__cache.get_gym_info(gym.gym_id)) # update gym info - # Get reverse geocoding - if self.__loc_service: - self.__loc_service.add_optional_arguments( - self.__location, [gym.lat, gym.lng], dts) + + # Get GMaps Triggers + if self._gmaps_reverse_geocode: + dts.update(self._gmaps_service.reverse_geocode( + (gym.lat, gym.lng), self._language)) + for mode in self._gmaps_distance_matrix: + dts.update(self._gmaps_service.distance_matrix( + mode, (gym.lat, gym.lng), self.__location, + self._language, self.__units)) threads = [] # Spawn notifications in threads so they can work in background @@ -760,8 +768,14 @@ def process_egg(self, egg): """ 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) + egg.gym_name = self.__cache.gym_name(egg.gym_id, egg.gym_name) + egg.gym_description = self.__cache.gym_desc( + egg.gym_id, egg.gym_description) + egg.gym_image = self.__cache.gym_image(egg.gym_id, egg.gym_image) + + # Update Team if Unknown + if Unknown.is_(egg.current_team_id): + egg.current_team_id = self.__cache.gym_team(egg.gym_id) # Make sure that eggs are enabled if self.__eggs_enabled is False: @@ -769,11 +783,11 @@ def process_egg(self, egg): return # Skip if previously processed - if self.__cache.get_egg_expiration(egg.gym_id) is not None: + if self.__cache.egg_expiration(egg.gym_id) is not None: log.debug("Egg {} was skipped because it was previously " "processed.".format(egg.name)) return - self.__cache.update_egg_expiration(egg.gym_id, egg.hatch_time) + self.__cache.egg_expiration(egg.gym_id, egg.hatch_time) # Check the time remaining seconds_left = (egg.hatch_time - datetime.utcnow()).total_seconds() @@ -782,16 +796,10 @@ def process_egg(self, egg): "".format(egg.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.lat, egg.lng], self.__location, self.__units) egg.direction = get_cardinal_dir( [egg.lat, egg.lng], self.__location) @@ -818,11 +826,15 @@ def process_egg(self, egg): def _trigger_egg(self, egg, alarms): # Generate the DTS for the event dts = egg.generate_dts(self.__locale, self.__timezone, self.__units) - dts.update(self.__cache.get_gym_info(egg.gym_id)) # update gym info - # Get reverse geocoding - if self.__loc_service: - self.__loc_service.add_optional_arguments( - self.__location, [egg.lat, egg.lng], dts) + + # Get GMaps Triggers + if self._gmaps_reverse_geocode: + dts.update(self._gmaps_service.reverse_geocode( + (egg.lat, egg.lng), self._language)) + for mode in self._gmaps_distance_matrix: + dts.update(self._gmaps_service.distance_matrix( + mode, (egg.lat, egg.lng), self.__location, + self._language, self.__units)) threads = [] # Spawn notifications in threads so they can work in background @@ -841,8 +853,14 @@ def process_raid(self, raid): """ 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) + 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: @@ -850,11 +868,11 @@ def process_raid(self, raid): return # Skip if previously processed - if self.__cache.get_raid_expiration(raid.gym_id) is not None: + 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.update_raid_expiration(raid.gym_id, raid.raid_end) + self.__cache.raid_expiration(raid.gym_id, raid.raid_end) # Check the time remaining seconds_left = (raid.raid_end - datetime.utcnow()).total_seconds() @@ -863,16 +881,10 @@ def process_raid(self, raid): "".format(raid.name, seconds_left)) return - # Assigned cached info - info = self.__cache.get_gym_info(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.lat, raid.lng], self.__location, self.__units) raid.direction = get_cardinal_dir( [raid.lat, raid.lng], self.__location) @@ -899,11 +911,15 @@ def process_raid(self, raid): def _trigger_raid(self, raid, alarms): # Generate the DTS for the event dts = raid.generate_dts(self.__locale, self.__timezone, self.__units) - dts.update(self.__cache.get_gym_info(raid.gym_id)) # update gym info - # Get reverse geocoding - if self.__loc_service: - self.__loc_service.add_optional_arguments( - self.__location, [raid.lat, raid.lng], dts) + + # Get GMaps Triggers + if self._gmaps_reverse_geocode: + dts.update(self._gmaps_service.reverse_geocode( + (raid.lat, raid.lng), self._language)) + for mode in self._gmaps_distance_matrix: + dts.update(self._gmaps_service.distance_matrix( + mode, (raid.lat, raid.lng), self.__location, + self._language, self.__units)) threads = [] # Spawn notifications in threads so they can work in background @@ -936,31 +952,43 @@ def process_weather(self, weather): self.__cache.update_cell_weather( weather.weather_cell_id, weather.condition) - # Check the Filters - passed = True - for name, f in self.__weather_filters.iteritems(): - passed = f.check_event(weather) and \ - self.check_weather_geofences(f, weather) - if passed: # Stop checking + # 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())} + + for r_name, rule in rules.iteritems(): # For all rules + for f_name in rule.filter_names: # Check Filters in Rules + f = self.__weather_filters.get(f_name) + passed = f.check_event(weather) and \ + self.check_weather_geofences(f, weather) + if not passed: + continue # go to next filter weather.custom_dts = f.custom_dts - break - if not passed: # Weather was rejected by all filters - return - # Generate the DTS for the event - dts = weather.generate_dts(self.__locale) + if self.__quiet is False: + log.info("{} weather notification" + " has been triggered in rule '{}'!" + "".format(weather.weather_cell_id, r_name)) + self._trigger_weather(weather, rule.alarm_names) + break # Next rule - if self.__quiet is False: - log.info("{} weather notification triggered!".format( - weather.weather_cell_id)) + def _trigger_weather(self, weather, alarms): + + dts = weather.generate_dts( + self.__locale, self.__timezone, self.__units) threads = [] # Spawn notifications in threads so they can work in background - for alarm in self.__alarms: - threads.append(gevent.spawn(alarm.weather_alert, dts)) - gevent.sleep(0) # explict context yield + for name in alarms: + alarm = self.__alarms.get(name) + if alarm: + threads.append(gevent.spawn(alarm.weather_alert, dts)) + else: + log.critical("Alarm '{}' not found!".format(name)) - for thread in threads: + for thread in threads: # Wait for all alarms to finish thread.join() # Check to see if a notification is within the given range diff --git a/PokeAlarm/Utilities/GenUtils.py b/PokeAlarm/Utilities/GenUtils.py index 77f6e628c..fabf5a381 100644 --- a/PokeAlarm/Utilities/GenUtils.py +++ b/PokeAlarm/Utilities/GenUtils.py @@ -1,5 +1,6 @@ # Standard Library Imports # 3rd Party Imports +from gevent.lock import Semaphore # Local Imports @@ -13,3 +14,23 @@ def parse_bool(value): except Exception: pass # Skip below raise ValueError('Not a valid boolean') + + +def synchronize_with(lock=None): + """ Synchronization decorator. """ + + if lock is None: + lock = Semaphore() + + def synchronize(func): + + def locked_func(*args, **kwargs): + lock.acquire(timeout=60) + try: + return func(*args, **kwargs) + finally: + lock.release() + + return locked_func + + return synchronize diff --git a/PokeAlarm/Utilities/GymUtils.py b/PokeAlarm/Utilities/GymUtils.py index a564c5e5b..475a8d1db 100644 --- a/PokeAlarm/Utilities/GymUtils.py +++ b/PokeAlarm/Utilities/GymUtils.py @@ -43,3 +43,12 @@ def match_regex_dict(reg_exs, name): if reg_ex.search(name): return True return False + + +# Returns true if the string does not match any given RE objects +def not_match_regex_dict(reg_exs, name): + name = unicode(name) + for reg_ex in reg_exs: + if reg_ex.search(name): + return False + return True diff --git a/PokeAlarm/Utils.py b/PokeAlarm/Utils.py index ab7007865..dbc4cddde 100644 --- a/PokeAlarm/Utils.py +++ b/PokeAlarm/Utils.py @@ -11,6 +11,7 @@ # Local Imports from PokeAlarm import not_so_secret_url from PokeAlarm import config +from PokeAlarm import Unknown log = logging.getLogger('Utils') @@ -128,6 +129,18 @@ def get_team_id(team_name): return get_team_id.ids.get(name) +# Returns the types of a move when requesting +def get_move_type(move_id): + if not hasattr(get_move_type, 'info'): + get_move_type.info = {} + file_ = get_path('data/move_info.json') + with open(file_, 'r') as f: + j = json.loads(f.read()) + for id_ in j: + get_move_type.info[int(id_)] = j[id_]['type'] + return get_move_type.info.get(move_id, Unknown.SMALL) + + # Returns the damage of a move when requesting def get_move_damage(move_id): if not hasattr(get_move_damage, 'info'): @@ -359,9 +372,15 @@ def get_gmaps_link(lat, lng): # Returns a String link to Apple Maps Pin at the location def get_applemaps_link(lat, lng): - latlon = '{},{}'.format(repr(lat), repr(lng)) + latlng = '{},{}'.format(repr(lat), repr(lng)) return 'http://maps.apple.com/maps?' \ - + 'daddr={}&z=10&t=s&dirflg=w'.format(latlon) + + 'daddr={}&z=10&t=s&dirflg=w'.format(latlng) + + +# Returns a String link to Teleport to a location in PokeGo++2.0 +def get_pokego2_link(lat, lng, name, type): + deeplink = '{},{},{}'.format(repr(lat), repr(lng), str(name)) + return 'https://pokego2.com/p.html?{}'.format(deeplink) # Returns a static map url with and parameters for dynamic test diff --git a/PokeAlarm/__init__.py b/PokeAlarm/__init__.py index 701feaae9..071663040 100644 --- a/PokeAlarm/__init__.py +++ b/PokeAlarm/__init__.py @@ -7,7 +7,7 @@ } not_so_secret_url = binascii.unhexlify( - '68747470733a2f2f6d6f6e73746572696d616765732e746b2f76312e332f') + '68747470733a2f2f6d6f6e73746572696d616765732e746b2f76312e352f') class Unknown: diff --git a/cache/.gitignore b/cache/.gitignore deleted file mode 100644 index 5e7d2734c..000000000 --- a/cache/.gitignore +++ /dev/null @@ -1,4 +0,0 @@ -# Ignore everything in this directory -* -# Except this file -!.gitignore diff --git a/config/config.ini.example b/config/config.ini.example index e33870d58..bcf4a95d3 100644 --- a/config/config.ini.example +++ b/config/config.ini.example @@ -1,27 +1,76 @@ -# Copy this file to config.ini and modify to suit your needs +# DO NOT USE NOTEPAD OR TEXTEDIT TO EDIT FILES! +# USE AN EDITOR SUCH AS NOTPAD++, ATOM, NANO OR VI(M) +# You can create a copy of this config and edit it to suit your needs. # Uncomment a line (remove the #) when you want to change its default value. -# Multiple arguments can be listed as [arg1, arg2, ... ] -# Number of arguments must match manager_count or be a single arguement (single arguements will apply to all Managers) -# To exclude an argument for a specific manager, use 'None' - -# Server Settings -#debug # Enables debugging mode -#host: # Address to listen on (default 127.0.0.1) -#port: # Port to listen on (default: 4000) -#concurrency: 200 # Maximum concurrent connections for the webserver(default: 200) -#manager_count: 1 # Number of Managers to run. (default: 1) - -# Manager-Specific Settings -#manager_name: manager_0 # Name of the Manager in the logs. Default(manager_0). -#key: # Google Maps API Key to use -#filters: # File containing filter settings (default: filters.json) -#alarms: # File containing alarm settings (default: alarms.json) -#rules: # File containing rules settings (default: None) -#geofence: # File containing geofence(s) used to filter (default: None) -#location: # Location for the manager. 'Name' or 'lat lng' (default: None) -#locale: # Language to be used to translate names (default: en) -#cache_type: # Specify the type of cache to use. Options: ['mem', 'file'] (Default: 'mem') -#unit: # Units used to measure distance. Either 'imperial' or 'metric' (default: imperial) -#timelimit: # Minimum number of seconds remaining to send a notification (default: 0) -#max_attempts: # Maximum number of attempts an alarm makes to send a notification. (default: 3) -#timezone: # Timezone used for notifications Ex: 'America/Los_Angeles' or '[America/Los_Angeles, America/New_York]' \ No newline at end of file +# By default, PA will use `config/config.ini` to load settings. +# You can override the config file selection with `--config-file` or `-cf`. + + +######################## +# Webserver Settings +######################## + +#host: 127.0.0.1 # Interface to listen on (default='127.0.0.1') +#port: 4000 # Port to listen on (default='4000') +#concurrency: 200 # Maximum concurrent connections to webserver (default=200) +#manager_count: 1 # Number of Managers to run (default=1) +#debug # Enable debug logging (default='False) + + +######################### +# Manager Settings +######################### +# All of the settings below this line are manager-specific. +# If a single setting is supplied, it will apply to all Managers. +# Example: `locale: en` will set all Managers to english +# If an array of settings is supplied, they will be apply to Managers in order. +# Example: `locale: [ en, fr, en ]` sets a different language for 3 Managers. +# `None` can be used to exempt a Manager from an optional setting + +#manager_name: # Name of Manager, used for logging (default='manager#') + + +# File Settings +##################### +# File settings define location of files with settings for a Manager. +# Relative paths are presumed from install folder, root paths are absolute. + +#filters: filters.json # Filters for the Manager (default='filters.json') +#alarms: alarms.json # Alarms for the Manager (default='alarms.json') +#rules: rules.json # Rules for the Manager (default=None) +#geofence: geofence.txt # Geofences to be used in Filters (default=None) + + +# Location Specific +##################### +#location: # Location, as address or coordinates (default=None) +#locale: en # Language used for DTS translations (default='en') + # Options: ['de', 'en', 'es', 'fr', 'it', 'ko', 'pt', 'zh_hk' ] +#unit: imperial # Units used to measurements.(default='imperial') + # Options: ['imperial', 'metric' ] +#timezone: America/Los_Angeles # Timezones used for notifications. Default uses system time (default=None) + # Options: https://en.wikipedia.org/wiki/List_of_tz_database_time_zones + + +# GMaps Settings +################ +#gmaps-key: # Google Maps API Key (default=None) +#gmaps-rev-geocode: yes # Enable Reverse Geocoded DTS. (default='no') + # Note: This requires the Reverse Geocoding API to be enabled on your GMAPs key. +#gmaps-dm-walk: yes # Enable Walking DM DTS. (default='no') + # Note: This requires the Distance Matrix API to be enabled on your GMAPs key. +#gmaps-dm-bike: yes # Enable Bicycling DM DTS. (default='no') + # Note: This requires the Distance Matrix API to be enabled on your GMAPs key. +#gmaps-dm-drive: yes # Enable Driving DM DTS. (default='no') + # Note: This requires the Distance Matrix API to be enabled on your GMAPs key. +#gmaps-dm-transit: yes # Enable Transit DM DTS. (default='no') + # Note: This requires the Distance Matrix API to be enabled on your GMAPs key. + + +# Miscellaneous +################ +#cache_type: file # Type of cache used to share information between webhooks. (default='mem') + # Options: ['mem', 'file'] +#timelimit: 0 # Minimum seconds remaining on an Event to trigger notification (default=0) +# Note - `max_attempts` is being deprecated and may be replaced by alarm-level settings +#max_attempts: 3 # Maximum number of attempts an alarm makes to send a notification. (default=3) diff --git a/data/base_stats.json b/data/base_stats.json index 2594649e5..bd2931290 100644 --- a/data/base_stats.json +++ b/data/base_stats.json @@ -1,5 +1,5 @@ { - "1": { + "001": { "attack": 118, "defense": 118, "stamina": 90, @@ -10,7 +10,7 @@ "weight": 6.9, "height": 0.71 }, - "2": { + "002": { "attack": 151, "defense": 151, "stamina": 120, @@ -21,7 +21,7 @@ "weight": 13, "height": 0.99 }, - "3": { + "003": { "attack": 198, "defense": 198, "stamina": 160, @@ -32,7 +32,7 @@ "weight": 100, "height": 2.01 }, - "4": { + "004": { "attack": 116, "defense": 96, "stamina": 78, @@ -42,7 +42,7 @@ "weight": 8.5, "height": 0.61 }, - "5": { + "005": { "attack": 158, "defense": 129, "stamina": 116, @@ -52,7 +52,7 @@ "weight": 19, "height": 1.09 }, - "6": { + "006": { "attack": 223, "defense": 176, "stamina": 156, @@ -63,7 +63,7 @@ "weight": 90.5, "height": 1.7 }, - "7": { + "007": { "attack": 94, "defense": 122, "stamina": 88, @@ -73,7 +73,7 @@ "weight": 9, "height": 0.51 }, - "8": { + "008": { "attack": 126, "defense": 155, "stamina": 118, @@ -83,7 +83,7 @@ "weight": 22.5, "height": 0.99 }, - "9": { + "009": { "attack": 171, "defense": 210, "stamina": 158, @@ -93,7 +93,7 @@ "weight": 85.5, "height": 1.6 }, - "10": { + "010": { "attack": 55, "defense": 62, "stamina": 90, @@ -103,7 +103,7 @@ "weight": 2.9, "height": 0.3 }, - "11": { + "011": { "attack": 45, "defense": 94, "stamina": 100, @@ -113,7 +113,7 @@ "weight": 9.9, "height": 0.71 }, - "12": { + "012": { "attack": 167, "defense": 151, "stamina": 120, @@ -124,7 +124,7 @@ "weight": 32, "height": 1.09 }, - "13": { + "013": { "attack": 63, "defense": 55, "stamina": 80, @@ -135,7 +135,7 @@ "weight": 3.2, "height": 0.3 }, - "14": { + "014": { "attack": 46, "defense": 86, "stamina": 90, @@ -146,7 +146,7 @@ "weight": 10, "height": 0.61 }, - "15": { + "015": { "attack": 169, "defense": 150, "stamina": 130, @@ -157,7 +157,7 @@ "weight": 29.5, "height": 0.99 }, - "16": { + "016": { "attack": 85, "defense": 76, "stamina": 80, @@ -168,7 +168,7 @@ "weight": 1.8, "height": 0.3 }, - "17": { + "017": { "attack": 117, "defense": 108, "stamina": 126, @@ -179,7 +179,7 @@ "weight": 30, "height": 1.09 }, - "18": { + "018": { "attack": 166, "defense": 157, "stamina": 166, @@ -190,7 +190,7 @@ "weight": 39.5, "height": 1.5 }, - "19": { + "019": { "attack": 103, "defense": 70, "stamina": 60, @@ -200,7 +200,7 @@ "weight": 3.5, "height": 0.3 }, - "20": { + "020": { "attack": 161, "defense": 144, "stamina": 110, @@ -210,7 +210,7 @@ "weight": 18.5, "height": 0.71 }, - "21": { + "021": { "attack": 112, "defense": 61, "stamina": 80, @@ -221,7 +221,7 @@ "weight": 2, "height": 0.3 }, - "22": { + "022": { "attack": 182, "defense": 135, "stamina": 130, @@ -232,7 +232,7 @@ "weight": 38, "height": 1.19 }, - "23": { + "023": { "attack": 110, "defense": 102, "stamina": 70, @@ -242,7 +242,7 @@ "weight": 6.9, "height": 2.01 }, - "24": { + "024": { "attack": 185, "defense": 158, "stamina": 120, @@ -252,7 +252,7 @@ "weight": 65, "height": 3.51 }, - "25": { + "025": { "attack": 112, "defense": 101, "stamina": 70, @@ -262,7 +262,7 @@ "weight": 6, "height": 0.41 }, - "26": { + "026": { "attack": 193, "defense": 165, "stamina": 120, @@ -272,7 +272,7 @@ "weight": 30, "height": 0.79 }, - "27": { + "027": { "attack": 126, "defense": 145, "stamina": 100, @@ -282,7 +282,7 @@ "weight": 12, "height": 0.61 }, - "28": { + "028": { "attack": 182, "defense": 202, "stamina": 150, @@ -292,7 +292,7 @@ "weight": 29.5, "height": 0.99 }, - "29": { + "029": { "attack": 86, "defense": 94, "stamina": 110, @@ -302,7 +302,7 @@ "weight": 7, "height": 0.41 }, - "30": { + "030": { "attack": 117, "defense": 126, "stamina": 140, @@ -312,7 +312,7 @@ "weight": 20, "height": 0.79 }, - "31": { + "031": { "attack": 180, "defense": 174, "stamina": 180, @@ -323,7 +323,7 @@ "weight": 60, "height": 1.3 }, - "32": { + "032": { "attack": 105, "defense": 76, "stamina": 92, @@ -333,7 +333,7 @@ "weight": 9, "height": 0.51 }, - "33": { + "033": { "attack": 137, "defense": 112, "stamina": 122, @@ -343,7 +343,7 @@ "weight": 19.5, "height": 0.89 }, - "34": { + "034": { "attack": 204, "defense": 157, "stamina": 162, @@ -354,7 +354,7 @@ "weight": 62, "height": 1.4 }, - "35": { + "035": { "attack": 107, "defense": 116, "stamina": 140, @@ -364,7 +364,7 @@ "weight": 7.5, "height": 0.61 }, - "36": { + "036": { "attack": 178, "defense": 171, "stamina": 190, @@ -374,7 +374,7 @@ "weight": 40, "height": 1.3 }, - "37": { + "037": { "attack": 96, "defense": 122, "stamina": 76, @@ -384,7 +384,7 @@ "weight": 9.9, "height": 0.61 }, - "38": { + "038": { "attack": 169, "defense": 204, "stamina": 146, @@ -394,7 +394,7 @@ "weight": 19.9, "height": 1.09 }, - "39": { + "039": { "attack": 80, "defense": 44, "stamina": 230, @@ -405,7 +405,7 @@ "weight": 5.5, "height": 0.51 }, - "40": { + "040": { "attack": 156, "defense": 93, "stamina": 280, @@ -416,7 +416,7 @@ "weight": 12, "height": 0.99 }, - "41": { + "041": { "attack": 83, "defense": 76, "stamina": 80, @@ -427,7 +427,7 @@ "weight": 7.5, "height": 0.79 }, - "42": { + "042": { "attack": 161, "defense": 153, "stamina": 150, @@ -438,7 +438,7 @@ "weight": 55, "height": 1.6 }, - "43": { + "043": { "attack": 131, "defense": 116, "stamina": 90, @@ -449,7 +449,7 @@ "weight": 5.4, "height": 0.51 }, - "44": { + "044": { "attack": 153, "defense": 139, "stamina": 120, @@ -460,7 +460,7 @@ "weight": 8.6, "height": 0.79 }, - "45": { + "045": { "attack": 202, "defense": 170, "stamina": 150, @@ -471,7 +471,7 @@ "weight": 18.6, "height": 1.19 }, - "46": { + "046": { "attack": 121, "defense": 99, "stamina": 70, @@ -482,7 +482,7 @@ "weight": 5.4, "height": 0.3 }, - "47": { + "047": { "attack": 165, "defense": 146, "stamina": 120, @@ -493,7 +493,7 @@ "weight": 29.5, "height": 0.99 }, - "48": { + "048": { "attack": 100, "defense": 102, "stamina": 120, @@ -504,7 +504,7 @@ "weight": 30, "height": 0.99 }, - "49": { + "049": { "attack": 179, "defense": 150, "stamina": 140, @@ -515,7 +515,7 @@ "weight": 12.5, "height": 1.5 }, - "50": { + "050": { "attack": 109, "defense": 88, "stamina": 20, @@ -525,7 +525,7 @@ "weight": 0.8, "height": 0.2 }, - "51": { + "051": { "attack": 205, "defense": 147, "stamina": 70, @@ -535,7 +535,7 @@ "weight": 33.3, "height": 0.71 }, - "52": { + "052": { "attack": 92, "defense": 81, "stamina": 80, @@ -545,7 +545,7 @@ "weight": 4.2, "height": 0.41 }, - "53": { + "053": { "attack": 150, "defense": 139, "stamina": 130, @@ -555,7 +555,7 @@ "weight": 32, "height": 0.99 }, - "54": { + "054": { "attack": 122, "defense": 96, "stamina": 100, @@ -565,7 +565,7 @@ "weight": 19.6, "height": 0.79 }, - "55": { + "055": { "attack": 191, "defense": 163, "stamina": 160, @@ -575,7 +575,7 @@ "weight": 76.6, "height": 1.7 }, - "56": { + "056": { "attack": 148, "defense": 87, "stamina": 80, @@ -585,7 +585,7 @@ "weight": 28, "height": 0.51 }, - "57": { + "057": { "attack": 207, "defense": 144, "stamina": 130, @@ -595,7 +595,7 @@ "weight": 32, "height": 0.99 }, - "58": { + "058": { "attack": 136, "defense": 96, "stamina": 110, @@ -605,7 +605,7 @@ "weight": 19, "height": 0.71 }, - "59": { + "059": { "attack": 227, "defense": 166, "stamina": 180, @@ -615,7 +615,7 @@ "weight": 155, "height": 1.91 }, - "60": { + "060": { "attack": 101, "defense": 82, "stamina": 80, @@ -625,7 +625,7 @@ "weight": 12.4, "height": 0.61 }, - "61": { + "061": { "attack": 130, "defense": 130, "stamina": 130, @@ -635,7 +635,7 @@ "weight": 20, "height": 0.99 }, - "62": { + "062": { "attack": 182, "defense": 187, "stamina": 180, @@ -646,7 +646,7 @@ "weight": 54, "height": 1.3 }, - "63": { + "063": { "attack": 195, "defense": 103, "stamina": 50, @@ -656,7 +656,7 @@ "weight": 19.5, "height": 0.89 }, - "64": { + "064": { "attack": 232, "defense": 138, "stamina": 80, @@ -666,7 +666,7 @@ "weight": 56.5, "height": 1.3 }, - "65": { + "065": { "attack": 271, "defense": 194, "stamina": 110, @@ -676,7 +676,7 @@ "weight": 48, "height": 1.5 }, - "66": { + "066": { "attack": 137, "defense": 88, "stamina": 140, @@ -686,7 +686,7 @@ "weight": 19.5, "height": 0.79 }, - "67": { + "067": { "attack": 177, "defense": 130, "stamina": 160, @@ -696,7 +696,7 @@ "weight": 70.5, "height": 1.5 }, - "68": { + "068": { "attack": 234, "defense": 162, "stamina": 180, @@ -706,7 +706,7 @@ "weight": 130, "height": 1.6 }, - "69": { + "069": { "attack": 139, "defense": 64, "stamina": 100, @@ -717,7 +717,7 @@ "weight": 4, "height": 0.71 }, - "70": { + "070": { "attack": 172, "defense": 95, "stamina": 130, @@ -728,7 +728,7 @@ "weight": 6.4, "height": 0.99 }, - "71": { + "071": { "attack": 207, "defense": 138, "stamina": 160, @@ -739,7 +739,7 @@ "weight": 15.5, "height": 1.7 }, - "72": { + "072": { "attack": 97, "defense": 182, "stamina": 80, @@ -750,7 +750,7 @@ "weight": 45.5, "height": 0.89 }, - "73": { + "073": { "attack": 166, "defense": 237, "stamina": 160, @@ -761,7 +761,7 @@ "weight": 55, "height": 1.6 }, - "74": { + "074": { "attack": 132, "defense": 163, "stamina": 80, @@ -772,7 +772,7 @@ "weight": 20, "height": 0.41 }, - "75": { + "075": { "attack": 164, "defense": 196, "stamina": 110, @@ -783,7 +783,7 @@ "weight": 105, "height": 0.99 }, - "76": { + "076": { "attack": 211, "defense": 229, "stamina": 160, @@ -794,7 +794,7 @@ "weight": 300, "height": 1.4 }, - "77": { + "077": { "attack": 170, "defense": 132, "stamina": 100, @@ -804,7 +804,7 @@ "weight": 30, "height": 0.99 }, - "78": { + "078": { "attack": 207, "defense": 167, "stamina": 130, @@ -814,7 +814,7 @@ "weight": 95, "height": 1.7 }, - "79": { + "079": { "attack": 109, "defense": 109, "stamina": 180, @@ -825,7 +825,7 @@ "weight": 36, "height": 1.19 }, - "80": { + "080": { "attack": 177, "defense": 194, "stamina": 190, @@ -836,7 +836,7 @@ "weight": 78.5, "height": 1.6 }, - "81": { + "081": { "attack": 165, "defense": 128, "stamina": 50, @@ -847,7 +847,7 @@ "weight": 6, "height": 0.3 }, - "82": { + "082": { "attack": 223, "defense": 182, "stamina": 100, @@ -858,7 +858,7 @@ "weight": 60, "height": 0.99 }, - "83": { + "083": { "attack": 167, "defense": 118, "stamina": 104, @@ -869,7 +869,7 @@ "weight": 15, "height": 0.79 }, - "84": { + "084": { "attack": 158, "defense": 88, "stamina": 70, @@ -880,7 +880,7 @@ "weight": 39.2, "height": 1.4 }, - "85": { + "085": { "attack": 223, "defense": 148, "stamina": 120, @@ -891,7 +891,7 @@ "weight": 85.2, "height": 1.8 }, - "86": { + "086": { "attack": 85, "defense": 128, "stamina": 130, @@ -901,7 +901,7 @@ "weight": 90, "height": 1.09 }, - "87": { + "087": { "attack": 139, "defense": 184, "stamina": 180, @@ -912,7 +912,7 @@ "weight": 120, "height": 1.7 }, - "88": { + "088": { "attack": 135, "defense": 90, "stamina": 160, @@ -922,7 +922,7 @@ "weight": 30, "height": 0.89 }, - "89": { + "089": { "attack": 190, "defense": 184, "stamina": 210, @@ -932,7 +932,7 @@ "weight": 30, "height": 1.19 }, - "90": { + "090": { "attack": 116, "defense": 168, "stamina": 60, @@ -942,7 +942,7 @@ "weight": 4, "height": 0.3 }, - "91": { + "091": { "attack": 186, "defense": 323, "stamina": 100, @@ -953,7 +953,7 @@ "weight": 132.5, "height": 1.5 }, - "92": { + "092": { "attack": 186, "defense": 70, "stamina": 60, @@ -964,7 +964,7 @@ "weight": 0.1, "height": 1.3 }, - "93": { + "093": { "attack": 223, "defense": 112, "stamina": 90, @@ -975,7 +975,7 @@ "weight": 0.1, "height": 1.6 }, - "94": { + "094": { "attack": 261, "defense": 156, "stamina": 120, @@ -986,7 +986,7 @@ "weight": 40.5, "height": 1.5 }, - "95": { + "095": { "attack": 85, "defense": 288, "stamina": 70, @@ -997,7 +997,7 @@ "weight": 210, "height": 8.79 }, - "96": { + "096": { "attack": 89, "defense": 158, "stamina": 120, @@ -1007,7 +1007,7 @@ "weight": 32.4, "height": 0.99 }, - "97": { + "097": { "attack": 144, "defense": 215, "stamina": 170, @@ -1017,7 +1017,7 @@ "weight": 75.6, "height": 1.6 }, - "98": { + "098": { "attack": 181, "defense": 156, "stamina": 60, @@ -1027,7 +1027,7 @@ "weight": 6.5, "height": 0.41 }, - "99": { + "099": { "attack": 240, "defense": 214, "stamina": 110, @@ -4010,9 +4010,9 @@ "height": 3.51 }, "384": { - "attack": 312, - "defense": 187, - "stamina": 210, + "attack": 284, + "defense": 170, + "stamina": 191, "type1": 16, "type2": 3, "legendary": true, diff --git a/data/move_info.json b/data/move_info.json index ef4c3fe1b..946602180 100644 --- a/data/move_info.json +++ b/data/move_info.json @@ -1,1115 +1,1301 @@ { - "13": { + "013": { + "type": 1, "damage": 60, "dps": 20.69, "duration": 2900, "energy": 33 }, - "14": { + "014": { + "type": 1, "damage": 150, "dps": 39.47, "duration": 3800, "energy": 100 }, - "16": { + "016": { + "type": 18, "damage": 80, "dps": 26.67, "duration": 3000, "energy": 50 }, - "18": { + "018": { + "type": 4, "damage": 50, "dps": 23.81, "duration": 2100, "energy": 33 }, - "20": { + "020": { + "type": 1, "damage": 35, "dps": 18.42, "duration": 1900, "energy": 33 }, - "21": { + "021": { + "type": 10, "damage": 60, "dps": 22.22, "duration": 2700, "energy": 50 }, - "22": { + "022": { + "type": 7, "damage": 90, "dps": 40.91, "duration": 2200, "energy": 100 }, - "24": { + "024": { + "type": 10, "damage": 70, "dps": 31.82, "duration": 2200, "energy": 50 }, - "26": { + "026": { + "type": 5, "damage": 100, "dps": 21.28, "duration": 4700, "energy": 50 }, - "28": { + "028": { + "type": 2, "damage": 50, "dps": 33.33, "duration": 1500, "energy": 50 }, - "30": { + "030": { + "type": 14, "damage": 70, "dps": 21.88, "duration": 3200, "energy": 50 }, - "31": { + "031": { + "type": 5, "damage": 120, "dps": 33.33, "duration": 3600, "energy": 100 }, - "32": { + "032": { + "type": 6, "damage": 100, "dps": 43.48, "duration": 2300, "energy": 100 }, - "33": { + "033": { + "type": 15, "damage": 50, "dps": 26.32, "duration": 1900, "energy": 33 }, - "34": { + "034": { + "type": 14, "damage": 40, "dps": 21.05, "duration": 1900, "energy": 33 }, - "35": { + "035": { + "type": 13, "damage": 65, "dps": 26.0, "duration": 2500, "energy": 33 }, - "36": { + "036": { + "type": 9, "damage": 100, "dps": 37.04, "duration": 2700, "energy": 100 }, - "38": { + "038": { + "type": 3, "damage": 60, "dps": 26.09, "duration": 2300, "energy": 33 }, - "39": { + "039": { + "type": 15, "damage": 90, "dps": 27.27, "duration": 3300, "energy": 50 }, - "40": { + "040": { + "type": 15, "damage": 130, "dps": 41.94, "duration": 3100, "energy": 100 }, - "42": { + "042": { + "type": 10, "damage": 95, "dps": 31.67, "duration": 3000, "energy": 100 }, - "45": { + "045": { + "type": 3, "damage": 55, "dps": 22.92, "duration": 2400, "energy": 33 }, - "46": { + "046": { + "type": 5, "damage": 80, "dps": 28.57, "duration": 2800, "energy": 50 }, - "47": { + "047": { + "type": 12, "damage": 110, "dps": 42.31, "duration": 2600, "energy": 100 }, - "48": { + "048": { + "type": 12, "damage": 25, "dps": 9.62, "duration": 2600, "energy": 50 }, - "49": { + "049": { + "type": 7, "damage": 90, "dps": 24.32, "duration": 3700, "energy": 50 }, - "50": { + "050": { + "type": 4, "damage": 35, "dps": 20.59, "duration": 1700, "energy": 33 }, - "51": { + "051": { + "type": 18, "damage": 50, "dps": 22.73, "duration": 2200, "energy": 33 }, - "53": { + "053": { + "type": 11, "damage": 45, "dps": 23.68, "duration": 1900, "energy": 33 }, - "54": { + "054": { + "type": 2, "damage": 60, "dps": 27.27, "duration": 2200, "energy": 50 }, - "56": { + "056": { + "type": 2, "damage": 40, "dps": 21.05, "duration": 1900, "energy": 33 }, - "57": { + "057": { + "type": 11, "damage": 45, "dps": 17.31, "duration": 2600, "energy": 33 }, - "58": { + "058": { + "type": 11, "damage": 50, "dps": 26.32, "duration": 1900, "energy": 33 }, - "59": { + "059": { + "type": 12, "damage": 55, "dps": 26.19, "duration": 2100, "energy": 33 }, - "60": { + "060": { + "type": 14, "damage": 65, "dps": 24.07, "duration": 2700, "energy": 33 }, - "62": { + "062": { + "type": 6, "damage": 70, "dps": 20.0, "duration": 3500, "energy": 33 }, - "63": { + "063": { + "type": 6, "damage": 70, "dps": 21.88, "duration": 3200, "energy": 50 }, - "64": { + "064": { + "type": 6, "damage": 80, "dps": 29.63, "duration": 2700, "energy": 50 }, - "65": { + "065": { + "type": 6, "damage": 80, "dps": 27.59, "duration": 2900, "energy": 50 }, - "66": { + "066": { + "type": 8, "damage": 50, "dps": 17.24, "duration": 2900, "energy": 33 }, - "67": { + "067": { + "type": 8, "damage": 40, "dps": 23.53, "duration": 1700, "energy": 33 }, - "69": { + "069": { + "type": 8, "damage": 50, "dps": 21.74, "duration": 2300, "energy": 33 }, - "70": { + "070": { + "type": 8, "damage": 100, "dps": 33.33, "duration": 3000, "energy": 50 }, - "72": { + "072": { + "type": 9, "damage": 70, "dps": 25.0, "duration": 2800, "energy": 33 }, - "74": { + "074": { + "type": 9, "damage": 60, "dps": 31.58, "duration": 1900, "energy": 50 }, - "75": { + "075": { + "type": 13, "damage": 25, "dps": 8.93, "duration": 2800, "energy": 50 }, - "77": { + "077": { + "type": 13, "damage": 45, "dps": 25.0, "duration": 1800, "energy": 33 }, - "78": { + "078": { + "type": 13, "damage": 100, "dps": 41.67, "duration": 2400, "energy": 100 }, - "79": { + "079": { + "type": 13, "damage": 80, "dps": 32.0, "duration": 2500, "energy": 50 }, - "80": { + "080": { + "type": 16, "damage": 45, "dps": 16.07, "duration": 2800, "energy": 33 }, - "82": { + "082": { + "type": 16, "damage": 90, "dps": 25.0, "duration": 3600, "energy": 50 }, - "83": { + "083": { + "type": 16, "damage": 50, "dps": 29.41, "duration": 1700, "energy": 33 }, - "84": { + "084": { + "type": 17, "damage": 70, "dps": 17.95, "duration": 3900, "energy": 33 }, - "85": { + "085": { + "type": 17, "damage": 60, "dps": 23.08, "duration": 2600, "energy": 50 }, - "86": { + "086": { + "type": 17, "damage": 100, "dps": 28.57, "duration": 3500, "energy": 50 }, - "87": { + "087": { + "type": 17, "damage": 130, "dps": 33.33, "duration": 3900, "energy": 100 }, - "88": { + "088": { + "type": 17, "damage": 90, "dps": 31.03, "duration": 2900, "energy": 50 }, - "89": { + "089": { + "type": 4, "damage": 40, "dps": 26.67, "duration": 1500, "energy": 33 }, - "90": { + "090": { + "type": 4, "damage": 80, "dps": 34.78, "duration": 2300, "energy": 50 }, - "91": { + "091": { + "type": 4, "damage": 110, "dps": 34.38, "duration": 3200, "energy": 100 }, - "92": { + "092": { + "type": 4, "damage": 130, "dps": 41.94, "duration": 3100, "energy": 100 }, - "94": { + "094": { + "type": 5, "damage": 40, "dps": 25.0, "duration": 1600, "energy": 33 }, - "95": { + "095": { + "type": 5, "damage": 80, "dps": 22.86, "duration": 3500, "energy": 50 }, - "96": { + "096": { + "type": 5, "damage": 55, "dps": 23.91, "duration": 2300, "energy": 33 }, - "99": { + "099": { + "type": 7, "damage": 75, "dps": 25.86, "duration": 2900, "energy": 50 }, "100": { + "type": 7, "damage": 45, "dps": 28.13, "duration": 1600, "energy": 33 }, "101": { + "type": 10, "damage": 70, "dps": 18.42, "duration": 3800, "energy": 33 }, "102": { + "type": 10, "damage": 70, "dps": 26.92, "duration": 2600, "energy": 50 }, "103": { + "type": 10, "damage": 140, "dps": 33.33, "duration": 4200, "energy": 100 }, "104": { + "type": 11, "damage": 60, "dps": 26.09, "duration": 2300, "energy": 50 }, "105": { + "type": 11, "damage": 70, "dps": 21.88, "duration": 3200, "energy": 50 }, "106": { + "type": 11, "damage": 80, "dps": 21.62, "duration": 3700, "energy": 50 }, "107": { + "type": 11, "damage": 130, "dps": 39.39, "duration": 3300, "energy": 100 }, "108": { + "type": 14, "damage": 100, "dps": 35.71, "duration": 2800, "energy": 100 }, "109": { + "type": 14, "damage": 100, "dps": 22.73, "duration": 4400, "energy": 50 }, "111": { + "type": 15, "damage": 60, "dps": 18.18, "duration": 3300, "energy": 33 }, "114": { + "type": 12, "damage": 50, "dps": 12.82, "duration": 3900, "energy": 100 }, "115": { + "type": 10, "damage": 55, "dps": 25.0, "duration": 2200, "energy": 33 }, "116": { + "type": 12, "damage": 180, "dps": 36.73, "duration": 4900, "energy": 100 }, "117": { + "type": 12, "damage": 70, "dps": 29.17, "duration": 2400, "energy": 33 }, "118": { + "type": 12, "damage": 90, "dps": 34.62, "duration": 2600, "energy": 50 }, "121": { + "type": 3, "damage": 60, "dps": 22.22, "duration": 2700, "energy": 50 }, "122": { + "type": 3, "damage": 110, "dps": 40.74, "duration": 2700, "energy": 100 }, "123": { + "type": 2, "damage": 40, "dps": 25.0, "duration": 1600, "energy": 33 }, "125": { + "type": 1, "damage": 60, "dps": 21.43, "duration": 2800, "energy": 50 }, "126": { + "type": 1, "damage": 40, "dps": 21.62, "duration": 1850, "energy": 33 }, "127": { + "type": 1, "damage": 55, "dps": 32.35, "duration": 1700, "energy": 50 }, "129": { + "type": 1, "damage": 80, "dps": 32.0, "duration": 2500, "energy": 50 }, "131": { + "type": 1, "damage": 50, "dps": 26.32, "duration": 1900, "energy": 33 }, "132": { + "type": 1, "damage": 50, "dps": 26.32, "duration": 1900, "energy": 33 }, "133": { + "type": 1, "damage": 35, "dps": 15.91, "duration": 2200, "energy": 33 }, "134": { + "type": 11, "damage": 50, "dps": 10.64, "duration": 4700, "energy": 100 }, "135": { + "type": 11, "damage": 90, "dps": 20.0, "duration": 4500, "energy": 100 }, "136": { + "type": 1, "damage": 25, "dps": 8.62, "duration": 2900, "energy": 33 }, "137": { + "type": 1, "damage": 25, "dps": 8.62, "duration": 2900, "energy": 33 }, "200": { + "type": 7, "damage": 3, "dps": 7.5, "duration": 400, "energy": 6 }, "201": { + "type": 7, "damage": 5, "dps": 10.0, "duration": 500, "energy": 6 }, "202": { + "type": 18, "damage": 6, "dps": 12.0, "duration": 500, "energy": 4 }, "203": { + "type": 18, "damage": 7, "dps": 10.0, "duration": 700, "energy": 8 }, "204": { + "type": 16, "damage": 6, "dps": 12.0, "duration": 500, "energy": 4 }, "205": { + "type": 13, "damage": 5, "dps": 8.33, "duration": 600, "energy": 8 }, "206": { + "type": 13, "damage": 6, "dps": 8.57, "duration": 700, "energy": 9 }, "207": { + "type": 2, "damage": 6, "dps": 10.0, "duration": 600, "energy": 6 }, "208": { + "type": 2, "damage": 8, "dps": 10.0, "duration": 800, "energy": 10 }, "209": { + "type": 10, "damage": 10, "dps": 10.0, "duration": 1000, "energy": 10 }, "210": { + "type": 3, "damage": 8, "dps": 10.0, "duration": 800, "energy": 9 }, "211": { + "type": 3, "damage": 10, "dps": 10.0, "duration": 1000, "energy": 10 }, "212": { + "type": 8, "damage": 5, "dps": 10.0, "duration": 500, "energy": 6 }, "213": { + "type": 8, "damage": 9, "dps": 12.86, "duration": 700, "energy": 6 }, "214": { + "type": 12, "damage": 7, "dps": 11.67, "duration": 600, "energy": 6 }, "215": { + "type": 12, "damage": 13, "dps": 13.0, "duration": 1000, "energy": 7 }, "216": { + "type": 5, "damage": 5, "dps": 8.33, "duration": 600, "energy": 7 }, "217": { + "type": 15, "damage": 12, "dps": 10.0, "duration": 1200, "energy": 12 }, "218": { + "type": 15, "damage": 10, "dps": 11.11, "duration": 900, "energy": 8 }, "219": { + "type": 1, "damage": 8, "dps": 10.0, "duration": 800, "energy": 10 }, "220": { + "type": 1, "damage": 6, "dps": 12.0, "duration": 500, "energy": 4 }, "221": { + "type": 1, "damage": 5, "dps": 10.0, "duration": 500, "energy": 5 }, "222": { + "type": 1, "damage": 7, "dps": 11.67, "duration": 600, "energy": 6 }, "223": { + "type": 1, "damage": 5, "dps": 10.0, "duration": 500, "energy": 5 }, "224": { + "type": 4, "damage": 10, "dps": 12.5, "duration": 800, "energy": 7 }, "225": { + "type": 4, "damage": 9, "dps": 11.25, "duration": 800, "energy": 8 }, "226": { + "type": 14, "damage": 5, "dps": 8.33, "duration": 600, "energy": 8 }, "227": { + "type": 6, "damage": 12, "dps": 13.33, "duration": 900, "energy": 7 }, "228": { + "type": 9, "damage": 8, "dps": 11.43, "duration": 700, "energy": 7 }, "229": { + "type": 9, "damage": 9, "dps": 10.0, "duration": 900, "energy": 10 }, "230": { + "type": 11, "damage": 5, "dps": 10.0, "duration": 500, "energy": 5 }, "231": { + "type": 11, "damage": 0, "dps": 0.0, "duration": 1730, "energy": 0 }, "233": { + "type": 5, "damage": 15, "dps": 10.71, "duration": 1400, "energy": 12 }, "234": { + "type": 14, "damage": 12, "dps": 10.91, "duration": 1100, "energy": 10 }, "235": { + "type": 14, "damage": 20, "dps": 12.5, "duration": 1600, "energy": 15 }, "236": { + "type": 4, "damage": 5, "dps": 8.33, "duration": 600, "energy": 7 }, "237": { + "type": 11, "damage": 12, "dps": 10.0, "duration": 1200, "energy": 14 }, "238": { + "type": 18, "damage": 10, "dps": 11.11, "duration": 900, "energy": 9 }, "239": { + "type": 9, "damage": 11, "dps": 13.75, "duration": 800, "energy": 6 }, "240": { + "type": 10, "damage": 11, "dps": 12.22, "duration": 900, "energy": 8 }, "241": { + "type": 2, "damage": 15, "dps": 11.54, "duration": 1300, "energy": 10 }, "242": { + "type": 1, "damage": 0, "dps": 0, "duration": 2230, "energy": 0 }, "243": { + "type": 2, "damage": 12, "dps": 13.33, "duration": 900, "energy": 8 }, "244": { + "type": 15, "damage": 6, "dps": 6.0, "duration": 1000, "energy": 15 }, "245": { + "type": 2, "damage": 100, "dps": 43.48, "duration": 2300, "energy": 100 }, "246": { + "type": 2, "damage": 90, "dps": 33.33, "duration": 2700, "energy": 50 }, "247": { + "type": 2, "damage": 140, "dps": 40.0, "duration": 3500, "energy": 100 }, "248": { + "type": 15, "damage": 80, "dps": 22.54, "duration": 3550, "energy": 50 }, "249": { + "type": 13, "damage": 8, "dps": 7.27, "duration": 1100, "energy": 15 }, "250": { + "type": 13, "damage": 20, "dps": 8.7, "duration": 2300, "energy": 25 }, "251": { + "type": 13, "damage": 90, "dps": 34.62, "duration": 2600, "energy": 50 }, "252": { + "type": 13, "damage": 140, "dps": 37.84, "duration": 3700, "energy": 100 }, "253": { + "type": 16, "damage": 15, "dps": 13.64, "duration": 1100, "energy": 9 }, "254": { + "type": 15, "damage": 90, "dps": 33.33, "duration": 2700, "energy": 50 }, "255": { + "type": 3, "damage": 14, "dps": 11.67, "duration": 1200, "energy": 10 }, "256": { + "type": 3, "damage": 90, "dps": 45.0, "duration": 2000, "energy": 100 }, "257": { + "type": 3, "damage": 70, "dps": 35.0, "duration": 2000, "energy": 50 }, "258": { + "type": 5, "damage": 80, "dps": 20.0, "duration": 4000, "energy": 50 }, "259": { + "type": 6, "damage": 50, "dps": 23.81, "duration": 2100, "energy": 33 }, "260": { + "type": 7, "damage": 10, "dps": 9.09, "duration": 1100, "energy": 14 }, "261": { + "type": 7, "damage": 15, "dps": 10.0, "duration": 1500, "energy": 15 }, "262": { + "type": 7, "damage": 70, "dps": 18.92, "duration": 3700, "energy": 33 }, "263": { + "type": 8, "damage": 8, "dps": 7.27, "duration": 1100, "energy": 14 }, "264": { + "type": 8, "damage": 10, "dps": 8.33, "duration": 1200, "energy": 15 }, "265": { + "type": 8, "damage": 60, "dps": 23.08, "duration": 2600, "energy": 50 }, "266": { + "type": 9, "damage": 15, "dps": 13.64, "duration": 1100, "energy": 7 }, "267": { + "type": 9, "damage": 80, "dps": 24.24, "duration": 3300, "energy": 50 }, "268": { + "type": 9, "damage": 70, "dps": 33.33, "duration": 2100, "energy": 50 }, "269": { + "type": 10, "damage": 14, "dps": 12.73, "duration": 1100, "energy": 10 }, "270": { + "type": 10, "damage": 160, "dps": 40.0, "duration": 4000, "energy": 100 }, "271": { + "type": 12, "damage": 8, "dps": 7.27, "duration": 1100, "energy": 14 }, "272": { + "type": 12, "damage": 90, "dps": 34.62, "duration": 2600, "energy": 50 }, "273": { + "type": 12, "damage": 90, "dps": 23.08, "duration": 3900, "energy": 50 }, "274": { + "type": 14, "damage": 12, "dps": 10.91, "duration": 1100, "energy": 12 }, "275": { + "type": 14, "damage": 120, "dps": 44.44, "duration": 2700, "energy": 100 }, "276": { + "type": 14, "damage": 60, "dps": 23.08, "duration": 2600, "energy": 50 }, "277": { + "type": 16, "damage": 110, "dps": 28.21, "duration": 3900, "energy": 50 }, "278": { + "type": 18, "damage": 12, "dps": 10.91, "duration": 1100, "energy": 12 }, "279": { + "type": 18, "damage": 70, "dps": 21.88, "duration": 3200, "energy": 33 }, "280": { + "type": 18, "damage": 70, "dps": 35.0, "duration": 2000, "energy": 50 }, "281": { + "type": 1, "damage": 15, "dps": 10.0, "duration": 1500, "energy": 15 }, "282": { + "type": 1, "damage": 8, "dps": 6.7, "duration": 1200, "energy": 10 }, "283": { + "type": 11, "damage": 16, "dps": 13.33, "duration": 1200, "energy": 8 }, "284": { + "type": 11, "damage": 65, "dps": 29.5, "duration": 1700, "energy": 50 }, "285": { + "type": 16, "damage": 150, "dps": 36.6, "duration": 3600, "energy": 100 }, "286": { + "type": 9, "damage": 80, "dps": 36.4, "duration": 1700, "energy": 50 }, "287": { + "type": 1, "damage": 0, "dps": 0, "duration": 1700, "energy": 15 }, "288": { + "type": 14, "damage": 70, "dps": 15.6, "duration": 4000, "energy": 50 }, "289": { + "type": 11, "damage": 130, "dps": 59.1, "duration": 1700, "energy": 100 }, "290": { + "type": 5, "damage": 130, "dps": 59.1, "duration": 1700, "energy": 100 }, "291": { + "type": 1, "damage": 5, "dps": 3.8, "duration": 1300, diff --git a/data/weather_boosts.json b/data/weather_boosts.json index 367140d7a..2f39c9161 100644 --- a/data/weather_boosts.json +++ b/data/weather_boosts.json @@ -1,9 +1,9 @@ { - "1": [9, 11, 4], - "2": [10, 12, 6], - "3": [0, 5], - "4": [1, 16, 3], - "5": [15, 2, 13], - "6": [14, 8], - "7": [17, 7] + "1": [10, 12, 5], + "2": [11, 13, 7], + "3": [1, 6], + "4": [2, 17, 4], + "5": [16, 3, 14], + "6": [15, 9], + "7": [18, 8] } \ No newline at end of file diff --git a/docs/alarms/discord.md b/docs/alarms/discord.md deleted file mode 100644 index 6256d3076..000000000 --- a/docs/alarms/discord.md +++ /dev/null @@ -1,216 +0,0 @@ -# Discord - -## Overview - -* [Prerequisites](#prerequisites) -* [Introduction](#introduction) -* [Basic Config](#basic-config) - * [Required Parameters](#required-parameters) - * [Example: Basic Alarm Configuration using Required Parameters](#example-basic-alarm-configuration-using-required-parameters) -* [Advanced Config](#advanced-config) - * [Optional Parameters](#optional-parameters) - * [Example: Alarm Configuration Using Optional Parameters](#example-alarm-configuration-using-optional-parameters) - * [Mini Map Configuration](#mini-map-configuration) - * [Formatting alarms text](#formatting-alarms-text) -* [How to Enable Discord Webhooks](#how-to-enable-discord-webhooks) - -## Prerequisites - -This guide assumes - -1. You are familiar with [JSON formatting](https://www.w3schools.com/js/js_json_intro.asp) -2. You have read and understood the [Alarms](alarms) Wiki -3. You are comfortable with the layout of `alarms.json`. -4. You are using the latest version of PokeAlarm. - -Please familiarize yourself with all of the above before proceeding. - -## Introduction - -**Discord** is a free voice and text chat app designed specifically for -gaming. Available on Windows, Mac OS X, iOS and Android. It is also usable -from any Chrome, Firefox or Opera browser. - -PokeAlarm offers the following for Discord: - -* Custom username for posting -* High resolution icons for pokemon, gym, pokestop, egg or raid notifications -* Personalized notifications via [Dynamic Text Substitution](dynamic-text-substitution) - -## Basic Config - -### Required Parameters -The parameters below are required to enable the Discord alarm service: - -| Parameters | Description | -|----------------|-----------------------------------------| -| `type` | Must be `discord` | -| `active` | `True` for alarm to be active | -| `webhook_url`* | Your Webhook URL for a specific channel | - -**Note:** In PokeAlarm version 3.1, `webhook_url` replaced `api_key`. - -### Example: Basic Alarm Configuration using Required Parameters - -**Note:** The above below is to be inserted into the alarms section of -`alarms.json`. It does not represent the entire `alarms.json` file. - -```json -{ - "active":"True", - "type":"discord", - "webhook_url":"YOUR_WEBHOOK_URL" -} -``` - -## Advanced Config - -### Optional Parameters -In addition to the required parameters, several optional parameters are -available to personalize your notifications. Below is an example of these -optional parameters and how they are incorporated into a functional alarm layout. - -These optional parameters are entered at the same level as `"type":"discord"`. - -| Parameters | Description | -|--------------------|----------------------------------------------| -| `startup_message` | Confirmation post when PokeAlarm initialized | - -These optional parameters below are applicable to the `pokemon`, `pokestop`, -`gym`, `egg`, and `raid` sections of the JSON file. - -| Parameters | Description | Default | -|------------------|---------------------------------------------------|-----------------------------------------------| -| `webhook_url` | URL of specific channel name. Overrides `webhook_url` at Alarm level. Use to post only -| `disable_embed` | Disables the body to make one line notifications | `False` | -| `username` | Username the bot should post the message as | `` | -| `icon_url` | URL path to pokemon icon | | -| `avatar_url` | URL path to pokemon avatar | | -| `title` | Notification text to begin the message | `A wild has appeared!` | -| `url` | Link to be added to notification text | `` | -| `body` | Additional text to be added to the message | `Available until <24h_time> ().` | -| `content` | Text before the Discord embed | | - -*Note*: Nidorans will be `nidoranf` or `nidoranm`, Farfetch'd will be -`farfetchd`, and Mr. Mime will be `mrmime`. - -## Example: Alarm Configuration Using Optional Parameters - -**Note:** The code below is to be inserted into the alarms section of -`alarms.json`. It does not represent the entire `alarms.json` file. - -```json -{ - "active":"True", - "type":"discord", - "webhook_url":"YOUR_WEBHOOK_URL", - "startup_message":"False", - "pokemon":{ - "webhook_url":"YOUR_WEBHOOK_URL_FOR_POKEMON_CHANNEL", - "username":"", - "icon_url*":"/_.png", - "title":"A wild has appeared!", - "url":"", - "body":"Available until <24h_time> ()." - }, - "pokestop":{ - "webhook_url":"YOUR_WEBHOOK_URL_FOR_POKESTOP_CHANNEL", - "username":"Pokestop", - "icon_url*":"/ready.png", - "title":"Someone has placed a lure on a Pokestop!", - "url":"", - "body":"Lure will expire at <24h_time> ()." - }, - "gym":{ - "webhook_url":"YOUR_WEBHOOK_URL_FOR_GYM_CHANNEL", - "username":" Gym Alerts", - "icon_url*":"/.png", - "title":"A Team gym has fallen!", - "url":"", - "body":"It is now controlled by ." - }, - "egg":{ - "webhook_url":"DISCORD_WEBHOOK_URL_FOR_EGG_CHANNEL", - "username":"Egg", - "icon_url*":"/.png", - "avatar_url*":"/.png", - "title":"Raid is incoming!", - "url":"", - "body":"A level raid will hatch at <24h_hatch_time> ()." - }, - "raid":{ - "webhook_url":"DISCORD_WEBHOOK_URL_FOR_RAID_CHANNEL", - "username":"Raid", - "icon_url*":"/_000.png", - "avatar_url*":"/_000.png", - "title":"Level Raid is available against !", - "url":"", - "body":"The raid is available until <24h_raid_end> ()." - } -} -``` -**Note:** THESE LINES ARE USED TO OVERRIDE DEFAULT VALUES. IF YOU DO NOT -WISH TO USE CUSTOM IMAGES, DO NOT ADD THESE LINES TO YOUR ALARMS.JSON. - -### Mini Map Configuration -![](../images/minimap.png) - -You can enable a small Google Static Maps image after your post, showing the -location of the alarmed pokemon, gym, or pokestop. This is done by adding -the `map` parameter at the Alarm level (which will apply maps for any - notification), or individually to the `pokemon`, `pokestop`, `gym`, `egg`, - or `raid` sections of your alarm. - -Below is an example of enabling the mini map for pokemon. - -```json - "pokemon":{ - "webhook_url":"YOUR_WEBHOOK_URL_FOR_POKEMON_CHANNEL", - "username":"", - "title":"A wild has appeared!", - "url":"", - "body":"Available until <24h_time> ().", - "map":{ - "enabled":"true", - "width":"250", - "height":"125", - "maptype":"roadmap", - "zoom":"15" - } - }, -``` - -| Parameters | Description | Default | -|----------------|---------------------------------------------------|-----------------------------------------------| -| `enabled` | Turns the map on or off | `True` | -| `width` | Width of the map | `250` px | -| `height` | Height of the map | `150` px | -| `maptype` | Link to be added to notification text | `roadmap` | -| `zoom` | Specifies the zoom of the map | `15` | - -### Formatting alarms text - -Here is a basic guide to apply custom styles to alarm text: - -| Style | Example | -|------------------------------------|----------------------------------| -| `*italics*` | *italics* | -| `**bold**` | **bold** | -| `***bold italics***` | ***bold italics*** | -| `__underline__` | __underline__ | -| `__*underline italics*__` | __*underline italics*__ | -| `__**underline bold**__` | __**underline bold**__ | -| `__***underline bold italics***__` | __***underline bold italics***__ | -| `~~Strikethrough~~` | ~~Strikethrough~~ | - -You can see other options in the official Discord information about formatting text [here](https://support.discordapp.com/hc/en-us/articles/210298617-Markdown-Text-101-Chat-Formatting-Bold-Italic-Underline-). - -## How to enable Discord webhooks - -1. You must have the role permission 'Manage Webhooks', or be an administrator for the server. - -2. Go into channel settings, into the Webhooks tab. - -3. Click "Create Webhook", 'Save' - -4. The webhook URL listed is the key you need. diff --git a/docs/alarms/facebook-pages.md b/docs/alarms/facebook-pages.md deleted file mode 100644 index 69dcf3c98..000000000 --- a/docs/alarms/facebook-pages.md +++ /dev/null @@ -1,276 +0,0 @@ -# Facebook - -## Overview - -* [Prerequisites](#prerequisites) -* [Introduction](#introduction) -* [Basic Config](#basic-config) - * [Required Parameters](#required-parameters) - * [Example: Basic Alarm Configuration using Required Parameters](#example-basic-alarm-configuration-using-required-parameters) -* [Advanced Config](#advanced-config) - * [Optional Parameters](#optional-parameters) - * [Example: Alarm Configuration Using Optional Parameters](#example-alarm-configuration-using-optional-parameters) -* [How to get a Permanent Facebook Page Access Token](#how-to-get-a-permanent-facebook-page-token) - -## Prerequisites - -This guide assumes - -1. You are familiar with [JSON formatting](https://www.w3schools.com/js/js_json_intro.asp) -2. You have read and understood the [Alarms](alarms) Wiki -3. You are comfortable with the layout of `alarms.json`. - -Please familiarize yourself with all of the above before proceeding. - -## Introduction - -**Facebook Pages** is an online social networking service that enables users -to post status messages to a public profile specifically created for business, -brands, celebrities, causes, and other organizations. Registered users can -read and post messages, but those who are unregistered can only read them. -Users access Facebook through the website interface, SMS or mobile device app. - -PokeAlarm offers the following for Facebook Pages: - -* Personalized notifications via [Dynamic Text Substitution](dynamic-text-substitution) - -## Basic Config - -### Required Parameters -These `alarms.json` parameters - `active`, `type`, and `page_access_token` - -are required to enable the Facebook Pages alarm service: - -| Parameters | Description | -|--------------------|----------------------------------------| -| type | Must be `facebook_page` | -| active | `True` for alarm to be active | -| page_access_token | Your permanent FB page access token | - -### Example: Basic Alarm Configuration using Required Parameters - -```json -{ - "active":"True", - "type":"facebook_page", - "page_access_token":"YOUR_PAGE_ACCESS_TOKEN" -} -``` -**Note:** The above code is to be inserted into the alarms section of -alarms.json. It does not represent the entire alarms.json file. - -## Advanced Config - -### Optional Parameters - -In addition to the 3 required parameters, several optional parameters are -available to personalize your Facebook Pages notifications. Below is an -example of these optional parameters and how they are incorporated into a -functional alarm layout for Facebook Pages. - -These optional parameters are entered at the same level as `"type":"facebook_page"`. - -| Parameters | Description | Default | -|--------------------|------------------------------------------------------------|------------------------------| -| `startup_message` | Confirmation post when PokeAlarm initialized | `True` | - -These optional parameters below are applicable to the `pokemon`, `pokestop`, -`gym`, `egg`, and `raid` sections of the JSON file. -Check Image column to see where everything appears in the final publication. - -![Facebook Example](../images/fb-example.png) - -| Parameters | Description | Image | -|------------------|---------------------------------------------------|-------| -| `message` | Message to post as status message | 1 | -| `link` | Link to be added to notification text | Link | -| `image` | Url of the image to show as a preview (empty for linked page preview) | 2 | -| `name` | Link title (empty for linked page title) | 3 | -| `description` | Link description (empty for blank description) | 4 | -| `caption` | Link domain (empty for linked page domain) | 5 | - -When it says `"empty for X"` it means that you can disable the default -PokeAlarm value setting that parameter to `""` in your `alarms.json` file. -In that case Facebook will use the link information to fill that field in -the publication. - -For example if you have `link` as a google maps link and you disable the -`image` parameter setting it to `""`, it will be a minimap image of that -coordinates. - -`pokemon` default values: - -| Parameters | Default | -|------------------|-----------------------------------------------| -| `message` | `A wild has appeared!` | -| `image` | | -| `link` | `` | -| `name` | `` | -| `description` | `Available until <24h_time> ()` | -| `caption` | None | - -`pokestop` default values: - -| Parameters | Default | -|------------------|------------------------------------------------| -| `message` | `Someone has placed a lure on a Pokestop!` | -| `image` | | -| `link` | `` | -| `name` | `Lured Pokestop` | -| `description` | `Lure will expire at <24h_time> ()` | -| `caption` | None | - -`gym` default values: - -| Parameters | Default | -|------------------|-----------------------------------------------| -| `message` | `A Team gym has fallen!` | -| `image` | | -| `link` | `` | -| `name` | ` gym fallen` | -| `description` | `It is now controlled by ` | -| `caption` | None | - -`egg` default values: - -| Parameters | Default | -|------------------|-----------------------------------------------| -| `message` | `A level raid is upcoming!` | -| `image` | | -| `link` | `` | -| `name` | `Egg` | -| `description` | `A level raid will hatch at <24h_hatch_time> ().` | -| `caption` | None | - -`raid` default values: - -| Parameters | Default | -|------------------|-----------------------------------------------| -| `message` | `Level raid available against !` | -| `image` | | -| `link` | `` | -| `name` | `Raid` | -| `description` | `The raid is available until <24h_raid_end> ().` | -| `caption` | None | - -## Example: Alarm Configuration Using Optional Parameters - -```json -{ - "active":"True", - "type":"facebook_page", - "page_access_token":"YOUR_PAGE_ACCESS_TOKEN", - "startup_message":"True", - "pokemon":{ - "message":" available. / (% - //)", - "image*":"/_.png", - "link":"", - "description":"Address:
", - "name":"" - }, - "pokestop":{ - "message":"Someone has placed a lure on a Pokestop! Lure will expire at <24h_time> ().", - "image*":"/ready.png", - "description":"Address:
", - "link":"", - "name":"" - }, - "gym":{ - "message":"A Team gym has fallen! It is now controlled by .", - "image*":"/.png", - "link":"", - "name":"", - "description":"Address:
" - }, - "egg":{ - "message":"A level raid is upcoming!", - "image*":"/.png", - "link":"", - "name":"Egg", - "description":"A level raid will hatch at <24h_hatch_time> ()." - }, - "raid":{ - "message":"Level raid available against !", - "image*":"/_000.png", - "link":"", - "name":"Raid", - "description":"The raid is available until <24h_raid_end> ()." - } -} -``` -**Note1:** THESE LINES ARE USED TO OVERRIDE DEFAULT VALUES. IF YOU DO NOT WISH -TO USE CUSTOM IMAGES, DO NOT ADD THESE LINES TO YOUR ALARMS.JSON. - -**Note2:** The above code is to be inserted into the alarms section of -alarms.json. It does not represent the entire alarms.json file. - -## How to get a Permanent Facebook Page Token - -Use the [Graph API Explorer](https://developers.facebook.com/tools/explorer) -for all of these steps except where otherwise stated. - -### 0. Create Facebook App - -**If you already have an app**, skip to step 1. - -1. Go to [My Apps](https://developers.facebook.com/apps/). -2. Click "+ Add a New App". -3. Setup a website app. -4. Go to App Review of your new app and make sure your app is made Public. - -### 1. Get User Short-Lived Access Token - -1. Go to the [Graph API Explorer](https://developers.facebook.com/tools/explorer). -2. Select the application you want to get the access token for by clicking on -the "Graph API Explorer" dropdown near the top right. -3. Click "Get Token" dropdown and choose "Get User Access Token". -4. In the pop-up, under the "Events, Groups & Pages" section, check -"manage_pages" and "publish_pages". -5. Click "Get Access Token". -6. Grant access from a Facebook account that has access to manage the target -page. Note that if this user loses access the final, never-expiring access -token will likely stop working. - -Token that appears in the "Access Token" field is your short-lived access token. - -### 2. Generate Long-Lived Access Token - -Following [these instructions](https://developers.facebook.com/docs/facebook-login/access-tokens#extending) from the Facebook docs, make a GET request to - -`https://graph.facebook.com/v2.2/oauth/access_token?grant_type=fb_exchange_token&client_id={app_id}&client_secret={app_secret}&fb_exchange_token={short_lived_token}` - -entering in your app's ID and secret, generated from step 0, and the -short-lived token, generated in the previous step. Be sure to remove the curly -braces "{}" when replacing values. - -You **cannot use the Graph API Explorer**. For some reason it gets stuck on -this request. I think it's because the response isn't JSON, but a query string. -Since it's a GET request, you can just go to the URL in your browser. - -The response should look like this: - -`access_token=ABC123&expires=5182959` - -"ABC123" will be your long-lived access token. You can put it into the -[Access Token Debugger](https://developers.facebook.com/tools/debug/accesstoken) -to verify. Under "Expires" it should have something like "2 months". - -### 4. Get User ID - -Using the long-lived access token, make a GET request to - -`https://graph.facebook.com/v2.2/me?access_token={long_lived_access_token}` - -Be sure to remove the curly braces "{}" when replacing values. The **id** field -is your account ID. You'll need it for the next step. - -### 5. Get Permanent Page Access Token - -Make a GET request to - -`https://graph.facebook.com/v2.2/{account_id}/accounts?access_token={long_lived_access_token}` - -Be sure to remove the curly braces "{}" when replacing values. The JSON -response should have a **data** field under which is an array of items the -user has access to. Find the item for the page you want the permanent access -token from. The **access_token** field should have your permanent access token. -Copy it and test it in the [Access Token Debugger](https://developers.facebook.com/tools/debug/accesstoken). Under "Expires" it should say "Never". diff --git a/docs/alarms/pushbullet.md b/docs/alarms/pushbullet.md deleted file mode 100644 index f736ceec8..000000000 --- a/docs/alarms/pushbullet.md +++ /dev/null @@ -1,132 +0,0 @@ -# Pushbullet - -## Overview - -* [Prerequisites](#prerequisites) -* [Introduction](#introduction) -* [Basic Config](#basic-config) - * [Required Parameters](#required-parameters) - * [Example: Basic Alarm Configuration using Required Parameters](#example-basic-alarm-configuration-using-required-parameters) -* [Advanced Config](#advanced-config) - * [Optional Parameters](#optional-parameters) - * [Example: Alarm Configuration Using Optional Parameters](#example-alarm-configuration-using-optional-parameters) -* [How to Get a Pushbullet API Key](#how-to-get-a-pushbullet-api-key) - -## Prerequisites -This guide assumes: - -1. You are familiar with [JSON formatting](https://www.w3schools.com/js/js_json_intro.asp) -2. You have read and understood the [Alarms](alarms) Wiki -3. You are comfortable with the layout of `alarms.json`. - -Please familiarize yourself with all of the above before proceeding. - -## Introduction - -PokeAlarm offers the following for Pushbullet: - -* Notifications to multiple Pushbullet channels -* Customizable Google Map image of the pokemon, gym, pokestop, egg and/or raid location -* Personalized notifications via [Dynamic Text Substitution](dynamic-text-substitution) - -## Basic Config - -### Required Parameters - -These `alarm.json` parameters are required to enable the Pushbullet alarm service: - -| Parameters | Description | -|:-------------- |:---------------------------------------| -|`type` | must be `pushbullet` | -|`active` |`True` for alarm to be active | -|`api_key` | Your Pushbullet API key | - -### Example: Basic Alarm Configuration using Required Parameters - -Below is how a basic Pushbullet alarm configuration would appear in `alarms.json`. - -```json -{ - "active":"True", - "type":"pushbullet", - "api_key":"YOUR_API_KEY" -} -``` - -**Note:** The above code is to be inserted into the alarms section of -alarms.json. It does not represent the entire alarms.json file. - -## Advanced Config - -### Optional Parameters - -In addition to the required parameters, several `alarm.json` optional -parameters are available to personalize your notifications. Below is an -example of these optional parameters and how they are incorporated into a -functional alarm layout. - - -These optional parameters are entered at the same level as `"type":"pushbullet"`. - -| Parameters | Description | Default | -|:-------------------|:-----------------------------------------------------------|:-----------------------------| -| `startup_message` | Confirmation post when PokeAlarm initialized | `True` | - -These optional parameters below are applicable to the `pokemon`, `pokestop`, `gym`, `egg`, and `raid` sections of the JSON file. - -| Parameters | Description | Default | -|:-------------- |:--------------------------------------------------|:----------------------------------------------| -|`channel` | Channel tag of the target channel | Sends to all devices | -|`title` | Notification title attached to the push | `A wild has appeared!` | -|`url` | Link to be attached to the push | `` | -|`body` | Message attached to the push | `Available until <24h_time> ().` | - -### Example: Alarm Configuration Using Optional Parameters - -```json -{ - "active":"True", - "type":"pushbullet", - "api_key":"YOUR_API_KEY", - "channel":"DEFAULT_CHANNEL", - "pokemon":{ - "title":"A wild has appeared!", - "url":"", - "body":"Available until <24h_time> ().", - "channel":"OVERRIDES_DEFAULT_CHANNEL" - }, - "pokestop":{ - "title":"Someone has placed a lure on a Pokestop!", - "url":"", - "body":"Lure will expire at <24h_time> ().", - "channel":"OVERRIDES_DEFAULT_CHANNEL" - }, - "gym":{ - "title":"A Team gym has fallen!", - "url":"", - "body":"It is now controlled by .", - "channel":"OVERRIDES_DEFAULT_CHANNEL" - }, - "egg": { - "title": "A level raid is incoming!", - "url": "", - "body": "The egg will hatch <24h_hatch_time> ().", - "channel":"OVERRIDES_DEFAULT_CHANNEL" - }, - "raid": { - "title": "Level raid is available against !", - "url": "", - "body": "The raid is available until <24h_raid_end> ()." - } -} -``` -**Note:** The above code is to be inserted into the alarms section of -alarms.json. It does not represent the entire alarms.json file. - -## How to get a Pushbullet API Key - -1. Go to [Pushbullet](https://www.pushbullet.com/) and click one of the 'Sign up' options. - -2. In the top right corner, click on the letter and select 'My Account'. - -3. Scroll down to 'Create Access Token`. Copy this token and place it in api_key parameter. diff --git a/docs/alarms/slack.md b/docs/alarms/slack.md deleted file mode 100644 index 17454c10b..000000000 --- a/docs/alarms/slack.md +++ /dev/null @@ -1,222 +0,0 @@ -# Slack - -## Overview - -* [Prerequisites](#prerequisites) -* [Introduction](#introduction) -* [Basic Config](#basic-config) - * [Required Parameters](#required-parameters) - * [Example: Basic Alarm Configuration using Required Parameters](#example-basic-alarm-configuration-using-required-parameters) -* [Advanced Config](#advanced-config) - * [Optional Parameters](#optional-parameters) - * [Example: Alarm Configuration Using Optional Parameters](#example-alarm-configuration-using-optional-parameters) - * [Mini Map Configuration](#mini-map-configuration) - * [Formatting alarms text](#formatting-alarms-text) -* [How to Get a Slack API Key](#how-to-get-a-slack-api-key) - -## Prerequisites - -This guide assumes - -1. You are familiar with [JSON formatting](https://www.w3schools.com/js/js_json_intro.asp) -2. You have read and understood the [Alarms](alarms) Wiki -3. You are comfortable with the layout of `alarms.json`. -4. You are using the latest version of PokeAlarm. - -Please familiarize yourself with all of the above before proceeding. - -## Introduction - -![](../images/slack_demo.png) - -**Slack** is a cloud-based team collaboration tool that is available on -Windows, Mac OS X, Linux, iOS, Android, and Windows Phone. Slack offers a -lot of IRC-like features: persistent chat rooms (channels) organized by topic, -as well as private groups and direct messaging. All content inside Slack is -searchable, including files, conversations, and people. - -PokeAlarm offers the following for Slack: - -* Custom username for posting -* High resolution icons for pokemon, gym, pokestop, egg and/or raid notifications -* Notifications to multiple Slack channels and/or teams -* Customizable Google Map image of the pokemon, gym, pokestop, egg and/or raid location -* Personalized notifications via [Dynamic Text Substitution](dynamic-text-substitution) - -## Basic Config - -### Required Parameters -These parameters below are required to enable the Slack alarm service: - -| Parameters | Default | Description | -|-------------------|-------------|---------------------------------------| -| `type` | `slack` | `slack` | -| `active` | `False` | `True` for alarm to be active | -| `api_key` | | Your Slack API key | -| `channel` | `"general"` | Default channel to post notifications | - -### Example: Basic Alarm Configuration using Required Parameters - -```json -{ - "active":"True", - "type":"slack", - "api_key":"YOUR_API_KEY", - "channel":"general" -} -``` - -**Note:** The above code is to be inserted into the alarms section of -alarms.json. It does not represent the entire alarms.json file. - -## Advanced Config - -### Optional Parameters - -In addition to the 3 required parameters, several optional parameters are -available to personalize your Slack notifications. Below is an example of -these optional parameters and how they are incorporated into a functional -alarm layout for Slack. - -These optional parameters are entered at the same level as `"type":"slack"`. - -| Parameters | Description | -|--------------------|----------------------------------------------| -| `startup_message` | Confirmation post when PokeAlarm initialized | - -These optional parameters below are applicable to the `pokemon`, `pokestop`, -`gym`, `egg`, and `raid` sections of the JSON file. - -| Parameters | Description | Default | -|------------------|---------------------------------------------------|----------------------------------------------| -| `channel` | Send messages to this channel. | `#general` | -| `username` | Username the bot should post the message as | `` | -| `icon_url` | URL path to pokemon icon | | -| `title` | Notification text to begin the message | `A wild has appeared!` | -| `url` | Link to be added to notification text | `` | -| `body` | Additional text to be added to the message | `Available until <24h_time> ().` | -| `map` | Specify a json object to describe the map | See Mini Map Configuration for more details | - -*Note*: Nidorans will be `nidoranf` or `nidoranm`, Farfetch'd will be -`farfetchd`, and Mr. Mime will be `mrmime`. Channels that do not exist -(channels cannot be created by bots) will default to general instead. - -## Example: Alarm Configuration Using Optional Parameters - -```json -{ - "active":"True", - "type":"slack", - "api_key":"YOUR_API_KEY", - "channel":"general", - "startup_message":"True", - "pokemon":{ - "channel":"general", - "username":"", - "icon_url*":"/_.png", - "title":"A wild has appeared!", - "url":"", - "body":"Available until <24h_time> ().", - "map":{ - "enabled":"true", - "width":"250", - "height":"125", - "maptype":"roadmap", - "zoom":"15" - } - }, - "pokestop":{ - "channel":"general", - "username":"Pokestop", - "icon_url*":"/ready.png", - "title":"Someone has placed a lure on a Pokestop!", - "url":"", - "body":"Lure will expire at <24h_time> ()." - }, - "gym":{ - "channel":"general", - "username":" Gym Alerts", - "icon_url*":"/.png", - "title":"A Team gym has fallen!", - "url":"", - "body":"It is now controlled by ." - }, - "egg":{ - "username":"Egg", - "icon_url*":"/.png", - "title":"A level raid is incoming!", - "url":"", - "body":"The egg will hatch <24h_hatch_time> ()." - }, - "raid":{ - "username":" Raid", - "icon_url*":"/_000.png", - "title":"Level raid is available against !", - "url":"", - "body":"The raid is available until <24h_raid_end> ()." - } -} -``` -**Note1:** THESE LINES ARE USED TO OVERRIDE DEFAULT VALUES. IF YOU DO NOT -WISH TO USE CUSTOM IMAGES, DO NOT ADD THESE LINES TO YOUR ALARMS.JSON. - -**Note2:** The above code is to be inserted into the alarms section of -alarms.json. It does not represent the entire alarms.json file. - -### Mini Map Configuration - -![](../images/minimap.png) - -You can enable a small Google Static Maps image after your post, showing the -location of the alarmed pokemon, gym, or pokestop. This is done by adding the -`map` parameter at the Alarm level (which will apply maps for any - notification), or individually to the `pokemon`, `pokestop`, `gym`, `egg`, - or `raid` sections of your alarm. - -Below is an example of enabling the mini map for pokemon. - -```json - "pokemon":{ - "channel":"general", - "username":"", - "title":"A wild has appeared!", - "url":"", - "body":"Available until <24h_time> ().", - "map":{ - "enabled":"true", - "width":"250", - "height":"125", - "maptype":"roadmap", - "zoom":"15" - } - }, -``` - -| Parameters | Description | Default | -|----------------|---------------------------------------------------|-------------------------------------------| -| `enabled` | Turns the map on or off | `True` | -| `width` | Width of the map | `250` px | -| `height` | Height of the map | `150` px | -| `maptype` | Link to be added to notification text | `roadmap` | -| `zoom` | Specifies the zoom of the map | `15` | - -### Formatting alarms text - -Here is a basic guide to apply custom styles to alarm text: - -| Style | Example | -|------------------------------------|----------------------------------| -| `_italics_` | *italics* | -| `*bold*` | **bold** | -| `_*bold italics*_` | ***bold italics*** | -| `~Strikethrough~` | ~~Strikethrough~~ | - -You can see other options in the official Slack information about formatting text [here](https://get.slack.help/hc/en-us/articles/202288908-Format-your-messages). - -## How to get a Slack API Key - -1. Visit [slack.com](https://www.slack.com). Enter your email address and click 'Create your team'. Follow the instructions to setup and activate your account. - -2. Go to the [create a bot page](https://my.slack.com/services/new/bot). Enter a username and click create. - -3. Copy the API Token given. Fill out any more information you want, and click 'Save Integration'. diff --git a/docs/alarms/telegram.md b/docs/alarms/telegram.md deleted file mode 100644 index b80ac9492..000000000 --- a/docs/alarms/telegram.md +++ /dev/null @@ -1,187 +0,0 @@ -# Telegram - -## Overview - -* [Prerequisites](#prerequisites) -* [Introduction](#introduction) -* [Basic Config](#basic-config) - * [Required Parameters](#required-parameters) - * [Example: Basic Alarm Configuration using Required Parameters](#example-basic-alarm-configuration-using-required-parameters) -* [Advanced Config](#advanced-config) - * [Optional Parameters](#optional-parameters) - * [Example: Alarm Configuration Using Optional Parameters](#example-alarm-configuration-using-optional-parameters) - * [Formatting alarms text](#formatting-alarms-text) -* [How to Get a Telegram API Key](#how-to-get-a-telegram-api-key) -* [How to Create a Custom Channel](#how-to-create-a-custom-channel) - -## Prerequisites - -This guide assumes: - -1. You are familiar with [JSON formatting](https://www.w3schools.com/js/js_json_intro.asp) -2. You have read and understood the [Alarms](alarms) Wiki -3. You are comfortable with the layout of `alarms.json`. - -Please familiarize yourself with all of the above before proceeding. - -## Introduction - -![](../images/telegram.png) - -**Telegram** is a cloud-based instant messaging service. Telegram clients -exist for both mobile (Android, iOS, Windows Phone, Ubuntu Touch) and desktop -systems (Windows, OS X, Linux). Users can send messages and exchange photos, -videos, stickers and files of any type. - -PokeAlarm offers the following for Telegram: - -* Notifications to multiple Telegram channels -* Customizable Google Map image of the pokemon, gym, pokestop, egg and/or -raid location -* Personalized notifications via [Dynamic Text Substitution](dynamic-text-substitution) - -## Basic Config - -### Required Parameters - -These `alarm.json` parameters are required to enable the Telegram alarm service: - -| Parameters | Description | -|----------------|----------------------------------------| -| `type` | Must be `telegram` | -| `active` | `True` for alarm to be active | -| `bot_token` | Your Bot Token from Telegram | -| `chat_id` | Your chat's id from Telegram | - -### Example: Basic Alarm Configuration using Required Parameters - -Below is how a basic Telegram alarm configuration would appear in -`alarms.json`. Note that this is **not** the entire `alarms.json`, but only -the section pertaining to the alarm portion of the JSON file. - -```json -{ - "active":"True", - "type":"telegram", - "bot_token":"YOUR_BOT_TOKEN", - "chat_id":"YOUR_CHAT_ID" -} -``` - -## Advanced Config - -### Optional Parameters -In addition to the required parameters, several `alarm.json` optional -parameters are available to personalize your notifications. Below is an -example of these optional parameters and how they are incorporated into a -functional alarm layout. - -Parameters at the alarm level will be the default to alert-level parameters. - -| Parameters | Description | Default | -|----------------------------|----------------------------------------------------------------------|---------| -| `location` | Sends minimap after main message. | `True` | -| `disable_map_notification` | Disables map notifications. Set to `False` if you are experiencing notification issues on Android | `True` | -| `venue` | Sends location in main message. | `False` | -| `startup_message` | Confirmation post when PokeAlarm initialized | `True` | - -These optional parameters below are applicable to the `pokemon`, `pokestop`, -`gym`, `egg`, and `raid` sections of the JSON file. These parameters override -the alarm-level settings for this alert. - -| Parameters | Description | Default | -|------------|----------------------------------------------|----------------------------------------------------------| -| `title` | Header text for the message | `A wild has appeared!` | -| `body` | Additional text to be added to the message | `" \n Available until <24h_time> ()."` | -| `location` | Sends minimap after main message. | `True` | -| `disable_map_notification` | Disables map notifications. Set to `False` if you are experiencing notification issues on Android | `True` | -| `venue` | Sends location in main message. | `False` | -| `stickers` | Sends pokemon images as stickers in the message | `True` | - -### Example: Alarm Configuration Using Optional Parameters - -Below is how an advanced alarm configuration would appear in `alarms.json`. -Note that this is **not** the entire `alarms.json`, but only the section -pertaining to the alarm portion of the JSON file. - -```json -{ - "active":"True", - "type":"telegram", - "bot_token":"YOUR_BOT_TOKEN", - "chat_id":"YOUR_CHAT_ID", - "disable_map_notification":"False", - "startup_message":"True", - "stickers":"True", - "pokemon":{ - "chat_id":"OVERRIDES_DEFAULT_CHANNEL", - "title":"A wild has appeared!", - "body":"Available until <24h_time> ().", - "location":"True" - }, - "pokestop":{ - "chat_id":"OVERRIDES_DEFAULT_CHANNEL", - "title":"Someone has placed a lure on a Pokestop!", - "body":"Lure will expire at <24h_time> ().", - "location":"True" - }, - "gym":{ - "chat_id":"OVERRIDES_DEFAULT_CHANNEL", - "title":"A Team gym has fallen!", - "body":"It is now controlled by .", - "location":"True" - }, - "egg":{ - "chat_id":"OVERRIDES_DEFAULT_CHANNEL", - "title":"A level raid is incoming!", - "body":"The egg will hatch <24h_hatch_time> ().", - "location":"True" - }, - "raid":{ - "chat_id":"OVERRIDES_DEFAULT_CHANNEL", - "title":"A raid is available against !", - "body":"The raid is available until <24h_raid_end> ().", - "location":"True" - } -} -``` - -### Formatting alarms text - -Here is a basic guide to apply custom styles to alarm text: - -| Style | Example | -|------------------------------------|----------------------------------| -| `_italic text_` | *italics* | -| `*bold text*` | **bold** | -| `_*bold italics*_` | ***bold italics*** | - -You can see other options in the official Telegram information about formatting -text [here](https://core.telegram.org/bots/api#formatting-options). - -## How to get a Telegram API Key - -1. Go to [Telegram Web Client](https://telegram.org/dl/webogram). Enter your -phone number and follow the instructions to create your account. - -2. Talk to the [BotFather](https://telegram.me/botfather) to create a new bot. -Use the `/newbot` command and follow his instructions. It will give you an API -Token when you are finished. - -3. Start a conversation with your bot. In the top left click on the menu bars, -then click create group. Type in the name of the bot you previously created, -then click on it when it appears below. Then click next. Type any message to -your bot. - -4. Enter your bot_token in to replace the `` in the following -url `https://api.telegram.org/bot/getUpdates`. Then go to it, -and find the section that says `"chat":{"id":`. This number is your -chat_id. - -## How to Create a Custom Channel - -1. Create a Public Channel (Currently doesn't work from the web app). - -2. Add your bot as an administrator for the channel. - -3. The chat_id for your bot will be `@channel_url`. diff --git a/docs/alarms/twilio.md b/docs/alarms/twilio.md deleted file mode 100644 index c3fa46803..000000000 --- a/docs/alarms/twilio.md +++ /dev/null @@ -1,172 +0,0 @@ -# Twilio (SMS) - -## Overview - -* [Prerequisites](#prerequisites) -* [Introduction](#introduction) -* [Basic Config](#basic-config) - * [Required Parameters](#required-parameters) - * [Example: Basic Alarm Configuration using Required Parameters](#example-basic-alarm-configuration-using-required-parameters) -* [Advanced Config](#advanced-config) - * [Multiple Destinations](#multiple-destinations) - * [Optional Parameters](#optional-parameters) - * [Example: Alarm Configuration Using Optional Parameters](#example-alarm-configuration-using-optional-parameters) -* [How to get the Account SID, Auth Token, and Twilio Number](#how-to-get-the-account-sid-auth-token-and-twilio-number) - -## Prerequisites - -This guide assumes: - -1. You are familiar with [JSON formatting](https://www.w3schools.com/js/js_json_intro.asp) -2. You have read and understood the [Alarms](alarms) Wiki -3. You are comfortable with the layout of `alarms.json`. - -## Introduction - -**Twilio** allows software developers to programmatically make and receive -phone calls and send and receive text messages using its web service APIs. - -PokeAlarm offers the following for Twilio: - -* Personalized notifications via [Dynamic Text Substitution](dynamic-text-substitution) - -## Basic Config - -These `alarms.json` parameters are required to enable the alarm service: - -### Required Parameters - -| Parameters | Description | -|:-------------- |:---------------------------------------| -|`type` | must be `twilio` | -|`active` | 'True' for alarm to be active | -|`account_sid` | Your Account SID from Twilio | -|`auth_token` | Your Auth Token from Twilio | -|`from_number` | Your Twilio number to send from | -|`to_number` | Your number to receive texts from | - -### Example: Basic Alarm Configuration using Required Parameters - -```json -{ - "active": "True", - "type":"twilio", - "account_sid":"YOUR_API_KEY", - "auth_token":"YOUR_AUTH_TOKEN", - "from_number":"YOUR_FROM_NUM", - "to_number":"YOUR_TO_NUM" -} -``` -**Note:** The above code is to be inserted into the alarms section of -alarms.json. It does not represent the entire alarms.json file. - -## Advanced Config -In addition to the above required parameters, several optional parameters -are available to personalize your notifications. - -### Multiple Destinations - -The `to_number` field can accept either a single destination phone number or -an array of phone numbers to send SMS messages to. This allows for sending SMS -alerts to multiple destinations. - -#### Example - -Below is an example of using an array for the destination number(s) in the -alarm configuration. - -```json -{ - "active": "True", - "type":"twilio", - "account_sid":"YOUR_API_KEY", - "auth_token":"YOUR_AUTH_TOKEN", - "from_number":"YOUR_FROM_NUM", - "to_number": [ "YOUR_1ST_TO_NUM", "YOUR_2ND_TO_NUM", "YOUR_3RD_TO_NUM" ] -} -``` -### Optional Parameters - -These optional parameters below are applicable to the `pokemon`, `pokestop`, -`gym`, `egg`, and `raid` alarm code of the JSON file. - -#### Optional Pokemon Parameters -| Parameters | Description | Default | -|:------------|:--------------------------------|:-----------------------------------------------------------| -|`message` | Text message for pokemon updates | `"A wild has appeared! Available until <24h_time> ()."` | - -#### Optional Pokestop Parameters -| Parameters | Description | Default | -|:------------|:---------------------------------------|:--------------------------------------------------------------| -|`message` | Text message for pokestop updates | `"Someone has placed a lure on a Pokestop! Lure will expire at <24h_time> ()."` | - -#### Optional Gym Parameters -| Parameters | Description | Default | -|:------------|:-------------------------------------|:--------------------------------------------------------------| -|`message` | Text message for gym updates | `"A Team gym has fallen! It is now controlled by ."` | - -#### Optional Egg Parameters -| Parameters | Description | Default | -|:------------|:-------------------------------------|:--------------------------------------------------------------| -|`message` | Text message for egg updates | `"A level raid is incoming! Egg hatches <24h_hatch_time> ()."` | - -#### Optional Raid Parameters -| Parameters | Description | Default | -|:------------|:-------------------------------------|:--------------------------------------------------------------| -|`message` | Text message for raid updates | `"Level raid against ! Available until <24h_raid_end> ()."` | - - -#### Example: Alarm Configuration Using Optional Parameters - -Below is an example of these optional parameters and how they are incorporated -into a functional alarm layout. - -```json -{ - "active": "True", - "type":"twilio", - "account_sid":"YOUR_API_KEY", - "auth_token":"YOUR_AUTH_TOKEN", - "from_number":"YOUR_FROM_NUM", - "to_number":"YOUR_TO_NUM", - "pokemon":{ - "from_number":"YOUR_FROM_NUM", - "to_number":"YOUR_TO_NUM", - "message": "A wild has appeared! Available until <24h_time> ()." - }, - "pokestop":{ - "from_number":"YOUR_FROM_NUM", - "to_number":"YOUR_TO_NUM", - "message": "Someone has placed a lure on a Pokestop! Lure will expire at <24h_time> ()." - }, - "gym":{ - "from_number":"YOUR_FROM_NUM", - "to_number":"YOUR_TO_NUM", - "message": "A Team gym has fallen! It is now controlled by ." - }, - "egg": { - "message": "A level raid is incoming! Egg hatches <24h_hatch_time> ()." - }, - "raid": { - "message": "Level raid against ! Available until <24h_raid_end> ()." - } -} -``` -**Note:** The above code is to be inserted into the alarms section of -alarms.json. It does not represent the entire alarms.json file. - -## How to get the Account SID, Auth Token, and Twilio Number - -1. Go to [Twilio](https://www.twilio.com) and click 'Get a free API key'. -Fill out the following form, and enter your phone number to verify your account. - -2. On the left hand side, click the Home Button and then click Dashboard. -The **Account SID** and **Auth Token** will be listed. To reveal the Auth -Token, click on the lock next to it. - -3. Scroll down and click on '# Phone Numbers'. Then click 'Get Started' to -get your free number. - -4. If you wish to text to different numbers, you need to register each before -you are allowed to message them. This can be done from the 'Verified Caller -ID's' page. diff --git a/docs/alarms/twitter.md b/docs/alarms/twitter.md deleted file mode 100644 index 08c844bfb..000000000 --- a/docs/alarms/twitter.md +++ /dev/null @@ -1,145 +0,0 @@ -# Twitter - -## Overview - -* [Prerequisites](#prerequisites) -* [Introduction](#introduction) -* [Basic Config](#basic-config) - * [Required Parameters](#required-parameters) - * [Example: Basic Alarm Configuration using Required Parameters](#example-basic-alarm-configuration-using-required-parameters) -* [Advanced Config](#advanced-config) - * [Optional Parameters](#optional-parameters) - * [Example: Alarm Configuration Using Optional Parameters](#example-alarm-configuration-using-optional-parameters) -* [How to Get a Twitter API Key](#how-to-get-a-twitter-api-key) - -## Prerequisites - -This guide assumes: - -1. You are familiar with [JSON formatting](https://www.w3schools.com/js/js_json_intro.asp) -2. You have read and understood the [Alarms](alarms) Wiki -3. You are comfortable with the layout of `alarms.json`. - -Please familiarize yourself with all of the above before proceeding. - -## Introduction - -**Twitter** is an online social networking service that enables users to send -and read short 140-character messages called "tweets". Registered users can -read and post tweets, but those who are unregistered can only read them. Users -access Twitter through the website interface, SMS or mobile device app. - -PokeAlarm offers the following for Twitter: - -* Personalized notifications via [Dynamic Text Substitution](dynamic-text-substitution) - -## Basic Config - -### Required Parameters - -These `alarm.json` parameters are required to enable the Twitter alarm service: - -| Parameters | Description | -|:-----------------|:---------------------------------------| -| `type` | must be `twitter` | -| `active` |`True` for alarm to be active | -| `access_token` | Your twitter access token | -| `access_secret` | Your twitter access secret | -| `consumer_key` | Your twitter consumer key | -| `consumer_secret`| Your twitter consumer secret | - -### Example: Basic Alarm Configuration using Required Parameters - -```json -{ - "active": "False", - "type": "twitter", - "access_token": "YOUR_ACCESS_TOKEN", - "access_secret": "YOUR_ACCESS_SECRET", - "consumer_key": "YOUR_CONSUMER_KEY", - "consumer_secret": "YOUR_CONSUMER_SECRET" -} -``` -**Note:** The above code is to be inserted into the alarms section of -`alarms.json`. It does not represent the entire `alarms.json` file. - -## Advanced Config - -### Optional Parameters - -In addition to the required parameters, several `alarm.json` optional -parameters are available to personalize your notifications. Below is an -example of these optional parameters and how they are incorporated into a -functional alarm layout. - -These optional parameters are entered at the same level as `"type":"twitter"`. - -| Parameters | Description | Default | -|:-------------------|:---------------------------------------------------|:-----------------------------| -| `startup_message` | Confirmation post when PokeAlarm initialized | `True` | - -These optional parameters below are applicable to the `pokemon`, `pokestop`, -`gym`, `egg`, and `raid` sections of the JSON file. - - -| Parameters | Description | Default | -|:----------------|:-------------------------------------|:----------------------------------------------| -| `status` | Message to post as status | `A wild has appeared! Available until <24h_time> (). ` | - -### Example: Alarm Configuration Using Optional Parameters - -```json -{ - "active": "False", - "type": "twitter", - "access_token": "YOUR_ACCESS_TOKEN", - "access_secret": "YOUR_ACCESS_SECRET", - "consumer_key": "YOUR_CONSUMER_KEY", - "consumer_secret": "YOUR_CONSUMER_SECRET", - "pokemon":{ - "status": "A wild has appeared! Available until <24h_time> (). " - }, - "pokestop":{ - "status": "Someone has placed a lure on a Pokestop! Lure will expire at <24h_time> (). " - }, - "gym":{ - "status":"A Team gym has fallen! It is now controlled by . " - }, - "egg": { - "status": "Level raid incoming! Hatches at <24h_hatch_time> (). " - }, - "raid": { - "status": "Raid against ! Available until <24h_raid_end> (). " - } -} -``` -**Note:** The above code is to be inserted into the alarms section of -`alarms.json`. It does not represent the entire `alarms.json` file. - -For more information on text substitutions, please see the main -configuration page. - -## How to get a Twitter API Key - -### Step 1: Create a Twitter account -* Go to [Twitter's signup page](https://twitter.com/signup) -* Fill out all details, and **make sure to include your phone number**. -This is a requirement for remote access, and you will need that to make -the Twitter bot work. - -### Step 2: Create a Twitter app -* Go to [apps.twitter.com](https://apps.twitter.com) -* Click 'Create New App' button -* Fill out the details on the form. You have to give your app a name, -description, and website. This can be a simple place holder like http://www.example.com -* Read the Developer Agreement, and check the box at the bottom if you agree. -Then click on the ‘Create your Twitter application’ button. - -### Step 3: Keys and Access tokens -* After creating your new app, you were redirected to its own page. If you -weren’t, go to [apps.twitter.com](https://apps.twitter.com) and click on your -apps name. -* On the app’s page, click on the ‘Keys and Access Tokens’ page. -* At the bottom of this page, click on the ‘Create my access token’ button. -* Take note of **Consumer Key (API Key), Consumer Secret (API Secret), Access -Token, & Access Token Secret**. These are the are required in the Twitter Config. diff --git a/docs/conf.py b/docs/conf.py index 06f948cc0..d260054a5 100755 --- a/docs/conf.py +++ b/docs/conf.py @@ -17,7 +17,7 @@ # documentation root, use os.path.abspath to make it absolute, like shown here. # import datetime -# import os +import os # import sys # sys.path.insert(0, os.path.abspath('.')) @@ -64,9 +64,9 @@ # built documents. # # The short X.Y version. -version = u'3.5' +version = u'3.6' # The full version, including alpha/beta/rc tags. -release = u'3.5' +release = u'3.6' # The language for content autogenerated by Sphinx. Refer to documentation # for a list of supported languages. @@ -92,7 +92,8 @@ # The theme to use for HTML and HTML Help pages. See the documentation for # a list of builtin themes. # -html_theme = 'sphinx_rtd_theme' +# html_theme = 'sphinx_rtd_theme' +html_theme = 'default' # Theme options are theme-specific and customize the look and feel of a theme # further. For a list of options available for each theme, see the @@ -100,10 +101,44 @@ # # html_theme_options = {} + +# From: +# * https://github.com/snide/sphinx_rtd_theme +# using-this-theme-locally-then-building-on-read-the-docs +# on_rtd is whether we are on readthedocs.org, this +# line of code grabbed from docs.readthedocs.org +on_rtd = os.environ.get('READTHEDOCS', None) == 'True' + +# only import and set the theme if we're building docs locally +if not on_rtd: + import sphinx_rtd_theme + html_theme = 'sphinx_rtd_theme' + html_theme_path = [sphinx_rtd_theme.get_html_theme_path()] + +# Suppress warnings: http://stackoverflow.com/a/28778969/2288008 +if not on_rtd: + import sphinx.environment + from docutils.utils import get_source_line + + def _warn_node(self, msg, node, **kwargs): + if not msg.startswith('nonlocal image URI found:'): + self._warnfunc(msg, '%s:%s' % get_source_line(node), **kwargs) + + sphinx.environment.BuildEnvironment.warn_node = _warn_node + # Add any paths that contain custom static files (such as style sheets) here, # relative to this directory. They are copied after the builtin static files, # so a file named "default.css" will overwrite the builtin "default.css". -html_static_path = ['.static'] +# html_static_path = ['.static'] +html_static_path = ['.static', 'css'] + +# Add custom .css files +# https://github.com/snide/sphinx_rtd_theme/issues/117#issuecomment-41571653 + + +def setup(app): + app.add_stylesheet("custom.css") + # Custom sidebar templates, must be a dictionary that maps document names # to template names. diff --git a/docs/configuration/alarms/discord.rst b/docs/configuration/alarms/discord.rst new file mode 100644 index 000000000..affc175f3 --- /dev/null +++ b/docs/configuration/alarms/discord.rst @@ -0,0 +1,269 @@ +Discord +===================================== + +.. contents:: Table of Contents + :depth: 2 + :local: + +.. role:: boltitalic + :class: boltitalic + +.. role:: underline + :class: underline + +.. role:: underlinebold + :class: underlinebold + +.. role:: underlineitalic + :class: underlineitalic + +.. role:: underlineboita + :class: underlineboita + +.. role:: strike + :class: strike + + +Prerequisites +------------------------------------- + +This guide assumes + ++ You are familiar with `JSON formatting `_. ++ You have read and understood the :doc:`index` wiki. ++ You are comfortable with the layout of ``alarms.json``. ++ You are using the latest version of PokeAlarm. + +Please familiarize yourself with all of the above before proceeding. + + +Introduction +------------------------------------- + +**Discord** is a free voice and text chat app designed specifically for gaming. +Available on Windows, Mac OS X, iOS and Android. It is also usable from any +Chrome, Firefox or Opera browser. + +PokeAlarm offers the following for Discord: + ++ Custom username for posting ++ High resolution icons for pokemon, gym, pokestop, egg or raid notifications ++ Personalized notifications via :doc:`../events/index` + + +Basic Config +------------------------------------- + + +Required Parameters +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +The parameters below are required to enable the Discord alarm service: + +=============== ======================================== +Parameters Description +=============== ======================================== +`type` Must be ``"discord"`` +`active` ``true`` for alarm to be active +`webhook_url` * Your Webhook URL for a specific channel +=============== ======================================== + +.. note:: \*In PokeAlarm version 3.1, `webhook_url` replaced `api_key`. + + +Example: Basic Alarm Configuration using Required Parameters +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +.. note:: + The above below is to be inserted into the alarms section of + `alarms.json`. It does not represent the entire `alarms.json` file. + +.. code-block:: json + + { + "active":true, + "type":"discord", + "webhook_url":"YOUR_WEBHOOK_URL" + } + + +Advanced Config +------------------------------------- + +Optional Parameters +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +In addition to the required parameters, several optional parameters are +available to personalize your notifications. Below is an example of these +optional parameters and how they are incorporated into a functional alarm layout. + +These optional parameters are entered at the same level as ``"type":"discord"``. + ++-------------------+-----------------------------------------------+----------+ +| Parameters | Description | Default | ++-------------------+-----------------------------------------------+----------+ +| `startup_message` | Confirmation post when PokeAlarm initialized | ``true`` | ++-------------------+-----------------------------------------------+----------+ + +These optional parameters below are applicable to the ``monsters``, ``stops``, +``gyms``, ``eggs``, and ``raids`` sections of the JSON file. + +=============== ================================================ ========================================== +Parameters Description Default +=============== ================================================ ========================================== +`webhook_url` URL of specific channel name. Overrides + `webhook_url` at Alarm level. Use to post only +`disable_embed` Disables the body to make one line notifications ``false`` +`username` Username the bot should post the message as ```` +`icon_url` URL path to icon +`avatar_url` URL path to avatar +`title` Notification text to begin the message ``A wild has appeared!`` +`url` Link to be added to notification text ```` +`body` Additional text to be added to the message ``Available until <24h_time>().`` +`content` Text before the Discord embed +=============== ================================================ =========================================== + +.. note:: + Nidorans will be ``nidoranf`` or ``nidoranm``, Farfetch'd will be + ``farfetchd``, and Mr. Mime will be ``mrmime``. + + +Example: Alarm Configuration Using Optional Parameters +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +.. note:: + The code below is to be inserted into the alarms section of + ``alarms.json``. It does not represent the entire ``alarms.json`` file. + +.. code-block:: json + + { + "discord_alarm":{ + "active":true, + "type":"discord", + "webhook_url":"YOUR_WEBHOOK_URL", + "startup_message":false, + "monsters":{ + "webhook_url":"YOUR_WEBHOOK_URL_FOR_POKEMON_CHANNEL", + "username":"", + "icon_url*":"/_.png", + "title":"A wild has appeared!", + "url":"", + "body":"Available until <24h_time> ()." + }, + "stops":{ + "webhook_url":"YOUR_WEBHOOK_URL_FOR_POKESTOP_CHANNEL", + "username":"Pokestop", + "icon_url*":"/ready.png", + "title":"Someone has placed a lure on a Pokestop!", + "url":"", + "body":"Lure will expire at <24h_time> ()." + }, + "gyms":{ + "webhook_url":"YOUR_WEBHOOK_URL_FOR_GYM_CHANNEL", + "username":" Gym Alerts", + "icon_url*":"/.png", + "title":"A Team gym has fallen!", + "url":"", + "body":"It is now controlled by ." + }, + "eggs":{ + "webhook_url":"DISCORD_WEBHOOK_URL_FOR_EGG_CHANNEL", + "username":"Egg", + "icon_url*":"/.png", + "avatar_url*":"/.png", + "title":"Raid is incoming!", + "url":"", + "body":"A level raid will hatch at <24h_hatch_time> ()." + }, + "raids":{ + "webhook_url":"DISCORD_WEBHOOK_URL_FOR_RAID_CHANNEL", + "username":"Raid", + "icon_url*":"/_000.png", + "avatar_url*":"/_000.png", + "title":"Level Raid is available against !", + "url":"", + "body":"The raid is available until <24h_raid_end> ()." + } + } + } + +.. note:: + \*THESE LINES ARE USED TO OVERRIDE DEFAULT VALUES. IF YOU DO NOT WISH + TO USE CUSTOM IMAGES, DO NOT ADD THESE LINES TO YOUR ALARMS.JSON. + +Mini Map Configuration +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +.. image:: ../../images/minimap.png + +You can enable a small Google Static Maps image after your post, showing the +location of the alarmed pokemon, gym, pokestop, egg, or raid. This is done by +adding the ``map`` parameter at the Alarm level (which will apply maps for any +notification), or individually to the ``monsters``, ``stops``, ``gyms``, +``eggs``, or ``raids`` sections of your alarm. + +Below is an example of enabling the mini map for pokemon. + +.. code-block:: json + + "monsters":{ + "webhook_url":"YOUR_WEBHOOK_URL_FOR_POKEMON_CHANNEL", + "username":"", + "title":"A wild has appeared!", + "url":"", + "body":"Available until <24h_time> ().", + "map":{ + "enabled":true, + "width":"250", + "height":"125", + "maptype":"roadmap", + "zoom":"15" + } + }, + + +=========== ====================================== ============= +Parameters Description Default +=========== ====================================== ============= +`enabled` Turns the map on or off ``true`` +`width` Width of the map ``"250"`` px +`height` Height of the map ``"150"`` px +`maptype` Link to be added to notification text ``"roadmap"`` +`zoom` Specifies the zoom of the map ``"15"`` +=========== ====================================== ============= + + +Formatting alarms text +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Here is a basic guide to apply custom styles to alarm text: + +=================================== ======================================== +Style Example +=================================== ======================================== +`*italics*` *italics* +`**bold**` **bold** +`***bold italics***` :boltitalic:`bold italics` +`__underline__` :underline:`underline` +`__*underline italics*__` :underlineitalic:`underline italics` +`__**underline bold**__` :underlinebold:`underline bold` +`__***underline bold italics***__` :underlineboita:`underline bold italics` +`~~strikethrough~~` :strike:`strikethrough` +=================================== ======================================== + +You can see other options in the official Discord information about +formatting text `here `_. + + +How to enable Discord webhooks +------------------------------------- + +1. You must have the role permission ``Manage Webhooks``, or be an administrator + for the server. + +2. Go into channel settings, into the Webhooks tab. + +3. Click ``Create Webhook``, ``Save`` + +4. The webhook URL listed is the key you need. diff --git a/docs/configuration/alarms/facebook-pages.rst b/docs/configuration/alarms/facebook-pages.rst new file mode 100644 index 000000000..551b7c150 --- /dev/null +++ b/docs/configuration/alarms/facebook-pages.rst @@ -0,0 +1,315 @@ +Facebook Pages +===================================== + +.. contents:: Table of Contents + :depth: 2 + :local: + + +Prerequisites +------------------------------------- + +This guide assumes + ++ You are familiar with `JSON formatting `_. ++ You have read and understood the :doc:`index` wiki. ++ You are comfortable with the layout of ``alarms.json``. ++ You are using the latest version of PokeAlarm. + +Please familiarize yourself with all of the above before proceeding. + + +Introduction +------------------------------------- + +**Facebook Pages** is an online social networking service that enables users to +post status messages to a public profile specifically created for business, +brands, celebrities, causes, and other organizations. Registered users can read +and post messages, but those who are unregistered can only read them. Users +access Facebook through the website interface, SMS or mobile device app. + +PokeAlarm offers the following for Facebook Pages: + ++ Personalized notifications via :doc:`../events/index` + + +Basic Config +------------------------------------- + + +Required Parameters +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +These ``alarms.json`` parameters - ``active``, ``type``, and ``page_access_token`` - +are required to enable the Facebook Pages alarm service: + +================= ===================================== +Parameters Description +================= ===================================== +type Must be ``"facebook_page"`` +active ``true`` for alarm to be active +page_access_token Your permanent FB page access token +================= ===================================== + +Example: Basic Alarm Configuration using Required Parameters +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +.. code-block:: json + + { + "active":true, + "type":"facebook_page", + "page_access_token":"YOUR_PAGE_ACCESS_TOKEN" + } + +.. note:: + The above code is to be inserted into the alarms section of + alarms.json. It does not represent the entire alarms.json file. + + +Advanced Config +------------------------------------- + +Optional Parameters +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +In addition to the 3 required parameters, several optional parameters are +available to personalize your Facebook Pages notifications. Below is an +example of these optional parameters and how they are incorporated into a +functional alarm layout for Facebook Pages. + +These optional parameters are entered at the same level as ``"type":"facebook_page"``. + ++-------------------+-----------------------------------------------+----------+ +| Parameters | Description | Default | ++-------------------+-----------------------------------------------+----------+ +| `startup_message` | Confirmation post when PokeAlarm initialized | ``true`` | ++-------------------+-----------------------------------------------+----------+ + +These optional parameters below are applicable to the ``monsters``, ``stops``, +``gyms``, ``eggs``, and ``raids`` sections of the JSON file. Check Image column to +see where everything appears in the final publication. + +.. image:: ../../images/fb-example.png + +=============== =============================================== ====== +Parameters Description Image +=============== =============================================== ====== +`message` Message to post as status message 1 +`link` Link to be added to notification text Link +`image` Url of the image to show as a preview (empty 2 + for linked page preview) +`name` Link title (empty for linked page title) 3 +`description` Link description (empty for blank description) 4 +`caption` Link domain (empty for linked page domain) 5 +=============== =============================================== ====== + +When it says ``"empty for X"`` it means that you can disable the default +PokeAlarm value setting that parameter to ``""`` in your ``alarms.json`` file. +In that case Facebook will use the link information to fill that field in the +publication. + +For example if you have ``link`` as a google maps link and you disable the +``image`` parameter setting it to ``""``, it will be a minimap image of that +coordinates. + +``monsters`` default values: + +=============== =============================================== +Parameters Default +=============== =============================================== +`message` ``A wild has appeared!`` +`image` +`link` ```` +`name` ```` +`description` ``Available until <24h_time> ()`` +`caption` None +=============== =============================================== + +``stops`` default values: + +=============== =============================================== +Parameters Default +=============== =============================================== +`message` ``Someone has placed a lure on a Pokestop!`` +`image` +`link` ```` +`name` ``Lured Pokestop`` +`description` ``Lure will expire at <24h_time> ()`` +`caption` None +=============== =============================================== + +``gyms`` default values: + +=============== ===================================== +Parameters Default +=============== ===================================== +`message` ``A Team gym has fallen!`` +`image` +`link` ```` +`name` `` gym fallen`` +`description` ``It is now controlled by `` +`caption` None +=============== ===================================== + +``eggs`` default values: + +============== ======================================================= +Parameters Default +============== ======================================================= +`message` ``A level raid is upcoming!`` +`image` +`link` ```` +`name` ``Egg`` +`description` ``A level raid will hatch at <24h_hatch_time> + ().`` +`caption` None +============== ======================================================= + +``raids`` default values: + +=============== ======================================================= +Parameters Default +=============== ======================================================= +`message` ``Level raid available against !`` +`image` +`link` ```` +`name` ``Raid`` +`description` ``The raid is available until <24h_raid_end> + ().`` +`caption` None +=============== ======================================================= + + +Example: Alarm Configuration Using Optional Parameters +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +.. code-block:: json + + { + "facebook_alarm":{ + "active":true, + "type":"facebook_page", + "page_access_token":"YOUR_PAGE_ACCESS_TOKEN", + "startup_message":false, + "monsters":{ + "message":" available. / (% - //)", + "image*":"/_.png", + "link":"", + "description":"Address:
", + "name":"" + }, + "stops":{ + "message":"Someone has placed a lure on a Pokestop! Lure will expire at <24h_time> ().", + "image*":"/ready.png", + "description":"Address:
", + "link":"", + "name":"" + }, + "gyms":{ + "message":"A Team gym has fallen! It is now controlled by .", + "image*":"/.png", + "link":"", + "name":"", + "description":"Address:
" + }, + "eggs":{ + "message":"A level raid is upcoming!", + "image*":"/.png", + "link":"", + "name":"Egg", + "description":"A level raid will hatch at <24h_hatch_time> ()." + }, + "raids":{ + "message":"Level raid available against !", + "image*":"/_000.png", + "link":"", + "name":"Raid", + "description":"The raid is available until <24h_raid_end> ()." + } + } + } + +.. note:: + \*THESE LINES ARE USED TO OVERRIDE DEFAULT VALUES. IF YOU DO NOT WISH + TO USE CUSTOM IMAGES, DO NOT ADD THESE LINES TO YOUR ALARMS.JSON. + + The above code is to be inserted into the alarms section of + alarms.json. It does not represent the entire alarms.json file. + + +How to get a Permanent Facebook Page Token +------------------------------------- + +Use the `Graph API Explorer `_ +for all of these steps except where otherwise stated. + +**0. Create Facebook App** + +**If you already have an app**, skip to step 1. + +1. Go to `My Apps `_. +2. Click ``+ Add a New App``. +3. Setup a website app. +4. Go to App Review of your new app and make sure your app is made Public. + +**1. Get User Short-Lived Access Token** + +1. Go to the `Graph API Explorer `_. +2. Select the application you want to get the access token for by clicking on + the ``Graph API Explorer`` dropdown near the top right. +3. Click ``Get Token`` dropdown and choose ``Get User Access Token``. +4. In the pop-up, under the ``Events, Groups & Pages`` section, check + ``manage_pages`` and ``publish_pages``. +5. Click ``Get Access Token``. +6. Grant access from a Facebook account that has access to manage the target + page. Note that if this user loses access the final, never-expiring access + token will likely stop working. + +Token that appears in the ``Access Token`` field is your short-lived access token. + +**2. Generate Long-Lived Access Token** + +Following `these instructions `_ +from the Facebook docs, make a GET request to + +``https://graph.facebook.com/v2.2/oauth/access_token?grant_type=fb_exchange_token&client_id={app_id}&client_secret={app_secret}&fb_exchange_token={short_lived_token}`` + +entering in your app's ID and secret, generated from step 0, and the +short-lived token, generated in the previous step. Be sure to remove the curly +braces ``{}`` when replacing values. + +You **cannot use the Graph API Explorer**. For some reason it gets stuck on +this request. I think it's because the response isn't JSON, but a query string. +Since it's a GET request, you can just go to the URL in your browser. + +The response should look like this: + +``access_token=ABC123&expires=5182959`` + +``ABC123`` will be your long-lived access token. You can put it into the +`Access Token Debugger `_ +to verify. +Under ``Expires`` it should have something like ``2 months``. + +**3. Get User ID** + +Using the long-lived access token, make a GET request to + +``https://graph.facebook.com/v2.2/me?access_token={long_lived_access_token}`` + +Be sure to remove the curly braces ``{}`` when replacing values. The **id** field +is your account ID. You'll need it for the next step. + +**4. Get Permanent Page Access Token** + +Make a GET request to + +``https://graph.facebook.com/v2.2/{account_id}/accounts?access_token={long_lived_access_token}`` + +Be sure to remove the curly braces ``{}`` when replacing values. The JSON +response should have a **data** field under which is an array of items the user +has access to. Find the item for the page you want the permanent access token +from. The **access_token** field should have your permanent access token. Copy +it and test it in the `Access Token Debugger `_. +Under ``Expires`` it should say ``Never``. diff --git a/docs/configuration/alarms/index.rst b/docs/configuration/alarms/index.rst new file mode 100644 index 000000000..e1ff23c57 --- /dev/null +++ b/docs/configuration/alarms/index.rst @@ -0,0 +1,167 @@ +Alarms +======= + +.. contents:: Table of Contents + :depth: 1 + :local: + +Prerequisites +------------------------------------- + +This guide assumes: + ++ You understand how :doc:`../events/index` and :doc:`../filters/index` work. ++ You understand what how :ref:`DTS ` work. ++ You understand + `JSON formatting `_. ++ You are using the latest version of PokeAlarm. + + +Introduction +------------------------------------- + +An **Alarm** object describes where and how PA is going to send a notification +once it has been properly triggered. When an Event passes a Filter, it is passed +on to the Alarms to trigger notifications. Each Alarm represents settings for +exactly a notification will be sent: which service, what text, what images, and +more. + +.. note:: By default, PA will trigger every Alarm when an Event passes a Filter. + You can override this behavior by using the advanced + :doc:`../rules-overview` feature. + +There are several different types of Alarms, each representing a different type +of service: + +.. toctree:: + :maxdepth: 1 + + discord + facebook-pages + pushbullet + slack + telegram + twilio + twitter + + +.. note:: It is valid to have multiple Alarms with the same type - a + different Alarm could represent a different channel or a specialized + message instead of just a different service. + + +Creating an Alarm +------------------------------------- + +Each Alarm is containing several key-value a *named* JSON Object containing +several key-value pairs called *alarm parameters*. Some parameters are +**required** for each alarm, and some are **optional** parameters. In the case of +optional parameters, default values are generally provided when they aren't +specified. For example, a basic Discord alarm looks like this: + +.. code-block:: json + + "my-discord-alarm":{ + "active":true, + "type":"discord", + "webhook_url":"YOUR_WEBHOOK_URL" + } + +The available parameters are different for every type of Alarm - make sure to +check the appropriate wiki page to ensure you are using the correct ones. + + +Customizing Alerts +------------------------------------- + +It is possible to customize the parameters an Alarm uses for different types of +Events. For example, you may want to send all "monsters" to one channel and all +"raids" to another. In this case, *alert level* parameters can be used. These +parameters override the *alarm level* parameters when used. Here is an example +that uses alarm using alert level parameters: + +.. code-block:: json + + "my-discord-alarm":{ + "active":true, + "type":"discord", + "webhook_url":"DEFAULT_CHANNEL_URL", + "monsters":{ + "webhook_url":"MONSTER_CHANNEL_URL" + }, + "raids":{ + "webhook_url":"RAIDS_CHANNEL_URL" + } + } + + +In the above example, any *alert level* parameters not set will default to the +*alarm level* parameters - this means "stops", "gyms", and "eggs" will all be +diverted to the channel at ``"DEFAULT_CHANNEL_URL"``. + +Additionally, are also several *alert level* parameters that can't be set at the +alarm level. For example, "body" can **only** be set at the alert level in +Discord: + +.. code-block:: json + + "my-discord-alarm":{ + "active":true, + "type":"discord", + "webhook_url":"DEFAULT_CHANNEL_URL", + "monsters":{ + "webhook_url":"MONSTER_CHANNEL_URL", + "body":"This is a monster event!" + }, + "raids":{ + "webhook_url":"RAIDS_CHANNEL_URL", + "body":"This is a raid event!" + } + } + + +Finally, you can use :ref:`DTS ` to customize most parameters based +on the event. This can be used for a variety of reasons: specializing the +message, customizing the channel, or even inserting your own images. Check out +:ref:`DTS ` for information on DTS. + + +Alarms File +------------------------------------- + +An *alarms file* (sometimes referred to as an 'alarms.json') is a file +containing then Alarms that PA uses. By default, PA loads from the +``alarms.json`` located in the base folder of the project. See the +:doc:`../server-settings` page for instructions on specifying the file by a +different name. This file must contain a single JSON object to load +successfully: + +.. code-block:: json + + { + + } + +Each Alarm will be listed inside this JSON object. It will end up looking +something like this: + +.. code-block:: json + + { + "my-first-alarm":{ + "active":true, + "type":"discord", + "webhook_url":"YOUR_WEBHOOK_URL" + }, + "my-second-alarm":{ + "active":true, + "type":"slack", + "api_key":"YOUR_API_KEY", + "channel":"general" + }, + "my-third-alarm":{ + "active":true, + "type":"discord", + "webhook_url":"YOUR_WEBHOOK_URL" + } + } diff --git a/docs/configuration/alarms/pushbullet.rst b/docs/configuration/alarms/pushbullet.rst new file mode 100644 index 000000000..655bf4d75 --- /dev/null +++ b/docs/configuration/alarms/pushbullet.rst @@ -0,0 +1,157 @@ +Pushbullet +===================================== + +.. contents:: Table of Contents + :depth: 2 + :local: + + +Prerequisites +------------------------------------- + +This guide assumes + ++ You are familiar with `JSON formatting `_. ++ You have read and understood the :doc:`index` wiki. ++ You are comfortable with the layout of ``alarms.json``. ++ You are using the latest version of PokeAlarm. + +Please familiarize yourself with all of the above before proceeding. + + +Introduction +------------------------------------- + + +PokeAlarm offers the following for Pushbullet: + ++ Notifications to multiple Pushbullet channels ++ Customizable Google Map image of the pokemon, gym, pokestop, egg and/or raid location ++ Personalized notifications via :doc:`../events/index` + +Basic Config +------------------------------------- + + +Required Parameters +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +These `alarm.json` parameters are required to enable the Pushbullet alarm service: + +=============== ===================================== +Parameters Description +=============== ===================================== +`type` Must be ``"pushbullet"`` +`active` ``true`` for alarm to be active +`api_key` Your Pushbullet API key +=============== ===================================== + + +Example: Basic Alarm Configuration using Required Parameters +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Below is how a basic Pushbullet alarm configuration would appear in ``alarms.json``. + +.. code-block:: json + + { + "active":true, + "type":"pushbullet", + "api_key":"YOUR_API_KEY" + } + +.. note:: + The above code is to be inserted into the alarms section of + alarms.json. It does not represent the entire alarms.json file. + + +Advanced Config +------------------------------------- + +Optional Parameters +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +In addition to the required parameters, several ``alarms.json`` optional +parameters are available to personalize your notifications. Below is an +example of these optional parameters and how they are incorporated into a +functional alarm layout. + +These optional parameters are entered at the same level as ``"type":"pushbullet"``. + ++-------------------+-----------------------------------------------+----------+ +| Parameters | Description | Default | ++-------------------+-----------------------------------------------+----------+ +| `startup_message` | Confirmation post when PokeAlarm initialized | ``true`` | ++-------------------+-----------------------------------------------+----------+ + +These optional parameters below are applicable to the ``monsters``, ``stops``, +``gyms``, ``eggs``, and ``raids`` sections of the JSON file. + +============= ========================================= =========================================== +Parameters Description Default +============= ========================================= =========================================== +`channel` Channel tag of the target channel Sends to all devices +`title` Notification title attached to the push ``A wild has appeared!`` +`url` Link to be attached to the push ```` +`body` Message attached to the push ``Available until <24h_time> ().`` +============= ========================================= =========================================== + + +Example: Alarm Configuration Using Optional Parameters +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +.. code-block:: json + + { + "pushbullet_alarm":{ + "active":true, + "type":"pushbullet", + "api_key":"YOUR_API_KEY", + "channel":"DEFAULT_CHANNEL", + "monsters":{ + "title":"A wild has appeared!", + "url":"", + "body":"Available until <24h_time> ().", + "channel":"OVERRIDES_DEFAULT_CHANNEL" + }, + "stops":{ + "title":"Someone has placed a lure on a Pokestop!", + "url":"", + "body":"Lure will expire at <24h_time> ().", + "channel":"OVERRIDES_DEFAULT_CHANNEL" + }, + "gyms":{ + "title":"A Team gym has fallen!", + "url":"", + "body":"It is now controlled by .", + "channel":"OVERRIDES_DEFAULT_CHANNEL" + }, + "eggs": { + "title":"A level raid is incoming!", + "url":"", + "body":"The egg will hatch <24h_hatch_time> ().", + "channel":"OVERRIDES_DEFAULT_CHANNEL" + }, + "raids":{ + "title":"Level raid is available against !", + "url":"", + "body":"The raid is available until <24h_raid_end> ()." + } + } + } + +.. note:: + The above code is to be inserted into the alarms section of + alarms.json. It does not represent the entire alarms.json file. + + +How to get a Pushbullet API Key +------------------------------------- + +1. Go to `Pushbullet `_ and click one of the + ``Sign up`` options. + +2. In the top right corner, click on the letter and select ``My Account``. + +3. Scroll down to ``Create Access Token``. Copy this token and place it in + ``api_key`` parameter. diff --git a/docs/configuration/alarms/slack.rst b/docs/configuration/alarms/slack.rst new file mode 100644 index 000000000..7b8b0d0b2 --- /dev/null +++ b/docs/configuration/alarms/slack.rst @@ -0,0 +1,258 @@ +Slack +===================================== + +.. contents:: Table of Contents + :depth: 2 + :local: + + +Prerequisites +------------------------------------- + +This guide assumes + ++ You are familiar with `JSON formatting `_. ++ You have read and understood the :doc:`index` wiki. ++ You are comfortable with the layout of ``alarms.json``. ++ You are using the latest version of PokeAlarm. + +Please familiarize yourself with all of the above before proceeding. + + +Introduction +------------------------------------- + +.. image:: ../../images/slack_example.png + +**Slack** is a cloud-based team collaboration tool that is available on +Windows, Mac OS X, Linux, iOS, Android, and Windows Phone. Slack offers a lot +of IRC-like features: persistent chat rooms (channels) organized by topic, as +well as private groups and direct messaging. All content inside Slack is +searchable, including files, conversations, and people. + +PokeAlarm offers the following for Slack: + ++ Custom username for posting ++ High resolution icons for pokemon, gym, pokestop, egg and/or raid notifications ++ Notifications to multiple Slack channels and/or teams ++ Customizable Google Map image of the pokemon, gym, pokestop, egg and/or raid location ++ Personalized notifications via :doc:`../events/index` + + +Basic Config +------------------------------------- + + +Required Parameters +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +These parameters below are required to enable the Slack alarm service: + +============ =============== ====================================== +Parameters Default Description +============ =============== ====================================== +`type` ``"slack"`` Name of service +`active` ``false`` ``true`` for alarm to be active +`api_key` Your Slack API key +`channel` ``"general"`` Default channel to post notifications +============ =============== ====================================== + + +Example: Basic Alarm Configuration using Required Parameters +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +.. code-block:: json + + { + "active":true, + "type":"slack", + "api_key":"YOUR_API_KEY", + "channel":"general" + } + +.. note:: + The above code is to be inserted into the alarms section of + alarms.json. It does not represent the entire alarms.json file. + + +Advanced Config +------------------------------------- + +Optional Parameters +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +In addition to the 3 required parameters, several optional parameters are +available to personalize your Slack notifications. Below is an example of +these optional parameters and how they are incorporated into a functional +alarm layout for Slack. + +These optional parameters are entered at the same level as ``"type":"slack"``. + ++-------------------+-----------------------------------------------+----------+ +| Parameters | Description | Default | ++-------------------+-----------------------------------------------+----------+ +| `startup_message` | Confirmation post when PokeAlarm initialized | ``true`` | ++-------------------+-----------------------------------------------+----------+ + +These optional parameters below are applicable to the ``monsters``, ``stops``, +``gyms``, ``eggs``, and ``raids`` sections of the JSON file. + +============= ============================================ =========================================== +Parameters Description Default +============= ============================================ =========================================== +`channel` Send messages to this channel ``#general`` +`username` Username the bot should post the message ```` +`icon_url` URL path to pokemon icon +`title` Notification text to begin the message ``A wild has appeared!`` +`url` Link to be added to notification text ```` +`body` Additional text to be added to the message ``Available until <24h_time> ().`` +`map` Specify a json object to describe the map See Mini Map Configuration for more details +============= ============================================ =========================================== + +.. note:: + Nidorans will be ``nidoranf`` or ``nidoranm``, Farfetch'd will be + ``farfetchd``, and Mr. Mime will be ``mrmime``. + Channels that do not exist (channels cannot be created by bots) will + default to general instead. + + +Example: Alarm Configuration Using Optional Parameters +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +.. code-block:: json + + { + "slack_alarm":{ + "active":true, + "type":"slack", + "api_key":"YOUR_API_KEY", + "channel":"general", + "startup_message":true, + "monsters":{ + "channel":"general", + "username":"", + "icon_url*":"/_.png", + "title":"A wild has appeared!", + "url":"", + "body":"Available until <24h_time> ().", + "map":{ + "enabled":true, + "width":"250", + "height":"125", + "maptype":"roadmap", + "zoom":"15" + } + }, + "stops":{ + "channel":"general", + "username":"Pokestop", + "icon_url*":"/ready.png", + "title":"Someone has placed a lure on a Pokestop!", + "url":"", + "body":"Lure will expire at <24h_time> ()." + }, + "gyms":{ + "channel":"general", + "username":" Gym Alerts", + "icon_url*":"/.png", + "title":"A Team gym has fallen!", + "url":"", + "body":"It is now controlled by ." + }, + "eggs":{ + "username":"Egg", + "icon_url*":"/.png", + "title":"A level raid is incoming!", + "url":"", + "body":"The egg will hatch <24h_hatch_time> ()." + }, + "raids":{ + "username":" Raid", + "icon_url*":"/_000.png", + "title":"Level raid is available against !", + "url":"", + "body":"The raid is available until <24h_raid_end> ()." + } + } + } + + +.. note:: + \*THESE LINES ARE USED TO OVERRIDE DEFAULT VALUES. IF YOU DO NOT + WISH TO USE CUSTOM IMAGES, DO NOT ADD THESE LINES TO YOUR ALARMS.JSON. + + The above code is to be inserted into the alarms section of + alarms.json. It does not represent the entire alarms.json file. + + +Mini Map Configuration +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +.. image:: ../../images/minimap.png + +You can enable a small Google Static Maps image after your post, showing the +location of the alarmed pokemon, gym, pokestop, egg or raid. This is done by +adding the `map` parameter at the Alarm level (which will apply maps for any +notification), or individually to the ``monsters``, ``stops``, ``gyms``, ``eggs``, or +``raids`` sections of your alarm. + +Below is an example of enabling the mini map for pokemon: + +.. code-block:: json + + "monsters":{ + "channel":"general", + "username":"", + "title":"A wild has appeared!", + "url":"", + "body":"Available until <24h_time> ().", + "map":{ + "enabled":true, + "width":"250", + "height":"125", + "maptype":"roadmap", + "zoom":"15" + } + }, + +=============== ========================================== ============ +Parameters Description Default +=============== ========================================== ============ +`enabled` Turns the map on or off ``true`` +`width` Width of the map ``"250"`` px +`height` Height of the map ``"150"`` px +`maptype` Link to be added to notification text ``"roadmap"`` +`zoom` Specifies the zoom of the map ``"15"`` +=============== ========================================== ============ + + +Formatting alarms text +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Here is a basic guide to apply custom styles to alarm text: + +================================ ============================= +Style Example +================================ ============================= +`_italics_` *italics* +`*bold*` **bold** +`_*bold italics*_` :boltitalic:`bold italics` +`~strikethrough~` :strike:`strikethrough` +================================ ============================= + +You can see other options in the official Slack information about formatting +text `here `_. + + +How to get a Slack API Key +------------------------------------- + +1. Visit `slack.com `_. Enter your email address and + click ``Create your team``. Follow the instructions to setup and activate + your account. + +2. Go to the `create a bot page `_. Enter + a username and click create. + +3. Copy the API Token given. Fill out any more information you want, and click + ``Save Integration``. diff --git a/docs/configuration/alarms/telegram.rst b/docs/configuration/alarms/telegram.rst new file mode 100644 index 000000000..4bd9e69d1 --- /dev/null +++ b/docs/configuration/alarms/telegram.rst @@ -0,0 +1,228 @@ +Telegram +===================================== + +.. contents:: Table of Contents + :depth: 2 + :local: + + +Prerequisites +------------------------------------- + +This guide assumes + ++ You are familiar with `JSON formatting `_. ++ You have read and understood the :doc:`index` wiki. ++ You are comfortable with the layout of ``alarms.json``. ++ You are using the latest version of PokeAlarm. + +Please familiarize yourself with all of the above before proceeding. + + +Introduction +------------------------------------- + +.. image:: ../../images/telegram.png + +**Telegram** is a cloud-based instant messaging service. Telegram clients exist +for both mobile (Android, iOS, Windows Phone, Ubuntu Touch) and desktop systems +(Windows, OS X, Linux). Users can send messages and exchange photos, videos, +stickers and files of any type. + +PokeAlarm offers the following for Telegram: + ++ Notifications to multiple Telegram channels ++ Customizable Google Map image of the pokemon, gym, pokestop, egg and/or raid location ++ Personalized notifications via :doc:`../events/index` + + +Basic Config +------------------------------------- + + +Required Parameters +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +These ``alarm.json`` parameters are required to enable the Telegram alarm service: + +=============== =================================== +Parameters Description +=============== =================================== +`type` Must be ``"telegram"`` +`active` ``true`` for alarm to be active +`bot_token` Your Bot Token from Telegram +`chat_id` Your chat's id from Telegram +=============== =================================== + + +Example: Basic Alarm Configuration using Required Parameters +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Below is how a basic Telegram alarm configuration would appear in +``alarms.json``. Note that this is **not** the entire ``alarms.json``, but only +the section pertaining to the alarm portion of the JSON file. + +.. code-block:: json + + { + "active":true, + "type":"telegram", + "bot_token":"YOUR_BOT_TOKEN", + "chat_id":"YOUR_CHAT_ID" + } + + +Advanced Config +------------------------------------- + +Optional Parameters +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +In addition to the required parameters, several ``alarms.json`` optional +parameters are available to personalize your notifications. Below is an example +of these optional parameters and how they are incorporated into a functional +alarm layout. + +Parameters at the alarm level will be the default to alert-level parameters. + +================= ====================================================== ============ +Parameters Description Default +================= ====================================================== ============ +`map` Sends minimap after main message. ``true`` +`map_notify` Disables map notifications. Set to ``false`` if you + are experiencing notification issues on Android ``false`` +`venue` Sends location in main message.* ``false`` +`venue_notify` Disables venue notifications. Set to ``false`` if you + are experiencing notification issues on Android ``true`` +`message_notify` Enables notifications messages ``true`` +`sticker` Sends pokemon images as stickers in the message ``true`` +`sticker_notify` Disables sticker notifications. Set to ``false`` + if you are experiencing notification issues on Android ``false`` +`sticker_url` Url to be used for the sticker. Must be .webp file. +`max_attempts` Max attempts to send for each message. ``"3"`` +`web_preview` Enables web preview for links in message. ``false`` +`startup_message` Confirmation post when PokeAlarm initialized ``true`` +================= ====================================================== ============ + +These optional parameters below are applicable to the ``monsters``, ``stops``, +``gyms``, ``eggs``, and ``raids`` sections of the JSON file. These parameters +override the alarm-level settings for this alert. + +================ ========================================= ============================ +Parameters Description Default +================ ========================================= ============================ +`message` Text for the message ``"*A wild has + appeared!*\nAvailable until + <24h_time> ()."`` +`map` Sends minimap after main message. ``true`` +`map_notify` Disables map notifications. Set to + ``false`` if you are experiencing + notification issues on Android ``false`` +`venue` Sends location in main message.* ``false`` +`venue_notify` Disables venue notifications. Set to + ``false`` if you are experiencing + notification issues on Android ``true`` +`sticker` Sends images as stickers in the message ``true`` +`sticker_notify` Disables sticker notifications. Set to + ``false`` if you are experiencing + notification issues on Android ``false`` +================ ========================================= ============================ + +.. note:: + \*if you use ``venue``, keep in mind that the markdown in your alarms + will be ignored because of a limitation in the Telegram API. + + +Example: Alarm Configuration Using Optional Parameters +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Below is how an advanced alarm configuration would appear in ``alarms.json``. +Note that this is **not** the entire ``alarms.json``, but only the section +pertaining to the alarm portion of the JSON file. + +.. code-block:: json + + { + "telegram_alarm":{ + "active":true, + "type":"telegram", + "bot_token":"YOUR_BOT_TOKEN", + "chat_id":"YOUR_CHAT_ID", + "map_notify":false, + "startup_message":false, + "sticker":true, + "monsters":{ + "chat_id":"OVERRIDES_DEFAULT_CHANNEL", + "message":"*A wild has appeared!*\nAvailable until <24h_time> ().", + "map":true + }, + "stops":{ + "chat_id":"OVERRIDES_DEFAULT_CHANNEL", + "message":"*Someone has placed a lure on a Pokestop!*\nLure will expire at <24h_time> ().", + "map":true + }, + "gyms":{ + "chat_id":"OVERRIDES_DEFAULT_CHANNEL", + "message":"*A Team gym has fallen!*\nIt is now controlled by .", + "map":true + }, + "eggs":{ + "chat_id":"OVERRIDES_DEFAULT_CHANNEL", + "message":"*A level raid is incoming!*\nThe egg will hatch <24h_hatch_time> ().", + "map":true + }, + "raids":{ + "chat_id":"OVERRIDES_DEFAULT_CHANNEL", + "message":"*A raid is available against !*\nThe raid is available until <24h_raid_end> ().", + "map":true + } + } + } + + +Formatting alarms text +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Here is a basic guide to apply custom styles to alarm text: + +============================= ============================= +Style Example +============================= ============================= +`_italic text_` *italics* +`*bold text*` **bold** +`_*bold italics*_` :boltitalic:`bold italics` +============================= ============================= + +You can see other options in the official Telegram information about +formatting text `here `_. + + +How to get a Telegram API Key +------------------------------------- + +1. Go to `Telegram Web Client `_. Enter your + phone number and follow the instructions to create your account. + +2. Talk to the `BotFather `_ to create a new bot. + Use the ``/newbot`` command and follow his instructions. It will give you an + API Token when you are finished. + +3. Start a conversation with your bot. In the top left click on the menu bars, + then click create group. Type in the name of the bot you previously created, + then click on it when it appears below. Then click next. Type any message to + your bot. + +4. Enter your bot_token in to replace the ```` in the following + url ``https://api.telegram.org/bot/getUpdates``. Then go to + it, and find the section that says ``"chat":{"id":``. This number + is your chat_id. + + +How to Create a Custom Channel +------------------------------------- + +1. Create a Public Channel (Currently doesn't work from the web app). + +2. Add your bot as an administrator for the channel. + +3. The chat_id for your bot will be `@channel_url`. diff --git a/docs/configuration/alarms/twilio.rst b/docs/configuration/alarms/twilio.rst new file mode 100644 index 000000000..d19cefa46 --- /dev/null +++ b/docs/configuration/alarms/twilio.rst @@ -0,0 +1,221 @@ +Twilio +===================================== + +.. contents:: Table of Contents + :depth: 2 + :local: + + +Prerequisites +------------------------------------- + +This guide assumes + ++ You are familiar with `JSON formatting `_. ++ You have read and understood the :doc:`index` wiki. ++ You are comfortable with the layout of ``alarms.json``. ++ You are using the latest version of PokeAlarm. + +Please familiarize yourself with all of the above before proceeding. + + +Introduction +------------------------------------- + +**Twilio** allows software developers to programmatically make and receive +phone calls and send and receive text messages using its web service APIs. + +PokeAlarm offers the following for Twilio: + ++ Personalized notifications via :doc:`../events/index` + + +Basic Config +------------------------------------- + +These ``alarms.json`` parameters are required to enable the alarm service: + + +Required Parameters +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +=============== ====================================== +Parameters Description +=============== ====================================== +`type` Must be ``"twilio"`` +`active` ``true`` for alarm to be active +`account_sid` Your Account SID from Twilio +`auth_token` Your Auth Token from Twilio +`from_number` Your Twilio number to send from +`to_number` Your number to receive texts from +=============== ====================================== + + +Example: Basic Alarm Configuration using Required Parameters +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +.. code-block:: json + + { + "active":true, + "type":"twilio", + "account_sid":"YOUR_API_KEY", + "auth_token":"YOUR_AUTH_TOKEN", + "from_number":"YOUR_FROM_NUM", + "to_number":"YOUR_TO_NUM" + } + +.. note:: + The above code is to be inserted into the alarms section of + alarms.json. It does not represent the entire alarms.json file. + + +Advanced Config +------------------------------------- + +In addition to the above required parameters, several optional parameters +are available to personalize your notifications. + + +Multiple Destinations +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +The ``"to_number"`` field can accept either a single destination phone number +or an array of phone numbers to send SMS messages to. This allows for +sending SMS alerts to multiple destinations. + +Below is an example of using an array for the destination number(s) in the +alarm configuration. + +.. code-block:: json + + { + "active":true, + "type":"twilio", + "account_sid":"YOUR_API_KEY", + "auth_token":"YOUR_AUTH_TOKEN", + "from_number":"YOUR_FROM_NUM", + "to_number":["YOUR_1ST_TO_NUM","YOUR_2ND_TO_NUM","YOUR_3RD_TO_NUM"] + } + + +Optional Parameters +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +These optional parameters below are applicable to the ``monsters``, ``stops``, +``gyms``, ``eggs``, and ``raids`` sections of the JSON file. + +``monsters`` default values: + +=========== ================================= =================================== +Parameters Description Default +=========== ================================= =================================== +`message` Text message for pokemon updates ``"A wild has appeared! + Available until <24h_time> + ()."`` +=========== ================================= =================================== + +``stops`` default values: + +=========== ================================= =================================== +Parameters Description Default +=========== ================================= =================================== +`message` Text message for pokestop updates ``"Someone has placed a lure on a + Pokestop! Lure will expire + at <24h_time> ()."`` +=========== ================================= =================================== + +``gyms`` default values: + +=========== ================================= =================================== +Parameters Description Default +=========== ================================= =================================== +`message` Text message for gym updates ``"A Team gym has fallen! + It is now controlled by + ."`` +=========== ================================= =================================== + +``eggs`` default values: + +=========== ================================= ===================================== +Parameters Description Default +=========== ================================= ===================================== +`message` Text message for egg updates ``"A level raid is incoming! + Egg hatches <24h_hatch_time> + ()."`` +=========== ================================= ===================================== + +``raids`` default values: + +=========== ================================= ===================================== +Parameters Description Default +=========== ================================= ===================================== +`message` Text message for raid updates ``"Level raid against + ! Available until + <24h_raid_end> ()."`` +=========== ================================= ===================================== + + +Example: Alarm Configuration Using Optional Parameters +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Below is an example of these optional parameters and how they are incorporated +into a functional alarm layout. + +.. code-block:: json + + { + "twilio_alarm":{ + "active":true, + "type":"twilio", + "account_sid":"YOUR_API_KEY", + "auth_token":"YOUR_AUTH_TOKEN", + "from_number":"YOUR_FROM_NUM", + "to_number":"YOUR_TO_NUM", + "monsters":{ + "from_number":"YOUR_FROM_NUM", + "to_number":"YOUR_TO_NUM", + "message":"A wild has appeared! Available until <24h_time> ()." + }, + "stops":{ + "from_number":"YOUR_FROM_NUM", + "to_number":"YOUR_TO_NUM", + "message":"Someone has placed a lure on a Pokestop! Lure will expire at <24h_time> ()." + }, + "gyms":{ + "from_number":"YOUR_FROM_NUM", + "to_number":"YOUR_TO_NUM", + "message":"A Team gym has fallen! It is now controlled by ." + }, + "eggs":{ + "message":"A level raid is incoming! Egg hatches <24h_hatch_time> ()." + }, + "raids":{ + "message":"Level raid against ! Available until <24h_raid_end> ()." + } + } + } + + +.. note:: + The above code is to be inserted into the alarms section of + alarms.json. It does not represent the entire alarms.json file. + + +How to get the Account SID, Auth Token, and Twilio Number +------------------------------------- + +1. Go to `Twilio `_ and click ``Get a free API key``. + Fill out the following form, and enter your phone number to verify your + account. + +2. On the left hand side, click the Home Button and then click Dashboard. + The **Account SID** and **Auth Token** will be listed. To reveal the Auth + Token, click on the lock next to it. + +3. Scroll down and click on ``# Phone Numbers``. Then click ``Get Started`` + to get your free number. + +4. If you wish to text to different numbers, you need to register each before + you are allowed to message them. This can be done from the ``Verified Caller + ID's`` page. diff --git a/docs/configuration/alarms/twitter.rst b/docs/configuration/alarms/twitter.rst new file mode 100644 index 000000000..6c5903c48 --- /dev/null +++ b/docs/configuration/alarms/twitter.rst @@ -0,0 +1,173 @@ +Twitter +===================================== + +.. contents:: Table of Contents + :depth: 2 + :local: + + +Prerequisites +------------------------------------- + +This guide assumes + ++ You are familiar with `JSON formatting `_. ++ You have read and understood the :doc:`index` wiki. ++ You are comfortable with the layout of ``alarms.json``. ++ You are using the latest version of PokeAlarm. + +Please familiarize yourself with all of the above before proceeding. + + +Introduction +------------------------------------- + +**Twitter** is an online social networking service that enables users to send +and read short 140-character messages called "tweets". Registered users can +read and post tweets, but those who are unregistered can only read them. Users +access Twitter through the website interface, SMS or mobile device app. + +PokeAlarm offers the following for Twitter: + ++ Personalized notifications via :doc:`../events/index` + +Basic Config +------------------------------------- + + +Required Parameters +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +These ``alarms.json`` parameters are required to enable the Twitter alarm service: + +================= ================================== +Parameters Description +================= ================================== +`type` Must be ``"twitter"`` +`active` ``true`` for alarm to be active +`access_token` Your twitter access token +`access_secret` Your twitter access secret +`consumer_key` Your twitter consumer key +`consumer_secret` Your twitter consumer secret +================= ================================== + + +Example: Basic Alarm Configuration using Required Parameters +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +.. code-block:: json + + { + "active":true, + "type":"twitter", + "access_token":"YOUR_ACCESS_TOKEN", + "access_secret":"YOUR_ACCESS_SECRET", + "consumer_key":"YOUR_CONSUMER_KEY", + "consumer_secret":"YOUR_CONSUMER_SECRET" + } + +.. note:: + The above code is to be inserted into the alarms section of + `alarms.json`. It does not represent the entire `alarms.json` file. + + +Advanced Config +------------------------------------- + + +Optional Parameters +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +In addition to the required parameters, several ``alarms.json`` optional +parameters are available to personalize your notifications. Below is an +example of these optional parameters and how they are incorporated into a +functional alarm layout. + +These optional parameters are entered at the same level as ``"type":"twitter"``. + ++-------------------+-----------------------------------------------+----------+ +| Parameters | Description | Default | ++-------------------+-----------------------------------------------+----------+ +| `startup_message` | Confirmation post when PokeAlarm initialized | ``true`` | ++-------------------+-----------------------------------------------+----------+ + +These optional parameters below are applicable to the ``monsters``, ``stops``, +``gyms``, ``eggs``, and ``raids`` sections of the JSON file. + +============ ========================== ========================================== +Parameters Description Default +============ ========================== ========================================== +`status` Message to post as status ``"A wild has appeared! + Available until <24h_time> (). + "`` +============ ========================== ========================================== + + +Example: Alarm Configuration Using Optional Parameters +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +.. code-block:: json + + { + "twitter_alarm":{ + "active":true, + "type":"twitter", + "access_token":"YOUR_ACCESS_TOKEN", + "access_secret":"YOUR_ACCESS_SECRET", + "consumer_key":"YOUR_CONSUMER_KEY", + "consumer_secret":"YOUR_CONSUMER_SECRET", + "monsters":{ + "status":"A wild has appeared! Available until <24h_time> (). " + }, + "stops":{ + "status":"Someone has placed a lure on a Pokestop! Lure will expire at <24h_time> (). " + }, + "gyms":{ + "status":"A Team gym has fallen! It is now controlled by . " + }, + "eggs":{ + "status":"Level raid incoming! Hatches at <24h_hatch_time> (). " + }, + "raids":{ + "status":"Raid against ! Available until <24h_raid_end> (). " + } + } + } + + +.. note:: + The above code is to be inserted into the alarms section of + ``alarms.json``. It does not represent the entire ``alarms.json`` file. + +For more information on text substitutions, please see the main configuration page. + + +How to get a Twitter API Key +------------------------------------- + +**Step 1: Create a Twitter account** + ++ Go to `Twitter's signup page `_. ++ Fill out all details, and **make sure to include your phone number**. This + is a requirement for remote access, and you will need that to make the Twitter + bot work. + +**Step 2: Create a Twitter app** + ++ Go to `apps.twitter.com `_ ++ Click ``Create New App`` button ++ Fill out the details on the form. You have to give your app a name, + description, and website. This can be a simple place holder like + http://www.example.com ++ Read the Developer Agreement, and check the box at the bottom if you agree. + Then click on the ``Create your Twitter application`` button. + +**Step 3: Keys and Access tokens** + ++ After creating your new app, you were redirected to its own page. If you + weren’t, go to `apps.twitter.com `_ and click on + your apps name. ++ On the app’s page, click on the ``Keys and Access Tokens`` page. ++ At the bottom of this page, click on the ‘Create my access token’ button. ++ Take note of **Consumer Key (API Key), Consumer Secret (API Secret), Access + Token, & Access Token Secret**. These are the are required in the Twitter Config. diff --git a/docs/configuration/events/egg-events.rst b/docs/configuration/events/egg-events.rst new file mode 100644 index 000000000..9cf7895ec --- /dev/null +++ b/docs/configuration/events/egg-events.rst @@ -0,0 +1,99 @@ +Eggs +===================================== + +.. contents:: Table of Contents + :depth: 2 + :local: + + +Prerequisites +------------------------------------- + +This pages assumes the following: + +1. You have a working scanner. +2. You read and understood the :ref:`events_dts` page. +3. You are using the latest version of PokeAlarm. + +Description +------------------------------------- + +A **Egg Event** represents when a egg event appears in a gym. + + +Available DTS +------------------------------------- + +General +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +================= ======================================================== +DTS Description +================= ======================================================== +gym_id The gym id. Unique per gym. +egg_lvl The tier level of the egg. +gym_name The name of the gym. * +gym_description The description of the gym. * +gym_image The url to the image of the gym. * +team_id The id of the team currently in control of the gym. +team_name The team currently in control of the gym. +team_leader The leader of the team currently in control of the gym. +sponsor_id The sponsor if of the gym. 0 if not sponsored. +sponsored True if sponsored, False if not. +================= ======================================================== + +.. note:: + + \* Gym Info requires caching. See the :ref:`object-caching` + page for more information. + + +Location +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +.. warning:: + + Geofences are only evaluated per Filter - ```` will be unknown if + it passes through a Filter without a ``geofences`` restriction applied. + +=================== ========================================================= +DTS Description +=================== ========================================================= +lat Latitude of the egg. +lng Longitude of the egg. +lat_5 Latitude of the egg, truncated to 5 decimal places. +lng_5 Longitude of the egg, truncated to 5 decimal places. +distance Distance of the egg from the set location. +direction Cardinal direction of the egg, from the set location. +gmaps Google Maps link to the location of the egg. +applemaps Apple Maps link to the location of the egg. +geofence Geofence around the event. +=================== ========================================================= + + +Time +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +================= ========================================================= +DTS Description +================= ========================================================= +hatch_time_left Time remaining until the egg hatches. +12h_hatch_time Time when the egg will hatch, formatted in 12h. +24h_hatch_time Time when the egg will hatch, formatted in 24h. +raid_time_left Time remaining until the raid ends. +12h_raid_end Time when the raid ends, formatted in 12h. +24h_raid_end Time when the raid ends, formatted in 24h. +================= ========================================================= + + +Weather +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +================= ========================================================= +DTS Description +================= ========================================================= +weather_id Weather ID of the egg. +weather Weather name of the egg. +weather_or_empty Weather name of the egg, or empty string if unknown. +weather_emoji Weather emoji of the egg, or empty string if unknown. +================= ========================================================= diff --git a/docs/configuration/events/gym-events.rst b/docs/configuration/events/gym-events.rst new file mode 100644 index 000000000..8a95e464e --- /dev/null +++ b/docs/configuration/events/gym-events.rst @@ -0,0 +1,77 @@ +Gyms +===================================== + +.. contents:: Table of Contents + :depth: 2 + :local: + + +Prerequisites +------------------------------------- + +This pages assumes the following: + +1. You have a working scanner. +2. You read and understood the :ref:`events_dts` page. +3. You are using the latest version of PokeAlarm. + + +Description +------------------------------------- + +A **Gym Event** represents when a gym has been taken for another team. + + +Available DTS +------------------------------------- + + +General +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +================ ======================================================== +DTS Description +================ ======================================================== +gym_id The gym id. Unique per gym. +old_team The team in control of the gym previously. +old_team_id The id of the team in control of the gym previously. +old_team_leader The leader of the team in control of the gym previously. +new_team The team currently in control of the gym. +new_team_id The id of the team currently in control of the gym. +new_team_leader The leader of the team currently in control of the gym. +gym_name The name of the gym. * +gym_description The description of the gym. * +gym_image The url to the image of the gym. * +slots_available Number of open guard slots available in a gym. +guard_count Number of guards assigned to a gym. +sponsor_id The sponsor if of the gym. 0 if not sponsored. +sponsored True if sponsored, False if not. +================ ======================================================== + +.. note:: + + \* Gym Info requires caching. See the :ref:`object-caching` + page for more information. + + +Location +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +.. warning:: + + Geofences are only evaluated per Filter - ```` will be unknown if + it passes through a Filter without a ``geofences`` restriction applied. + +=================== ========================================================= +DTS Description +=================== ========================================================= +lat Latitude of the gym. +lng Longitude of the gym. +lat_5 Latitude of the gym, truncated to 5 decimal places. +lng_5 Longitude of the gym, truncated to 5 decimal places. +distance Distance of the gym from the set location. +direction Cardinal direction of the gym, from the set location. +gmaps Google Maps link to the location of the gym. +applemaps Apple Maps link to the location of the gym. +geofence Geofence around the event. +=================== ========================================================= diff --git a/docs/configuration/events/index.rst b/docs/configuration/events/index.rst new file mode 100644 index 000000000..b862934bc --- /dev/null +++ b/docs/configuration/events/index.rst @@ -0,0 +1,138 @@ +Events +===================================== + +.. contents:: Table of Contents + :depth: 2 + :local: + +Prerequisites +------------------------------------- + +This guide assumes the following: + ++ You are using the latest version of PokeAlarm. + +Introduction +------------------------------------- + +In PokeAlarm, an **Event** represents something of interest that has happened +in the World. Events can be several different things - a new monster spawning, +a gym changing teams, or a new raid appearing. There are 5 different categories +for Events, each with different information: + +.. toctree:: + :maxdepth: 1 + + monster-events + stop-events + gym-events + egg-events + raid-events + +.. _events_dts: + +Dynamic Text Substitutions +------------------------------------- + +Dynamic Text Substitutions (or DTS) are special text that can be used to +customize notifications based on the triggered Event. These values are +surrounded with diamond brackets (``<`` and ``>``) and will by substituted with +a value based on the Event in question. For example, a notification with the +following text: + +.. code-block:: none + + A wild has appeared! It has % IVs! + +Could be substituted to the following: + +.. code-block:: none + + A wild Charmander has appeared! It has 100.0% IVs! + +Or, it could appear like this: + +.. code-block:: none + + A wild Pidgey has appeared! It has 55.6% IVs! + +The DTS that you can use vary by type of Event - make sure to check the page for +each type to which DTS can be used. + + +Missing Information +------------------------------------- + +.. note:: You can accept or reject an event based on the state of missing + information. See the ``is_missing_info`` restriction on the + :doc:`../filters/index` page for instructions. + +When PA doesn't have the correct information needed to correctly do a +substitution, it may replace it with one of the following: + ++ ? ++ ??? ++ unknown + +This can happen for a variety of reasons - but generally is because the scanner +did not send the information needed in the webhook. PA does it's best to fill in +the gaps by sharing and caching information between separate webhooks (like gym +names or teams), but some info may require a settings update with your scanner +(like IVs or CP). + + +Advanced +------------------------------------- + + +Reverse Geocoding +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +**Reverse Geocoding** is a process that to get the name or data of +places where the Events take place. This can be used to get things such +as address, city, state, or more. + +PA will only use Reverse Geocoding for Events that have been triggered. +Each Event will use up a single point of your API quota, regardless +of number of fields or alarms used. + +================== ======================================================== +Text Description +================== ======================================================== +```` Street number of the alert location +```` Street name of the alert location +``
`` Address of the alert location, includes both street + number and street name, in that order only +```` Address of the alert location, in european format (street + name and street number) +```` Postal code of the alert location +```` Neighborhood code of the alert location +```` Sublocality code of the alert location +```` City code of the alert location +```` County code of the alert location +```` State code of the alert location +```` Country code of the alert location +================== ======================================================== + + +Distance Matrix +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +**Distance Matrix** calculations determine how far away an Event is, for +both time and distance. This can be Walking, Biking, Driving, or Transit. +These calculations require a set location, and a Google Maps API key. For more +information, see the Distance Matrix section of the +:doc:`../../miscellaneous/location-services` page. + +======================= ======================================================== +Text Description +======================= ======================================================== +```` Estimated walking distance to the alert location +```` Estimated walking time to alert location +```` Estimated bike distance to the alert location +```` Estimated bike time to alert location +```` Estimated drive distance to the alert location +```` Estimated drive time to alert location +```` Estimated public transit distance to the alert location +```` Estimated public transit time to alert location +======================= ======================================================== diff --git a/docs/configuration/events/monster-events.rst b/docs/configuration/events/monster-events.rst new file mode 100644 index 000000000..7c36f8a9b --- /dev/null +++ b/docs/configuration/events/monster-events.rst @@ -0,0 +1,223 @@ +Monsters +===================================== + +.. contents:: Table of Contents + :depth: 2 + :local: + +Prerequisites +------------------------------------- + +This pages assumes the following: + +1. You have a working scanner. +2. You read and understood the :ref:`events_dts` page. +3. You are using the latest version of PokeAlarm. + + +Description +------------------------------------- + +A **Monster Event** represents when a monster spawns in the wild. + + +Available DTS +------------------------------------- + +General +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +=================== ========================================================== +DTS Description +=================== ========================================================== +mon_name The name of the monster's species. +mon_id ID of the monster's species. +mon_id_3 ID of the monster's species, padded to 3 digits. +form Form name of the monster. +form_or_empty Form name of the monster, or empty string if unknown. +form_id Form ID for the monster. +form_id_3 Form ID of the monster, padded to 3 digits. +type1 Name of the monster's primary type. +type1_or_empty Name of the monster's primary type, or empty string + if unknown. +type1_emoji Emoji for the monster's primary type, or empty string + if unknown. +type2 Name of the monster's secondary type. +type2_or_empty Name of the monster's secondary type, or empty string + if unknown. +type2_emoji Emoji for the monster's secondary type, or empty string + if unknown. +types Monster's type formatted as "type1/type2". +types_emoji Type emojis for the monster as "type1+type2", or empty + string if unknown. +=================== ========================================================== + + +Stats +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +.. note:: + + The DTS in this section require your scanner to encounter the target + monsters to get the proper information. This typically requires special + settings and accounts - see the documentation for your scanner for + specifics. + +=================== ========================================================= +DTS Description +=================== ========================================================= +mon_lvl Level of the monster. +cp Combat Points of the monster. +iv Individual Values percentage of the monster. +iv_0 IVs, rounded to the nearest integer. +iv_2 IVs, rounded to 2 decimal places. +atk Attack IV of the monster. +def Defense IV of the monster. +sta Stamina IV of the monster. +base_catch Catch rate of the monster when using a poke ball. +base_catch_0 Catch rate of the monster when using a poke ball, rounded to the nearest integer. +base_catch_2 Catch rate of the monster when using a poke ball, rounded to 2 decimal places. +great_catch Catch rate of the monster when using a great ball. +great_catch_0 Catch rate of the monster when using a great ball, rounded to the nearest integer. +great_catch_2 Catch rate of the monster when using a great ball, rounded to 2 decimal places. +ultra_catch Catch rate of the monster when using an ultra ball. +ultra_catch_0 Catch rate of the monster when using an ultra ball, rounded to the nearest integer. +ultra_catch_2 Catch rate of the monster when using an ultra ball, rounded to 2 decimal places. +=================== ========================================================= + +Moves +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +.. note:: + + The DTS in this section require your scanner to encounter the target + monsters to get the proper information. This typically requires special + settings and accounts - see the documentation for your scanner for + specifics. + +=================== ========================================================= +DTS Description +=================== ========================================================= +quick_move Name of the monster's quick move. +quick_id ID of the monster's quick move. +quick_type_id ID of the monster's quick move type. +quick_type Name of the monster's quick move type. +quick_type_emoji Emoji of the monster's quick move type. +quick_damage Damage of the monster's quick move. +quick_dps DPS of the monster's quick move. +quick_duration Duration of the monster's quick move. +quick_energy Energy generated by the quick move. +charge_move Name of the monster's charge move. +charge_id ID of the monster's charge move. +charge_type_id ID of the monster's charge move type. +charge_type Name of the monster's charge move type. +charge_type_emoji Emoji of the monster's charge move type. +charge_damage Damage of the monster's charge move. +charge_dps DPS of the monster's charge move. +charge_duration Duration of the monster's charge move. +charge_energy Energy generated by the charge move. +atk_grade Offensive grade of the monster's moveset. +def_grade Defensive grade of the monster's moveset. +=================== ========================================================= + + +Cosmetic +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +.. note:: + + The DTS in this section require your scanner to encounter the target + monsters to get the proper information. This typically requires special + settings and accounts - see the documentation for your scanner for + specifics. + +=================== ============================================================ +DTS Description +=================== ============================================================ +costume Costume of the monster. +costume_or_empty Costume of the monster, or an empty string if unknown. +costume_id Costume ID of the monster. +costume_id_3 Costume ID of the monster, formatted to there digits. +gender Gender of the monster, represented as a single character. +height Height of the monster. +height_0 Height of the monster, rounded to the nearest integer. +height_2 Height of the monster, rounded to 2 decimal places. +weight Weight of the monster. +weight_0 Weight of the monster, rounded to the nearest integer. +weight_2 Weight of the monster, rounded to 2 decimal places. +size Estimated size of the monster. +big_karp Return `big` if Magikarp weight is >=13.13. +tiny_rat Return `tiny` if Rattata weight is <=2.41. +=================== ============================================================ + + +Location +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +.. warning:: + + Geofences are evaluated on a per Filter basis - ```` will + always be unknown if it passes through a Filter without a ``geofences`` + restriction applied. + +=================== ============================================================ +DTS Description +=================== ============================================================ +distance Distance of the monster from the set location. +direction Cardinal direction of the monster, from the set location. +lat Latitude of the monster. +lng Longitude of the monster. +lat_5 Latitude of the monster, truncated to 5 decimal places. +lng_5 Longitude of the monster, truncated to 5 decimal places. +gmaps Google Maps link to the location of the monster. +applemaps Apple Maps link to the location of the monster. +geofence Geofence around the event. +=================== ============================================================ + + +Time +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +=================== ============================================================ +DTS Description +=================== ============================================================ +time_left Time remaining until the monster expires. +12h_time Time that the monster will disappear, in a 12h format. +24h_time Time that the monster will disappear, in a 24h format. +=================== ============================================================ + + +Weather +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +======================== ======================================================= +DTS Description +======================== ======================================================= +weather_id Weather ID of the monster. +weather Weather name of the monster. +weather_or_empty Weather name of the monster, or empty string if + unknown. +weather_emoji Weather emoji of the monster, or empty string if + unknown. +boosted_weather_id Return weather ID if monster is boosted. +boosted_weather Return weather name if monster is boosted. +boosted_weather_or_empty Return weather name if monster is boosted, or + empty string if unknown. +boosted_weather_emoji Return weather emoji if monster is boosted, or + empty string if unknown. +boosted_or_empty Return `boosted` if monster is boosted, or empty + string if not. +======================== ======================================================= + + +Miscellaneous +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +=================== ============================================================ +DTS Description +=================== ============================================================ +encounter_id The encounter id. Unique per monster spawn. +spawn_start Estimated time that the monster spawn starts. +spawn_end Estimated time that the monster spawn ends. +spawn_verified Whether this spawn times have been verified. +=================== ============================================================ diff --git a/docs/configuration/events/raid-events.rst b/docs/configuration/events/raid-events.rst new file mode 100644 index 000000000..b56a6fc13 --- /dev/null +++ b/docs/configuration/events/raid-events.rst @@ -0,0 +1,167 @@ +Raids +===================================== + +.. contents:: Table of Contents + :depth: 2 + :local: + + +Prerequisites +------------------------------------- + +This pages assumes the following: + +1. You have a working scanner. +2. You read and understood the :ref:`events_dts` page. +3. You are using the latest version of PokeAlarm. + + +Description +------------------------------------- + +A **Raid Event** represents when a raid event appears in a gym. + + +Available DTS +------------------------------------- + +General +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +================= ============================================================ +DTS Description +================= ============================================================ +gym_id The gym id. Unique per gym. +mon_name The name of the monster's species. +mon_id ID of the monster's species. +mon_id_3 ID of the monster's species, padded to 3 digits. +raid_lvl The tier level of the raid. +form Form name of the monster. +form_or_empty Form name of the monster, or empty string if unknown. +form_id Form ID for the monster. +form_id_3 Form ID of the monster, padded to 3 digits. +min_cp Minimum potential CP of the monster. +max_cp Maximum potential CP of the monster. +type1 Name of the monster's primary type. +type1_or_empty Name of the monster's primary type, or empty string + if unknown. +type1_emoji Emoji for the monster's primary type, or empty string + if unknown. +type2 Name of the monster's secondary type. +type2_or_empty Name of the monster's secondary type, or empty string + if unknown. +type2_emoji Emoji for the monster's secondary type, or empty string + if unknown. +types Monster's type formatted as "type1/type2". +types_emoji Type emojis for the monster as "type1+type2", or empty + string if unknown. +gym_name The name of the gym. * +gym_description The description of the gym. * +gym_image The url to the image of the gym. * +team_id The id of the team currently in control of the gym. +team_name The team currently in control of the gym. +team_leader The leader of the team currently in control of the gym. +sponsor_id The sponsor if of the gym. 0 if not sponsored. +sponsored True if sponsored, False if not. +================= ============================================================ + +.. note:: + + \* Gym Info requires caching. See the :ref:`object-caching` + page for more information. + + +Moves +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +================== ========================================================= +DTS Description +================== ========================================================= +quick_move Name of the monster's quick move. +quick_id ID of the monster's quick move. +quick_type_id ID of the monster's quick move type. +quick_type Name of the monster's quick move type. +quick_type_emoji Emoji of the monster's quick move type. +quick_damage Damage of the monster's quick move. +quick_dps DPS of the monster's quick move. +quick_duration Duration of the monster's quick move. +quick_energy Energy generated by the quick move. +charge_move Name of the monster's charge move. +charge_id ID of the monster's charge move. +charge_type_id ID of the monster's charge move type. +charge_type Name of the monster's charge move type. +charge_type_emoji Emoji of the monster's charge move type. +charge_damage Damage of the monster's charge move. +charge_dps DPS of the monster's charge move. +charge_duration Duration of the monster's charge move. +charge_energy Energy generated by the charge move. +================== ========================================================= + + +Cosmetic +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +================== ========================================================= +DTS Description +================== ========================================================= +costume Costume name of the monster. +costume_or_empty Costume name of the monster, or empty string if unknown. +costume_id Costume ID for the monster. +costume_id_3 Costume ID of the monster, padded to 3 digits. +================== ========================================================= + + +Location +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +.. warning:: + + Geofences are only evaluated per Filter - ```` will be unknown if + it passes through a Filter without a ``geofences`` restriction applied. + +============= ======================================================= +DTS Description +============= ======================================================= +lat Latitude of the raid. +lng Longitude of the raid. +lat_5 Latitude of the raid, truncated to 5 decimal places. +lng_5 Longitude of the raid, truncated to 5 decimal places. +distance Distance of the raid from the set location. +direction Cardinal direction of the raid, from the set location. +gmaps Google Maps link to the location of the raid. +applemaps Apple Maps link to the location of the raid. +geofence Geofence around the event. +============= ======================================================= + + +Time +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +================ =============================================== +DTS Description +================ =============================================== +raid_time_left Time remaining until the raid ends. +12h_raid_end Time when the raid ends, formatted in 12h. +24h_raid_end Time when the raid ends, formatted in 24h. +================ =============================================== + + +Weather +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +======================== ======================================================= +DTS Description +======================== ======================================================= +weather_id Weather ID of the raid. +weather Weather name of the raid. +weather_or_empty Weather name of the raid, or empty string if unknown. +weather_emoji Weather emoji of the raid, or empty string if unknown. +boosted_weather_id Return weather ID if monster is boosted. +boosted_weather Return weather name if monster is boosted. +boosted_weather_or_empty Return weather name if monster is boosted, or empty + string if unknown. +boosted_weather_emoji Return weather emoji if monster is boosted, or empty + string if unknown. +boosted_or_empty Return `boosted` if monster is boosted, or empty + string if not. +======================== ======================================================= diff --git a/docs/configuration/events/stop-events.rst b/docs/configuration/events/stop-events.rst new file mode 100644 index 000000000..efff84da6 --- /dev/null +++ b/docs/configuration/events/stop-events.rst @@ -0,0 +1,71 @@ +Stops +===================================== + +.. contents:: Table of Contents + :depth: 2 + :local: + + +Prerequisites +------------------------------------- + +This pages assumes the following: + +1. You have a working scanner. +2. You read and understood the :ref:`events_dts` page. +3. You are using the latest version of PokeAlarm. + + +Description +------------------------------------- + +A **Stop Event** represents when a stop is lured. + + +Available DTS +------------------------------------- + + +General +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +============ ============================== +DTS Description +============ ============================== +stop_id The stop id. Unique per stop. +============ ============================== + + +Location +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +.. warning:: + + Geofences are only evaluated per Filter - ```` will be unknown if + it passes through a Filter without a ``geofences`` restriction applied. + +============ ====================================================== +DTS Description +============ ====================================================== +lat Latitude of the stop. +lng Longitude of the stop. +lat_5 Latitude of the stop, truncated to 5 decimal places. +lng_5 Longitude of the stop, truncated to 5 decimal places. +distance Distance of the stop from the set location. +direction Cardinal direction of the stop, from the set location. +gmaps Google Maps link to the location of the stop. +applemaps Apple Maps link to the location of the stop. +geofence Geofence around the event. +============ ====================================================== + + +Time +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +============ ==================================================== +DTS Description +============ ==================================================== +time_left Time remaining until the lure expires. +12h_time Time that the lure will disappear, in a 12h format. +24h_time Time that the lure will disappear, in a 24h format. +============ ==================================================== diff --git a/docs/configuration/filters/egg-filters.rst b/docs/configuration/filters/egg-filters.rst new file mode 100644 index 000000000..f309f6f30 --- /dev/null +++ b/docs/configuration/filters/egg-filters.rst @@ -0,0 +1,74 @@ +Eggs +===================================== + +.. contents:: Table of Contents + :depth: 2 + :local: + +Prerequisites +------------------------------------- + +This page assumes: + ++ You have a working scanner. ++ You understand + `JSON formatting `_. ++ You are using the latest version of PokeAlarm. ++ You have read and understood the :doc:`index` page. + +Introduction +------------------------------------- + +The ``"eggs"`` section has three distinct settings. + ++----------------------+-----------------------------------------------------------+ +| Setting Name | Description | ++======================+===========================================================+ +| enabled | Process Egg Events only if ``true`` | ++----------------------+-----------------------------------------------------------+ +| defaults | Section for the default settings | ++----------------------+-----------------------------------------------------------+ +| filters | See below parameters | ++----------------------+-----------------------------------------------------------+ + + +Available DTS +------------------------------------- + +General +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + +================== ================================================ ================================ +Parameter Description Example +================== ================================================ ================================ +min_egg_lvl Minimum level of the egg when hatched. ``0`` +max_egg_lvl Maximum level of the egg when hatched. ``5`` +current_teams List of allowed current teams, by id or name. ``["Instinct","Mystic"]`` +gym_name_contains List of regex's required to be in the gym name. ``["Sponsored","West\\sOak"]`` +gym_name_excludes List of regex's rejected to be in the gym name. ``["Sponsored","West\\sOak"]`` +park_contains List of regex's required to be in the park name. ``["Sponsored","Park\\sName"]`` +sponsored restrict sponsor_id to be zero or not ``true`` or ``false`` +================== ================================================ ================================ + + +Miscellaneous +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +=============== ====================================================== ============================== +Parameter Description Example +=============== ====================================================== ============================== +min_dist Min distance of event from set location in miles ``0.0`` * + or meters (depending on settings). +max_dist Max distance of event from set location in miles ``1000.0`` * + or meters (depending on settings). +min_time_left Minimum time (in seconds) until monster despawns. ``1000`` +max_time_left Maximum time (in seconds) until monster despawns. ``2400`` +weather Accepted weathers, by id or name. ``["Clear",2]`` +geofences See :ref:`geofences_filters` page on 'Geofences' ``["geofence1","geofence2"]`` +custom_dts See :ref:`custom_dts_filters` page on 'Custom DTS' ``{"dts1":"substitution"}`` +is_missing_info See :ref:`missing_info_filters` page on 'Missing Info' ``true`` or ``false`` + +=============== ====================================================== ============================== + ++ Floats can use ``"inf"`` to represent infinity diff --git a/docs/configuration/filters/gym-filters.rst b/docs/configuration/filters/gym-filters.rst new file mode 100644 index 000000000..bf4dd9c0d --- /dev/null +++ b/docs/configuration/filters/gym-filters.rst @@ -0,0 +1,72 @@ +Gyms +===================================== + +.. contents:: Table of Contents + :depth: 2 + :local: + +Prerequisites +------------------------------------- + +This page assumes: + ++ You have a working scanner. ++ You understand + `JSON formatting `_. ++ You are using the latest version of PokeAlarm. ++ You have read and understood the :doc:`index` page. + +Introduction +------------------------------------- + +The ``"gyms"`` section has four distinct settings. + ++----------------------+-----------------------------------------------------------+ +| Setting Name | Description | ++======================+===========================================================+ +| enabled | Process Gym Events only if ``true`` | ++----------------------+-----------------------------------------------------------+ +| ignore_neutral | If ``true``, ignore uncontested gyms | ++----------------------+-----------------------------------------------------------+ +| defaults | Section for the default settings | ++----------------------+-----------------------------------------------------------+ +| filters | See below parameters | ++----------------------+-----------------------------------------------------------+ + + +Available DTS +------------------------------------- + +General +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +================== ================================================ ================================ +Parameter Description Example +================== ================================================ ================================ +old_teams List of allowed previous teams, by id or name. ``["Instinct","Mystic"]`` +new_teams List of allowed new teams, by id or name. ``["Valor","Mystic"]`` +gym_name_contains List of regex's required to be in the gym name. ``["Sponsored","West\\sOak"]`` +gym_name_excludes List of regex's rejected to be in the gym name. ``["Sponsored","West\\sOak"]`` +min_slots Minimum number of guard slots available. ``2`` +max_slots Maximum number of guard slots available. ``6`` +park_contains List of regex's required to be in the park name. ``["Sponsored","Park\\sName"]`` +sponsored restrict sponsor_id to be zero or not ``true`` or ``false`` +================== ================================================ ================================ + + +Miscellaneous +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +=============== ====================================================== ============================== +Parameter Description Example +=============== ====================================================== ============================== +min_dist Min distance of event from set location in miles ``0.0`` * + or meters (depending on settings). +max_dist Max distance of event from set location in miles ``1000.0`` * + or meters (depending on settings). +geofences See :ref:`geofences_filters` page on 'Geofences' ``["geofence1","geofence2"]`` +custom_dts See :ref:`custom_dts_filters` page on 'Custom DTS' ``{"dts1":"substitution"}`` +is_missing_info See :ref:`missing_info_filters` page on 'Missing Info' ``true`` or ``false`` +=============== ====================================================== ============================== + ++ Floats can use ``"inf"`` to represent infinity diff --git a/docs/configuration/filters/index.rst b/docs/configuration/filters/index.rst new file mode 100644 index 000000000..13e78fb7a --- /dev/null +++ b/docs/configuration/filters/index.rst @@ -0,0 +1,242 @@ +Filters +======== + +.. contents:: Table of Contents + :depth: 2 + :local: + + +Prerequisites +------------------------------------- + +This pages assumes the following: + ++ You understand how :doc:`../events/index` work. ++ You understand `JSON formatting `_. ++ You are using the latest version of PokeAlarm. + +Introduction +------------------------------------- + +A **Filter** is what PA uses to decide if it is worth of a notification or not. +When PA receives a new Event, it is compared one by one against the Filters. +When PA finds a matching Filter, it triggers a notification. + +.. note:: By default, PA processes Filters in the order they are listed in the + filters file and only triggers on the first match. You can override + this behavior by using the advanced :doc:`../rules-overview` feature. + +There are 5 different types of Filters, each matching a category of Events: + + +.. toctree:: + :maxdepth: 1 + + monster-filters + stop-filters + gym-filters + egg-filters + raid-filters + + +Restrictions +------------------------------------- + +A Filter is represented as a *named* JSON Object containing several key-value +pairs called *restrictions*. Each restriction represents a limit on which Events +are allowed to pass. Restrictions are *explicit* (they must be listed to be +checked) and *associative* (all restrictions must be passed to match) A Filter +with no restrictions would allow any Event to pass: + +.. code-block:: json + + "all-filter-name":{ + } + +.. note:: Filters will *only* check an Event's value if a restriction requires + it. A Monster's IV value won't be checked unless either ``min_iv`` or + ``max_iv`` is set. As such, you should avoid setting restrictions + unless you intend to Filter on those values. + +To add a ``monsters`` restriction, you simply describe it inside the object. The +following would only allow Monsters of certain species: + +.. code-block:: json + + "only-starters":{ + "monsters":["Charmander","Squirtle","Bulbasaur"] + } + +Additional restrictions are added in the same way: + +.. code-block:: json + + "only-high-iv-lvl-starters":{ + "monsters":["Charmander","Squirtle","Bulbasaur"], + "min_iv": 90.0, + "min_lvl": 15 + } + +Each type of Filter has different restrictions, so make sure to check each page +carefully. + +Filters File +------------------------------------- + +A *filters file* (often refereed to as ``filters.json``) is a file containing +the Filters that PA uses. By default, PA loads the Filter from the +``filters.json`` located in the base folder of the project. See the +:doc:`../server-settings` page for instructions on specifying the file by +a different name. This file must contain a single JSON object to load +successfully: + +.. code-block:: json + + { + + } + +Inside this JSON object, you need to add sections for each type of Filter you +wish to add. Sections are optional, and unspecified sections will be disabled +by default. + +.. code-block:: json + + { + "monsters":{ + }, + "stops":{ + }, + "gyms":{ + }, + "eggs":{ + }, + "raids":{ + } + } + +Each section can contain the following sub-sections: + +The ``enabled`` sub-section is a boolean value of either ``true`` or ``false`` +that enables or disables processing of that type of Event. + +The ``defaults`` sub-section is a JSON object containing default restrictions +that are applied to all Filters in the section, unless already specified. For +example, adding ``"min_iv": 90`` in the monsters defaults section will add that +restriction to all Filters - unless they already have a ``min_iv`` restriction. + +.. note:: You can use ``null`` to ignore a default value. Even with a default + ``"monsters"`` restriction set, ``"monsters":null`` inside a filter + acts as if that the monster restriction is not set. + +The ``filters`` section is simply a JSON object containing the Filters, +configured as described above. Here is an example of just the monsters section: + +.. code-block:: json + + "monsters":{ + "enabled":true, + "defaults":{}, + "filters":{ + "filter_by_monsters_example":{ + "monsters":["Bulbasaur","Charmander",7] + }, + "filter_by_ivs_example":{ + "min_atk": 0, "max_atk": 15, + "min_iv": 0.0, "max_iv": 100 + }, + "filter_by_moves_example":{ + "monsters":["Bulbasaur"], + "quick_moves":["Vine Whip","Tackle"], + "charge_moves":["Sludge Bomb","Seed Bomb"] + } + } + } + + +Advanced +------------------------------------- + +.. _missing_info_filters: + +Missing Information +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +As described on the :doc:`../events/index` page, sometimes an Event is missing +information. Erring on the side of caution, a Filter will skip a restriction if +the information needed to check it is missing. If your use the ``min_iv`` info, +but the IV is ``unknown`` for any reason, then by default Filter will skip +checking a restriction as if it wasn't specified. + +The ``is_missing_info`` restriction can be used to require information to be +missing or not. When ``"is_missing_info":false`` is set, the Filter requires +all *checked* values to be known. When ``"is_missing_info":true`` is set, the +Filter does the opposite - at least one *checked* value must be unknown to pass. + +.. warning:: The ``is_missing_info`` restriction only affects *checked* + information. Filters only check information if a restriction + requires it. For example, IV is only checked if either ``min_iv`` + or ``max_iv`` is set. The same is true for other values. + +.. _geofences_filters: + +Geofences +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +For more information on configuring your ``geofence.txt``, see the :doc:`../geofences` page. + +You can require an Event to be inside specific geofences for a Filter. + +This example will check if an event is inside either ``"fence1"`` or ``"fence2"`` +as defined in: + +.. code-block:: json + + "filter_name_1":{ + "geofences":["fence1","fence2"] + } + + +Geofences are checked in order. The first geofence with the event inside +will be used to define the ```` DTS. + +If no geofences are set, the ```` DTS will always return ``unknown``. + +If a geofence with the set name does not exist, it will be skipped and an +error will print out to the console. + +Another example would be to configure alerts inside all of your geofences. You +just have to configure the geofences like this: + +.. code-block:: json + + "filter_name_1":{ + "geofences":["all"] + } + +.. _custom_dts_filters: + +Custom DTS +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +**Custom DTS** is a feature that allows you to specify *filter specific* DTS to +an Event when it passes a filter. The ``custom_dts`` is a JSON object of +key-value pairs. For example, the ```` DTS would be either +"Grass starters" or "Fire starters" depending on the Filter it passed with the +following configuration: + +.. warning:: Using ``custom_dts`` at a Filter level will override any custom + dts from "defaults" level - not just the specific DTS used. + +.. code-block:: json + + "filters":{ + "filter_name_1":{ + "monsters":[1,2,3], + "custom_dts":{"family":"Grass starters"} + }, + "filter_name_2":{ + "monsters":[4,5,6], + "custom_dts":{"family":"Fire starters"} + } + } diff --git a/docs/configuration/filters/monster-filters.rst b/docs/configuration/filters/monster-filters.rst new file mode 100644 index 000000000..217c62e61 --- /dev/null +++ b/docs/configuration/filters/monster-filters.rst @@ -0,0 +1,105 @@ +Monsters +===================================== + +.. contents:: Table of Contents + :depth: 2 + :local: + +Prerequisites +------------------------------------- + +This page assumes: + ++ You have a working scanner. ++ You understand + `JSON formatting `_. ++ You are using the latest version of PokeAlarm. ++ You have read and understood the :doc:`index` page. + +Introduction +------------------------------------- + +The ``"monsters"`` section has three distinct settings. + ++----------------------+-----------------------------------------------------------+ +| Setting Name | Description | ++======================+===========================================================+ +| enabled | Process Monster Events only if ``true`` | ++----------------------+-----------------------------------------------------------+ +| defaults | Section for the default settings | ++----------------------+-----------------------------------------------------------+ +| filters | See below parameters | ++----------------------+-----------------------------------------------------------+ + + +Available DTS +------------------------------------- + +General +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +================= ================================================== ================================ +Parameter Description Example +================= ================================================== ================================ +monsters Array of allowed monsters, by id or name. ``["Bulbasaur","2",3]`` +monsters_exclude Array of excluded monsters, by id or name. ``["Bulbasaur","2",3]`` +form_ids Array of allowed form ids for a monster. ``[0,"1"]`` +genders Array of acceptable genders. Options: `"male", ``["female"]`` + "female", "neutral"` +============== ===================================================== ================================ + + +Encounter Information +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +.. note:: + + Encounter information may require special settings or accounts for your + scanner to work correctly. Please consult the documentation for your + scanner. + +============== ================================================== ================================ +Parameter Description Example +============== ================================================== ================================ +min_lvl Minimum level of the monster. ``0`` +max_lvl Maximum level of the monster. ``40`` +min_atk Minimum attack IV of the monster. ``0`` +max_atk Maximum attack IV of the monster. ``15`` +min_def Minimum defense IV of the monster. ``0`` +max_def Maximum defense IV of the monster. ``15`` +min_sta Minimum stamina IV of the monster. ``0`` +max_sta Maximum stamina IV of the monster. ``15`` +min_iv Minimum total IV percentage of the monster. ``0.0`` * +max_iv Maximum total IV percentage of the monster. ``100.0`` * +min_cp Minimum CP of the monster. ``0`` +max_cp Maximum CP of the monster. ``10000`` +quick_moves Accepted quick moves, by id or name. ``["Vine Whip","Tackle"]`` +charge_moves Accepted charge moves, by id or name. ``["Sludge Bomb","Seed Bomb"]`` +min_height Minimum height of the monster. ``0.0`` * +max_height Maximum height of the monster. ``250.0`` * +min_weight Minimum weight of the monster. ``0.0`` * +max_weight Maximum weight of the monster. ``250.0`` * +sizes Array of acceptable sizes. Options: `"tiny", ``["tiny","big"]`` + "small", "normal", "large", "big"` +============== ================================================== ================================ + + +Miscellaneous +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +=============== ====================================================== ============================== +Parameter Description Example +=============== ====================================================== ============================== +min_dist Min distance of event from set location in miles ``0.0`` * + or meters (depending on settings). +max_dist Max distance of event from set location in miles ``1000.0`` * + or meters (depending on settings). +min_time_left Minimum time (in seconds) until monster despawns. ``1000`` +max_time_left Maximum time (in seconds) until monster despawns. ``2400`` +weather Accepted weathers, by id or name. ``["Clear",2]`` +geofences See :ref:`geofences_filters` page on 'Geofences' ``["geofence1","geofence2"]`` +custom_dts See :ref:`custom_dts_filters` page on 'Custom DTS' ``{"dts1":"substitution"}`` +is_missing_info See :ref:`missing_info_filters` page on 'Missing Info' ``true`` or ``false`` +=============== ====================================================== ============================== + ++ Floats can use ``"inf"`` to represent infinity diff --git a/docs/configuration/filters/raid-filters.rst b/docs/configuration/filters/raid-filters.rst new file mode 100644 index 000000000..224c3907d --- /dev/null +++ b/docs/configuration/filters/raid-filters.rst @@ -0,0 +1,76 @@ +Raids +===================================== + +.. contents:: Table of Contents + :depth: 2 + :local: + +Prerequisites +------------------------------------- + +This page assumes: + ++ You have a working scanner. ++ You understand + `JSON formatting `_. ++ You are using the latest version of PokeAlarm. ++ You have read and understood the :doc:`index` page. + +Introduction +------------------------------------- + +The ``"raids"`` section has three distinct settings. + ++----------------------+-----------------------------------------------------------+ +| Setting Name | Description | ++======================+===========================================================+ +| enabled | Process Raid Events only if ``true`` | ++----------------------+-----------------------------------------------------------+ +| defaults | Section for the default settings | ++----------------------+-----------------------------------------------------------+ +| filters | See below parameters | ++----------------------+-----------------------------------------------------------+ + + +Available DTS +------------------------------------- + +General +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +================= ================================================ =============================== +Parameter Description Example +================= ================================================ =============================== +monsters Array of allowed monsters, by id or name. ``["Raikou","244",245]`` +monsters_exclude Array of excluded monsters, by id or name. ``["Raikou","244",245]`` +min_raid_lvl Minimum level of the raid. ``0`` +max_raid_lvl Maximum level of the raid. ``5`` +min_cp Minimum CP of the monster. ``0`` +max_cp Maximum CP of the monster. ``100000`` +quick_moves Accepted quick moves, by id or name. ``["Vine Whip","Tackle"]`` +charge_moves Accepted charge moves, by id or name. ``["Sludge Bomb","Seed Bomb"]`` +current_teams List of allowed current teams, by id or name. ``["Instinct","Mystic"]`` +gym_name_contains List of regex's required to be in the gym name. ``["Sponsored","West\\sOak"]`` +gym_name_excludes List of regex's rejected to be in the gym name. ``["Sponsored","West\\sOak"]`` +================= ================================================ =============================== + + +Miscellaneous +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +=============== ====================================================== ============================== +Parameter Description Example +=============== ====================================================== ============================== +min_dist Min distance of event from set location in miles ``0.0`` * + or meters (depending on settings). +max_dist Max distance of event from set location in miles ``1000.0`` * + or meters (depending on settings). +min_time_left Minimum time (in seconds) until monster despawns. ``1000`` +max_time_left Maximum time (in seconds) until monster despawns. ``2400`` +weather Accepted weathers, by id or name. ``["Clear",2]`` +geofences See :ref:`geofences_filters` page on 'Geofences' ``["geofence1","geofence2"]`` +custom_dts See :ref:`custom_dts_filters` page on 'Custom DTS' ``{"dts1":"substitution"}`` +is_missing_info See :ref:`missing_info_filters` page on 'Missing Info' ``true`` or ``false`` +=============== ====================================================== ============================== + ++ Floats can use ``"inf"`` to represent infinity diff --git a/docs/configuration/filters/stop-filters.rst b/docs/configuration/filters/stop-filters.rst new file mode 100644 index 000000000..e383b961f --- /dev/null +++ b/docs/configuration/filters/stop-filters.rst @@ -0,0 +1,55 @@ +Stops +===================================== + +.. contents:: Table of Contents + :depth: 2 + :local: + +Prerequisites +------------------------------------- + +This page assumes: + ++ You have a working scanner. ++ You understand + `JSON formatting `_. ++ You are using the latest version of PokeAlarm. ++ You have read and understood the :doc:`index` page. + +Introduction +------------------------------------- + +The ``"stops"`` section has three distinct settings. + ++----------------------+-----------------------------------------------------------+ +| Setting Name | Description | ++======================+===========================================================+ +| enabled | Process Stop Events only if ``true`` | ++----------------------+-----------------------------------------------------------+ +| defaults | Section for the default settings | ++----------------------+-----------------------------------------------------------+ +| filters | See below parameters | ++----------------------+-----------------------------------------------------------+ + + +Available DTS +------------------------------------- + +Miscellaneous +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +=============== ====================================================== ============================== +Parameter Description Example +=============== ====================================================== ============================== +min_dist Min distance of event from set location in miles ``0.0`` * + or meters (depending on settings). +max_dist Max distance of event from set location in miles ``1000.0`` * + or meters (depending on settings). +min_time_left Minimum time (in seconds) until monster despawns. ``1000`` +max_time_left Maximum time (in seconds) until monster despawns. ``2400`` +geofences See :ref:`geofences_filters` page on 'Geofences' ``["geofence1","geofence2"]`` +custom_dts See :ref:`custom_dts_filters` page on 'Custom DTS' ``{"dts1":"substitution"}`` +is_missing_info See :ref:`missing_info_filters` page on 'Missing Info' ``true`` or ``false`` +=============== ====================================================== ============================== + ++ Floats can use ``"inf"`` to represent infinity diff --git a/docs/configuration/geofences.rst b/docs/configuration/geofences.rst new file mode 100644 index 000000000..6af2551b2 --- /dev/null +++ b/docs/configuration/geofences.rst @@ -0,0 +1,94 @@ +Geofences +===================================== + +.. contents:: Table of Contents + :depth: 2 + :local: + +Prerequisites +------------------------------------- + +This guide assumes the following: + ++ You are using the latest version of PokeAlarm. ++ You understand how :doc:`filters/index` work. ++ You understand how :doc:`managers` work. + +Introduction +------------------------------------- + +A **Geofence** is a geographic boundary, described as a polygon formed by a +series of points. Each point is represented by coordinates of latitude and +longitude. For example, this is a geofence that surrounds Central Park: + +.. image:: images/geofence_central_park_bounded.png + :align: center + + +Defining Geofences +------------------------------------- + +Each Geofence is composed of a name and a list of points. The first line of the +description must be the name, surrounded by square brackets. The points of the +Geofence follow, each as a pair of coordinates on a separate line. The Geofence +around Central Park would be described as follows: + +.. code-block:: none + + [Central Park] + 40.801206,-73.958520 + 40.767827,-73.982835 + 40.763798,-73.972808 + 40.797343,-73.948385 + +In this case, the name is ``Central Park`` and it has 4 points, one for each +corner of the park. There are no limits on how big your geofence can be, but do +note that additional points may require increase processing time. + +If using multiple geofences, they must be listed consecutively, with no empty +spaces. + + +Filtering on Geofences +------------------------------------- + +.. note:: In order to filter by a geofence, you must load a file describing + your geofences. See the :doc:`managers` page for specifics. + +Using the ``"geofence"`` restriction, you can filter events by requiring them to +be located inside one of the geofences you have defined: + +.. code-block:: json + + "geofence example": { + "geofence": [ "Central Park", "Geofence #2", "Geofence #3" ] + } + +.. note:: An event is only compared to a Geofence if it is listed in the + filter. This means that PA does not waste time checking unlisted + geofences, but also means the `` DTS doesn't work unless + you have a geofence restriction specified. + +You can also use the ``"all"`` shortcut, if you have a large number of +geofences and find it cumbersome to list them all. It is equivalent to listing +every Geofence attached to a Manager: + +.. code-block:: json + + "geofence example": { + "geofence": [ "all" ] + } + + +Notes +------------------------------------- + +Differences from Rocketmap +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +If you are using the same Geofences for both Rocketmap and PokeAlarm, it's +possible that you may see an event get rejected by PokeAlarm. This is because +RM and PA use Geofences differently. RM uses them to rescrit work movement, but +PA uses them to restrict events. As a result, RM will occasionally send +an Event that PA will reject. If this is a problem, you can either +increase the size of your PA geofences, or remove them all together. \ No newline at end of file diff --git a/docs/images/geofence_central_park_bounded.png b/docs/configuration/images/geofence_central_park_bounded.png old mode 100755 new mode 100644 similarity index 100% rename from docs/images/geofence_central_park_bounded.png rename to docs/configuration/images/geofence_central_park_bounded.png diff --git a/docs/settings/managers.md b/docs/configuration/managers.md similarity index 50% rename from docs/settings/managers.md rename to docs/configuration/managers.md index 2da0d3ffd..e769b8942 100644 --- a/docs/settings/managers.md +++ b/docs/configuration/managers.md @@ -13,49 +13,51 @@ This guide will walk you through configuring server settings for PokeAlarm. * [Timezones](#timezones) ## Prerequisites + This guide assumes the following: -1. You have correctly [installed PokeAlarm](installation). +1. You have correctly [installed PokeAlarm](../getting-started/installation.html). 2. You are using Notepad++, Nano, or Vi(m) to configure any files. Do **NOT** use or open any files with Notepad or TextEdit - they will break your files! ## Introduction + In PokeAlarm, a **Manager** is a grouping of different settings. Managers allow you to configure multiple combinations of filters, alarms, geofences, -and other settings behind single webserver +and other settings behind single webserver. -![Manager Example](../images/v3_overview.png) +![Manager Example](../images/managers.png) -Webhooks are received by the PokeAlarm server, which then passes a copy to -the manager. Each Manager determines (independently)if the alert passes one -of the set filters (and geofence if enabled). If it does, the Manager sends -the alert to the alarm defined in the Alarms file. +Webhooks are received by the PokeAlarm server, which then passes a copy to the +manager. Each Manager determines (independently)if the alert passes one of the +set filters (and geofence if enabled). If it does, the Manager sends the alert +to the alarm defined in the Alarms file. PokeAlarm runs each Manager in a separate process, allowing each Manager to operate in parallel and taking advantage of multiple cores. ## Multiple Managers - Managers can be configured using either the command line or the configuration - file. In order to run multiple managers, you must first set `manager_count` - equal to the number of mangers you want to run. Managers use the arguments of - a type in order. If only one argument (of a type) is provided, this argument - will be applied to all Managers. For example, the following command: - ``` - python start_pokealarm.py -m 3 -f common.json -f rares.json -f uncommon.json -a alarms.json - ``` - This command sets up three managers. The first uses the filter file - `common.json`, the second uses the `rares.json`, and the third uses the - `uncommon.json`. However, all three managers will use the same `alarms.json` - file to set up their alarms. - - This same configuration can be accomplished via the following in the - configuration file: - - ```ini -manager_count: 1 +Managers can be configured using either the command line or the configuration +file. In order to run multiple managers, you must first set `manager_count` +equal to the number of mangers you want to run. Managers use the arguments of +a type in order. If only one argument (of a type) is provided, this argument +will be applied to all Managers. For example, the following command: + +``` +python start_pokealarm.py -m 3 -f common.json -f rares.json -f uncommon.json -a alarms.json +``` + +This command sets up three managers. The first uses the filter file +`common.json`, the second uses the `rares.json`, and the third uses the +`uncommon.json`. However, all three managers will use the same `alarms.json` +file to set up their alarms. +This same configuration can be accomplished via the following in the configuration file: + +```ini +manager_count: 3 filters: [ common.json, rares.json, uncommon.json ] alarms: alarms.json ``` @@ -64,34 +66,34 @@ alarms: alarms.json ### Manager Names -Manager names are currently useful for logging purposes only. Changing the -name will change the name of the logger used in PA's output. Manager names -are configured the same as other parameters: +Manager names are currently useful for logging purposes only. Changing the name +will change the name of the logger used in PA's output. Manager names are +configured the same as other parameters: ```ini manager_name: [ manager_0, manager_1, manager_2 ] ``` -If no manager name is defined, PA will name that manager automatically based -on it's order. +If no manager name is defined, PA will name that manager automatically based on +it's order. ### Geofences Geofences are a useful tool and can be bound in a mixture of combinations to -different Managers. Configuring geofence files is similar to other options: +different managers. Configuring geofence files is similar to other options: ```ini geofence: [ city1.json, none, city2.json ] ``` -As you can see, you can mix managers with geofences and without by using -`none` for any managers that you don't want a geofence file loaded for. +As you can see, you can mix managers with geofences and without by using `none` +for any managers that you don't want a geofence file loaded for. -You can find more information about Geofences on the [Geofences](geofences) +You can find more information about Geofences on the [Geofences](geofences.html) wiki page. ### Timezones By default PA will use your server time for notifications. If you wish to change this timezone, you can use either the `-tz` or `--timezone` to set a -timezone. A full list of compatible timezones can be found [here](https://en.wikipedia.org/wiki/List_of_tz_database_time_zones). +timezone. A full list of compatible timezones can be found [here](https://en.wikipedia.org/wiki/List_of_tz_database_time_zones). diff --git a/docs/configuration/rules.rst b/docs/configuration/rules.rst new file mode 100644 index 000000000..2b6b673aa --- /dev/null +++ b/docs/configuration/rules.rst @@ -0,0 +1,111 @@ +Rules +===================================== + +.. contents:: Table of Contents + :depth: 2 + :local: + +Prerequisites +------------------------------------- + +This guide assumes the following: + ++ You are using the latest version of PokeAlarm. ++ You understand how to configure :doc:`filters/index`. ++ You understand how to configure :doc:`alarms/index`. + + +Introduction +------------------------------------- + +In PokeAlarm, a **Rule** is a what decides which :doc:`filters/index` are +checked before being sent to which :doc:`alarms/index`. When PA processes an +Event, each Rule is a chance for a notification to be sent. The Event is +compared against each Filter listed, until it finds a match. Once matched, it +is passed on the listed Alarms, triggering a notification for each. + +If no rules are defined, PA follows the "default" rule. It checks every Filter +available, and if it finds a match it triggers every Alarm. By setting a +Rule, you can customize this behavior. + +.. warning:: Rules are processed independently of each other. If an Alarm is + listed in two different Rules that both pass, it's possible for a + notification to trigger twice. + +Custom Rules +------------------------------------- + +A **Rule** is represented as *named* JSON Object with only two parameters. +``"filters"`` is a list of Filters by name, and ``"alarms"`` is a list of +Alarms by name. + +.. warning:: Attempting to create a Rule with a non existent Filter or Alarm + will throw an error - make sure your spelling is correct! + +.. code-block:: json + + "rule_example": { + "filters": ["filter_name_1", "filter_name_2", "filter_name_3"], + "alarms": ["alarm_name_1", "alarm_name_2", "alarm_name_3"] + } + +In the above example, PA wil check ``"filter_name_1"``, followed by +``"filter_name_2"``, followed by ``"filter_name_3"``. If at any point an Event +matches a filter, it will cease checking and triggers all 3 listed Alarms. + +Rules File +------------------------------------- + +A *rules file* (sometimes referred to as ``rules.json``) is a file describing +the rules that PA uses. By default, PA doesn't load any rules file. See the +:doc:`../server-settings` page for instructions on specifying the file. +This file must contain a single JSON object to load successfully: + +.. code-block:: json + + { + + } + +Inside this JSON object, you need to add sections for each type of Filter you +wish to add. Sections are optional, and unspecified sections will use the +default rule. + +.. code-block:: json + + { + "monsters":{ + }, + "stops":{ + }, + "gyms":{ + }, + "eggs":{ + }, + "raids":{ + } + } + +Each section is a JSON object that can contain the rules for that section. For +example, a potential ``"monsters`` section might look like this: + +.. code-block:: json + + { + "monsters":{ + "my_first_rule": { + "filters": ["uncommon_spawns", "okay_spawns"], + "alarms": ["discord_okay_channel", "telegram_okay_channel"] + }, + "my_second_rule": { + "filters": ["100iv", "best_spawns"], + "alarms": ["discord_best_channel", "telegram_best_channel"] + } + } + } + +In the above, if an Event passes either the ``"uncommon_spawns"`` or the +``"okay_spawns"`` filter, it will trigger the ``"discord_okay_channel"`` and +``"telegram_okay_channel"`` alarms. However, if it passes either the +``"100iv"`` or ``"best_spawns"`` filter, then it will trigger the +``"discord_best_channel"`` and ``"telegram_best_channel"`` alarms. diff --git a/docs/configuration/server-settings.md b/docs/configuration/server-settings.md new file mode 100644 index 000000000..a2048da7c --- /dev/null +++ b/docs/configuration/server-settings.md @@ -0,0 +1,200 @@ +# Server Settings + +## Overview + +This guide will walk you through configuring server settings for PokeAlarm. + +* [Prerequisites](#prerequisites) +* [Server Settings](#server-settings) +* [Command Line](#command-line) +* [Configuration File](#configuration-file) + +## Prerequisites + +This guide assumes the following: + +1. You have correctly [installed PokeAlarm](../getting-started/installation.html). + +2. You are using Notepad++, Nano, or Vi(m) to configure any files. Do **NOT** +use or open any files with Notepad or TextEdit - they will break your files! + +## Server Settings + +Settings for the PokeAlarm server can be done the following two ways: + +1. **Command Line** - When starting PokeAlarm, you can specify certain settings +with flags following the start up command. For example, you can change the IP +that PokeAlarm binds itself to by using either `python start_pokealarm.py -H +192.168.0.1` or `python start_pokealarm.py --host 192.168.0.1`. + **Note**: when used together, command line flags will override arguments + specified in the configuration file. + +2. **Configuration File** - You can also use a configuration file in `ini` +format to set server settings for PokeAlarm. These settings use the same flags +at the command line. For example, you either `host: 192.168.0.1` or +`H: 192.168.0.1` line to the configuration file to change the IP that PokeAlarm +binds itself to. + +For files, all relative paths will being from the PokeAlarm root folder, but +absolute file paths can still be used. + +## Command Line + +To get the most recent command line settings for your version, use the +following command: `python start_pokealarm.py --help`. + +``` +usage: start_pokealarm.py [-h] [-cf CONFIG] [-d] [-H HOST] [-P PORT] + [-C CONCURRENCY] [-m MANAGER_COUNT] + [-M MANAGER_NAME] [-f FILTERS] [-a ALARMS] + [-r RULES] [-gf GEOFENCES] [-l LOCATION] + [-L {de,en,es,fr,it,ko,pt,zh_hk}] + [-u {metric,imperial}] [-tz TIMEZONE] [-k GMAPS_KEY] + [--gmaps-rev-geocode GMAPS_REV_GEOCODE] + [--gmaps-dm-walk GMAPS_DM_WALK] + [--gmaps-dm-bike GMAPS_DM_BIKE] + [--gmaps-dm-drive GMAPS_DM_DRIVE] + [--gmaps-dm-transit GMAPS_DM_TRANSIT] + [-ct {mem,file}] [-tl TIMELIMIT] [-ma MAX_ATTEMPTS] + +optional arguments: + -h, --help Show this help message and exit. + -cf CONFIG, --config CONFIG + Configuration file. + -d, --debug Debug Mode. + -H HOST, --host HOST Set web server listening host. + -P PORT, --port PORT Set web server listening port. + -C CONCURRENCY, --concurrency CONCURRENCY + Maximum concurrent connections for the webserver. + -m MANAGER_COUNT, --manager_count MANAGER_COUNT + Number of Manager processes to start. + -M MANAGER_NAME, --manager_name MANAGER_NAME + Names of Manager processes to start. + -f FILTERS, --filters FILTERS + Filters configuration file. default: filters.json + -a ALARMS, --alarms ALARMS + Alarms configuration file. default: alarms.json + -r RULES, --rules RULES + Rules configuration file. default: None + -gf GEOFENCES, --geofences GEOFENCES + Alarms configuration file. default: None + -l LOCATION, --location LOCATION + Location, can be an address or coordinates. + -L {de,en,es,fr,it,ko,pt,zh_hk}, --locale {de,en,es,fr,it,ko,pt,zh_hk} + Locale for Pokemon and Move names: default en," + " + check locale folder for more options. + -u {metric,imperial}, --units {metric,imperial} + Specify either metric or imperial units to use for + distance " + "measurements. + -tz TIMEZONE, --timezone TIMEZONE + Timezone used for notifications. Ex: + "America/Los_Angeles" + -k GMAPS_KEY, --gmaps-key GMAPS_KEY + Specify a Google API Key to use. + --gmaps-rev-geocode GMAPS_REV_GEOCODE + Enable Walking Distance Matrix DTS. + --gmaps-dm-walk GMAPS_DM_WALK + Enable Walking Distance Matrix DTS. + --gmaps-dm-bike GMAPS_DM_BIKE + Enable Bicycling Distance Matrix DTS. + --gmaps-dm-drive GMAPS_DM_DRIVE + Enable Driving Distance Matrix DTS. + --gmaps-dm-transit GMAPS_DM_TRANSIT + Enable Transit Distance Matrix DTS. + -ct {mem,file}, --cache_type {mem,file} + Specify the type of cache to use. Options: ['mem', + 'file'] (Default: 'mem') + -tl TIMELIMIT, --timelimit TIMELIMIT + Minimum limit. + -ma MAX_ATTEMPTS, --max_attempts MAX_ATTEMPTS + Maximum attempts an alarm makes to send a + notification. +``` + +## Configuration File + +A copy of the most recent configuration file should be located at +`config/config.ini.example`. You can copy this file as a starting point. + +By default, PokeAlarm will load the file at `config/config.ini` if it exists. +You can manually specify a configuration file with either the `-cf` or +`--config` file via the command line. + +```ini +# DO NOT USE NOTEPAD OR TEXTEDIT TO EDIT FILES! +# USE AN EDITOR SUCH AS NOTEPAD++, ATOM, NANO OR VI(M) +# You can create a copy of this config and edit it to suit your needs. +# Uncomment a line (remove the #) when you want to change its default value. +# By default, PA will use `config/config.ini` to load settings. +# You can override the config file selection with `--config-file` or `-cf`. + + +######################## +# Webserver Settings +######################## + +#host: 127.0.0.1 # Interface to listen on (default='127.0.0.1') +#port: 4000 # Port to listen on (default='4000') +#concurrency: 200 # Maximum concurrent connections to webserver (default=200) +#manager_count: 1 # Number of Managers to run (default=1) +#debug # Enable debug logging (default='False) + + +######################### +# Manager Settings +######################### +# All of the settings below this line are manager-specific. +# If a single setting is supplied, it will apply to all Managers. +# Example: `locale: en` will set all Managers to english +# If an array of settings is supplied, they will be apply to Managers in order. +# Example: `locale: [ en, fr, en ]` sets a different language for 3 Managers. +# `None` can be used to exempt a Manager from an optional setting + +#manager_name: # Name of Manager, used for logging (default='manager#') + + +# File Settings +##################### +# File settings define location of files with settings for a Manager. +# Relative paths are presumed from install folder, root paths are absolute. + +#filters: filters.json # Filters for the Manager (default='filters.json') +#alarms: alarms.json # Alarms for the Manager (default='alarms.json') +#rules: rules.json # Rules for the Manager (default=None) +#geofence: geofence.txt # Geofences to be used in Filters (default=None) + + +# Location Specific +##################### +#location: # Location, as address or coordinates (default=None) +#locale: en # Language used for DTS translations (default='en') + # Options: ['de', 'en', 'es', 'fr', 'it', 'ko', 'pt', 'zh_hk' ] +#unit: imperial # Units used to measurements.(default='imperial') + # Options: ['imperial', 'metric' ] +#timezone: America/Los_Angeles # Timezones used for notifications. Default uses system time (default=None) + # Options: https://en.wikipedia.org/wiki/List_of_tz_database_time_zones + + +# GMaps Settings +################ +#gmaps-key: # Google Maps API Key (default=None) +#gmaps-rev-geocode: yes # Enable Reverse Geocoded DTS. (default='no') + # Note: This requires the Reverse Geocoding API to be enabled on your GMAPs key. +#gmaps-dm-walk: yes # Enable Walking DM DTS. (default='no') + # Note: This requires the Distance Matrix API to be enabled on your GMAPs key. +#gmaps-dm-bike: yes # Enable Bicycling DM DTS. (default='no') + # Note: This requires the Distance Matrix API to be enabled on your GMAPs key. +#gmaps-dm-drive: yes # Enable Driving DM DTS. (default='no') + # Note: This requires the Distance Matrix API to be enabled on your GMAPs key. +#gmaps-dm-transit: yes # Enable Transit DM DTS. (default='no') + # Note: This requires the Distance Matrix API to be enabled on your GMAPs key. + + +# Miscellaneous +################ +#cache_type: file # Type of cache used to share information between webhooks. (default='mem') + # Options: ['mem', 'file'] +#timelimit: 0 # Minimum seconds remaining on an Event to trigger notification (default=0) + # Note - `max_attempts` is being deprecated and may be replaced by alarm-level settings +#max_attempts: 3 # Maximum number of attempts an alarm makes to send a notification. (default=3) +``` diff --git a/docs/contents/faq.md b/docs/contents/faq.md deleted file mode 100644 index 512d9c839..000000000 --- a/docs/contents/faq.md +++ /dev/null @@ -1,141 +0,0 @@ -# FAQ - -## Overview -* [General Info](#general-info) -* [Troubleshooting](#troubleshooting) - -## General Info - -These are general questions about PA and it's development. - -#### Where should I go for support? -* If, after *carefully* reading the Wiki and the rest of this FAQ, you -can visit our [Discord](https://discordapp.com/invite/S2BKC7p). Make -sure to read the rules channel, so you don't inadvertently get banned. - -#### What scanners are supported? -* Currently RocketMap (RM) and Monocle are compatible with PA. -If you are interested in adding support for your program, feel free to -read the [Webhook Standards](webhook-standard) and ask us in Discord -what you can do to add support for PA. - -#### I have a great idea for a new feature! -* Open a Feature Request on our Github page. Use the -[correct template](https://github.com/PokeAlarm/PokeAlarm/issues/new) -- Please **DO NOT** just ask for a feature in Discord. There is a lot of -chat in discord and your request will certainly get lost. Issues let us -track the request and real with it in a more concrete manor. -- If you see a request you like, be sure to comment on it to show your -support! - - -#### Do you accept PRs? -* Yup - you can submit them via Github. If it is a big change, feel free -to approach us before so we can coordinate better. - -#### Do you support new services? -* Please check in the -[New/Upcoming Services MEGA-THREAD](https://github.com/RocketMap/PokeAlarm/issues/147) -to see if the service has already been requested. If it hasn't, feel -free to leave a post requesting it. - -#### How can I support PokeAlarm? -* Besides submitting PRs or helping us with the -[Wiki](https://github.com/PokeAlarm/PokeAlarmWiki), you can support -Deadly (the creator of PA) on -[Patreon](https://www.patreon.com/pokealarm). - - -## Troubleshooting - -#### PokeAlarm complains about a `ValueError` error and says I need to talk to some guy named JSON? -1. Make sure you didn't open any files with Notepad or TextEdit - they -can break the encoding on your files. Use Notepad++ or a better editor. -2. If you sure that isn't the problem, then you probably have an error -with your JSON Formatting. Look up how JSON formatting works and use a -[JSON Editor](http://www.jsoneditoronline.org/) to find your problem. - -#### Why isn't `` working right? -* You must have gym-details enabled in your scanner and webhook options. -* Most scanners don't send the gym-details with every gym related -webhook - PA will cache the details and try to remember them, but -this goes away upon restart. It takes time for the scanner to send all -the details. - -You can use file-caching to save the gym names to a file so that they -are available upon restart. Check out the -[Object Caching](object-caching) page for more information. - -#### How can I optimize PokeAlarm? -PA uses Gevent and Multiprocessing to be as responsive as possible to -incoming requests. However (due to language and hardware limitations), -it is possible for PA to be overwhelmed and have a hard time handling -requests for large setups. If you are experiencing problems, you can try -the following options: -1. If on Windows, try Linux (even a VM will see large improvements). -2. Run PA on a separate server. -3. Lower the number of managers you are using. Each manager runs in its -own process, which makes it expensive. -4. If possible, separate scanners and pa instances into smaller groups -and even onto different servers. -5. Upgrade your server hardware. - -PA also has a `concurrency` setting that can be lowered - it limits the -number of active connections allowed to it. This will prevent PA - -Additionally, there are a number of settings in RM to optimize: -1. Disable extra webhooks - use RM's blacklist/whitelist and disable -webhook types you aren't using. -2. Lower webhook-threads (`wh-concurrent` or similar) - This will cause -RM to send less connections at once. -3. Increase `wh-frame-interval` - Increase the number of events RM sends -at once to lower overhead. -5. Increase `wh-lfu-size` - this will increase RM's cache size to repeat -less information. -6. Increase `wh-backoff-factor` - Increase break between webhooks. -7. Increase `wh-connect-timeout` and `#wh-read-timeout` timeouts for RM. -This gives your server more time to react. -8. Decrease database threads `db-concurrency` or similar - uses less -sockets. -**Note:** Decreasing/Increase these settings may cause queue build up -in a variety of different places. It is a matter of trial and error to -find the ideal settings for your setup. - -Try the RM (or PA) discord for more info. - - -#### Error 10053 on Windows or Error 53 on Linux? -* This is an issue with too many open sockets on windows that causes -PA to be unable to open an new connections. See the above steps for -some suggestions on optimization. - - -#### RocketMap repeatedly spams `Caused by ReadTimeoutError("HTTPConnectionPool(host='127.0.0.1', port=4000)`? -* This mean's that RM is not connecting to PA for some reason: -1. Make sure PA is running. -2. Make sure RM is sending to the correct IP:PORT combo. -3. If the PokeAlarm instance is on a remote server, try increasing RM's -`wh-timeout` parameter (which defaults to 1s). -4. Check hardware for a bottleneck. See above for optimizations. - -#### Why do some DTS (``, etc) or another DTS show up as `?`? -* PA replaces DTS that are used with `?`, `???`, or `unknown` when it -doesn't know the correct information. This could be a variety of reasons - -#### Map images aren't showing up correctly... What can I do? -* Make sure you have added a [Google API Key](google-maps-api-key) and -have the Static Maps API enabled. If you already have it enabled, make -sure that you haven't hit the limit for free users. - -#### Missing icons in your alerts? -* Remove your lines from `icon_url` and `avatar_url` from your -[Alarms](alarms) to use the default images in the PA. - -#### Do you want to use custom images in your alerts? -* Add in your alarms the option to add images (depends on the service -that is used) and add your url where the images are. For example, if you -use [Discord](discord) it will be something like this: - -``` -"icon_url":"https://raw.githubusercontent.com/user/PokeIcons/master/icons/.png" -``` diff --git a/docs/contents/installation.md b/docs/contents/installation.md deleted file mode 100644 index 4926c4d65..000000000 --- a/docs/contents/installation.md +++ /dev/null @@ -1,70 +0,0 @@ -# Installation - -## Overview - -This guide will walk you through the initial setup of PokeAlarm. - -* [Prerequisites](#prerequisites) -* [Installation](#installation) -* [Running PokeAlarm](#running-pokealarm) -* [Updating PokeAlarm](#updating-pokealarm) - -## Prerequisites - -This guide assumes the following: - -1. You have [Python 2.7](https://www.python.org/download/releases/2.7/) - successfully installed -2. You have [Git](https://git-scm.com/downloads) successfully installed -3. You have [RocketMap](https://github.com/RocketMap/RocketMap) or another - supported scanner successfully installed. -4. You have either Notepad++, Nano, or Vi(m) installed. Do **NOT** use or - open any files with Notepad or TextEdit - they will break your files! - -## Installation - -1. **Clone PokeAlarm locally** - Create a new folder to install PokeAlarm (it - is recommended you store it in a different folder than your scanner). Use - `git clone https://github.com/PokeAlarm/PokeAlarm.git` to create a local - copy of the project. - -2. **Install requirements** - Navigate into the root folder of your PokeAlarm - installation. Run `pip install -r requirements.txt --upgrade`. - This will install and update the packages that PokeAlarm needs to run. - -3. **Create your Filters configuration file** - Copy and paste - `alarms.json.example`. Rename the copy to `alarms.json`. This file will - tell PokeAlarm what information it should send. - -4. **Create your Alarms configuration file** - Copy and paste - `filters.json.example`. Rename the copy to `filters.json`. This file will - tell PokeAlarm what the alerts to say and what service to send them on. - -5. **Finish configuring PokeAlarm** - Now you should configure PokeAlarm. - Use the [Configuration Guide](started-guide) for more detailed instructions - on how to personalize PokeAlarm to fit your needs. - - -## Running PokeAlarm - -1. **Start PokeAlarm** - Run the command `python start_pokealarm.py` to - have PokeAlarm start and begin listening for information via webhooks. - **Note:** PokeAlarm installs some dependencies on the fly. If you encounter - errors when first running a new service, try running as root (with `sudo`) - to insure it can install the dependency. - -2. **Send webhooks to PokeAlarm** - Make sure you are sending your webhooks - to PokeAlarm by adding PokeAlarm's address to your scanner. If you are using - RocketMap (and the default PokeAlarm settings), add - `-wh http://127.0.0.1:4000` to your start up command or - `webhook:http://127.0.0.1:4000` to your `config.ini` file. - -## Updating PokeAlarm -Updating PokeAlarm is a simple process, provided you haven't changed any -files you weren't supposed to. For this reason, it is highly suggested not -to edit any files that end in the `.py` extension. -1. Open a command line in the root folder of your PokeAlarm installation. -2. Run `git pull`. -3. Run `pip install -r requirements.txt`. -4. Make sure to checkout the [Patch Notes](patch-notes) to see if any updates - to your config files are necessary. diff --git a/docs/css/custom.css b/docs/css/custom.css new file mode 100644 index 000000000..41fc91791 --- /dev/null +++ b/docs/css/custom.css @@ -0,0 +1,32 @@ +/* +Custom styles for PA rtd +*/ + +.boltitalic { + font-weight: bold; + font-style: italic; +} + +.underline { + text-decoration: underline; +} + +.underlinebold { + text-decoration: underline; + font-weight: bold; +} + +.underlineitalic { + text-decoration: underline; + font-style: italic; +} + +.underlineboita { + text-decoration: underline; + font-weight: bold; + font-style: italic; +} + +.strike { + text-decoration: line-through; +} diff --git a/docs/documentation/patch-notes.md b/docs/documentation/patch-notes.md deleted file mode 100644 index 5c9fc6248..000000000 --- a/docs/documentation/patch-notes.md +++ /dev/null @@ -1,235 +0,0 @@ -# Patch Notes - -## Patch History - -* [Patch 3.5](#patch-35) -* [Patch 3.4](#patch-34) -* [Patch 3.3](#patch-33) -* [Patch 3.2](#patch-32) -* [Patch 3.1](#patch-31) - ---- - -## Patch 3.5 - -This patch contains several breaking changes - make sure to read -carefully, back up your current configuration, and have some free time -before attempting to upgrade. -### Filters - -**Breaking Changes** - Filters have been completely reworked, with the -design focused on reducing managers and optimizing system resources. -Several filter parameter's have changed or been updated. For full -instructions on the new system, please see the new -[Filters](filters-overview) page in the wiki. - -Some highlights include: - * Custom DTS - new feature to define filter specific DTS - -### Server Settings - -* Added `concurrency` setting - Determines the maximum number of -concurrent connections PA will accept. Lowering this may help lower-end -systems improve the response time for their machines. - -### Alarms - -* **All** - * Updated default image urls for `icon_url` and `avatar_url`. These - default urls have built in cache busting - -* **Discord** - * `webhook_url` field is now DTS compatible - -* **Twilio** - * Now supports using an array of numbers for the `to` field in Alert - configurations. - -### Dynamic Text Substitutions - -* **Pokemon** - * `enc_id` changed to `encounter_id` - * `level` changed to `mon_lvl` - * `pkmn` changed to `mon_name` - * `pkmn_id` changed to `mon_id` - * `pkmn_id_3` changed to `mon_id_3` - * `form_id_3_or_empty` replaced with `form_id_3` - * `tiny_rat` - Updated to use weight instead of size. - * `big_karp` - Updated to use weight instead of size. - -* **Pokestops** - * `id` changed to `stop_id` - -* **Raids** - * `team_leader` - Reports the name of the team leader of the team in - control of the gym. - * `pkmn` changed to `mon_name` - * `raid_level` changed to `raid_lvl` - * `time_left` changed to `raid_time_left` - * `24h_time` changed to `24h_raid_end` - * `gym_image_url` changed to `gym_image` - -* **Eggs** - * `raid_level` changed to `egg_lvl` - * `begin_time_left` changed to `hatch_time_left` - * `time_left` changed to `raid_time_left` - * `begin_12h_time` changed to `12h_hatch_time` - * `begin_24h_time` changed to `24h_hatch_time` - * `gym_image_url` changed to `gym_image` - -* **Gyms** - * `gym_image_url` changed to `gym_image` - * `slots_available` - displays the number of open guard slots - available in a gym - * `guard_count` - displays the number of guards assigned to a gym - -### Misc - -* Added Gen3 Move information -* Updated Kyogre and Groudon stats -* Added Portuguese language translations - `pt` - ---- - -## Patch 3.4 - -### Server Settings - -* Implemented caching for managers with `-ct` or `--cache_type`. Cache is used to handling remembering things like pokemon history and gym names. - * (default) `mem` - data persists only in memory. - * `file` - data is saved and loaded from a file. -* PA now gracefully exits on ctrl+c, finishing items in queue and logging the status of managers. - -### Dynamic Text Substitutions - -* **All** - - * `lat_5` and `lng_5` - Latitude and Longitude for the event, truncated to 5 decimal places. - * `address_eu` - same as ` `. - -* **Pokemon** - - * `form_or_empty` - Reports the form name of the pokemon if known, or an empty string if unknown. - * `pkmn_id_3` - pokemon id padded to 3 digits. - * `form_id_or_emtpy` - prints form_id padded to 3 digits if known, or and empty string if unknown. - -* **Raids** - * `form_or_empty` - Reports the form name of the pokemon if known, or an empty string if unknown. - * `team_name` - Reports the current team for a Raid gym if known, or 'unknown' if not. - * `team_id` - Reports the current team id for a Raid gym if known, or '?' if not. - * `min_cp` and `max_cp` - min and max potential cp for the raid boss if caught. - * `pkmn_id_3` - pokemon id padded to 3 digits. - * `form_id_or_emtpy` - prints form_id padded to 3 digits if known, or and empty string if unknown. - -### Tools - -* Webhook Tester - * Added `webhook_tester.py` for users to simulate sending events. - ---- - -## Patch 3.3 - -### Dynamic Text Substitution -* **Pokemon** - * (Re) added `'form'` DTS (and made it more robust). - -#### Server Settings -* **Reverse Location** - * Location services have been completely reworked to be more reliable. - * Location results now retrieve results set in whatever language is set for that manager. - * Location results now cache in memory - lowering overall API usage. - ---- - -## Patch 3.2 - -#### Filters -* **Pokemon** - * Pokemon can now be filtered by their form_id (example": `"form": [0, 1, 2]`). - * Pokemon can now be filtered by their gender (example": `"gender": ["male", "female"`). - * `'min_cp'` and `'max_cp'` are used to limit the CP of pokemon to alert. -* **Egg** - * "Egg" section is now added to the filters.json. - * `'enabled'` allows incoming raid alerts to be toggled on or off. - * `'min_level'` and `'max_level'` are used to limit the levels of incoming raids to alert on. -* **Raids** - * "Raids" section is now added to the filters.json. - * `'enabled'` allows raid alerts to be toggled on or off. - * `'default'` allows setting default settings for filters, and has the same options as pokemon filters do. - * Filters for pokemon raids can be set similar to the "pokemon" section, with the `"name": {}` scheme. - -#### Dynamic Text Substitution -* **General** - * Added `'applemaps'` to most alerts for AppleMaps link for iOS users. - * Time DTS now switch to ##h##m format when longer than one hour. -* **Pokemon** - * Added support for the following substitutions: `'cp', 'form', 'form_id', 'level'`. - * Added `'big_karp'` that displays 'big' on big magikarp and `'tiny_rat'` that displays 'tiny' on small rattata. -* **Egg** - * "Egg" alerts have the following substitutions: `'type', 'id', 'raid_level', 'raid_end', 'raid_being', 'lat', 'lng', 'gym_name', 'gym_description', 'gym_url'`. -* **Raid** - * "Raid" alerts have the following substitutions: `'type', 'id', 'pkmn_id', 'cp', 'quick_id', 'quick_damage', 'quick_dps', 'quick_duration', 'quick_energy', 'charge_id', 'charge_damage', 'charge_dps', 'charge_duration', 'charge_energy', 'raid_level', 'raid_end', 'raid_begin' 'lat', 'lng', 'gym_name', 'gym_description', 'gym_url'`. -* **Gyms** - * Added the following Gym substitutions: `'name', 'description', 'url'`. - * Added the following 'Gym Leader' substitutions: `'old_team_id', 'new_team_leader', 'old_team_leader'`. - -#### Alarms -* **Twitter** - * Twitter now automatically truncates to 140 characters - it will preserve links if added to the end. -* **Discord** - * Discord usernames now automatically truncates usernames to 32 characters. - * Added `'avatar_url'` to change the avatar of the post. - * Added `content` field that posts a message before the embed, allows for taging by user or roll. - * Added `'disable_embed'` that disables the discord embeds when set to `true`. - ---- - -## Patch 3.1 - -#### Filters -* **Multifilters** - Each filter can now be one of the following: - * `'True'` for all defaults, `'False'` for entirely disabled. - * A single filter in a json object (Ex: `{ "min_iv":"0", "max_iv" : "0" ... }`). - * Multiple filters inside an array: `[{"min_iv":"0", "max_iv":"25" }, {"min_iv":"75", "max_iv":"100"} ]`. - -* **Pokemon** - * All default filter parameters are now encapsulated in a single filter under the label `default`. - * `size` requires an array of valid sizes from the following: `['tiny', 'small', 'normal', 'large', 'big']`. - * `move_1` and `move_2` are now `quick_move` and `charge_move`. - * `size`, `quick_move`, `charge_move`, `moveset` filter parameters will accept any value when set to `null`. - -* **Pokestops** - * Now only two fields: `enabled` and `filters`. - * `filters` supports the Multifilter format with `min_dist` and `max_dist` fields. - -* **Gym** - * Now only three fields `enabled`, `ignore_neutral`, and `filters`. - * `filters` supports multifilters with the following fields: - * `from_team` - Array of valid previous team names. - * `to_team` - Array of valid current team names. - * `min_dist` and `max_dist` working as before. - -#### Dynamic Text Substitution -* `` added - the name of the first geofence in which the notification is in. -* `` now list either `'tiny'`, `'small'`, `'normal'`, `'large'`, or `'big'`. -* Quick moves now use the following: ``, ``, ``, ``, ``, ``. -* Charges moves now use the following: ``, ``, ``, ``, ``, ``. - -#### Alarms -* All Services - * `startup_list` is officially gone. -* Boxcar - * No longer supported. -* Discord - * `api_key` renamed to `webhook_url`. - * Will now retry if webhook was not received correctly. - * New optional alarm and alert level field: `map`. - * `enabled` - True of False to enabled/disabled map. - * Added other static map parameters. -* Slack - * `channel` parameter is now required at the Alarm level. - * Slack will no longer default to general if the correct channel cannot be found. - * Slack will still default to the Alarm level channel over the Alert level channel is not found (so everyone can still use ``!). -* Pushover - * No longer supported. diff --git a/docs/dts/dynamic-text-substitution.md b/docs/dts/dynamic-text-substitution.md deleted file mode 100644 index 1b6fb781b..000000000 --- a/docs/dts/dynamic-text-substitution.md +++ /dev/null @@ -1,105 +0,0 @@ -# DTS Overview - -## Overview - -* [Prerequisites](#prerequisites) -* [Introduction](#introduction) -* [Available DTS](#available-dts) -* [Advanced](#advanced) - * [Reverse Geocoding](#reverse-geocoding) - * [Distance Matrix](#distance-matrix) - -## Prerequisites - -This guide assumes: - -1. You have a working scanner. -3. You have read and understood the [Alarms](alarms) page. -4. You are comfortable with the layout of `alarms.json`. -5. You are using the latest version of PokeAlarm. - -## Introduction - -Dynamic Text Substitutions (or DTS) are special text values that -that are automatically change to useful text. These text values, when -surrounded with diamond brackets (`<` and `>`) are replaced by a value -customized to fit the Event. For example, the following text: - -`A wild has appeared! It has % IVs!` - -Will appear as the following if a perfect Charmander is sent: - -> A wild Charmander has appeared! It has 100.0% IVs! - -Or, it could appear like this if a mediocre Pidgey is sent: - -> A wild Pidgey has appeared! It has 55.6% IVs! - -If an Event doesn't have the correct information, it may display either -`?`, `???`, or `unknown` as the substitution. - -**Warning:** ONLY use the `alarms.json` to customize your notifications. -Editing other files may not work as correctly! - -## Available DTS - -The DTS that are available depend on the type of Event that trigger's a -notification. Currently PA supports five types of Events: -[Monsters](monster-dts), [Stops](stop-dts), [Gyms](gym-dts), -[Eggs](egg-dts), and [Raids](raid-dts). - -## Advanced - -### Reverse Geocoding - -**Reverse Geocoding** is a process that to get the name or data of -places where the Events take place. This can be used to get things such -as address, city, state, or more. For more information, see the -Geocoding section of the [Google Maps API](google-maps-api-key) page. - -PA will only use Reverse Geocoding for Events that have been triggered. -Each Event will use up a single point of your API quota, regardless -of number of fields or alarms used. - -| Text | Description | -|:---------------- |:--------------------------------------------------| -| `` | Street number of the alert location | -| `` | Street name of the alert location | -| `
` | Address of the alert location, includes both street number and street name, in that order only | -| `` | Address of the alert location, in european format (street name and street number) | -| `` | Postal code of the alert location | -| `` | Neighborhood code of the alert location | -| `` | Sublocality code of the alert location | -| `` | City code of the alert location | -| `` | County code of the alert location | -| `` | State code of the alert location | -| `` | Country code of the alert location | - -### Distance Matrix - -**Distance Matrix** calculations determine how far away an Event is, for -both time and distance. This can be Walking, Biking, or Driving. These -calculations require a set location, and a Google Maps API key. For more -information, see the Distance Matrix section of the -[Google Maps API](google-maps-api-key) page. - -| Text | Description | -|:---------------- |:--------------------------------------------------| -| `` | Estimated walking distance to the alert location | -| `` | Estimated walking time to alert location | - -| Text | Description | -|:---------------- |:--------------------------------------------------| -| `` | Estimated bike distance to the alert location | -| `` | Estimated bike time to alert location | - - -| Text | Description | -|:---------------- |:--------------------------------------------------| -| `` | Estimated drive distance to the alert location | -| `` | Estimated drive time to alert location | - -Each table represents 1 API quota used for all parameters per pokemon, -pokestop, or gym regardless of number of fields or alarms specified. For -example, `` and `` would require 2 points, but -`` and `` would only require 1 (per alert). diff --git a/docs/dts/egg-dts.md b/docs/dts/egg-dts.md deleted file mode 100644 index 1adcda574..000000000 --- a/docs/dts/egg-dts.md +++ /dev/null @@ -1,45 +0,0 @@ -# Egg DTS - -## Overview - -* [Prerequisites](#prerequisites) -* [Available DTS](#available-dts) - -## Prerequisites - -This page assumes: - -1. You have a working scanner. -2. You read and understood the [DTS](dynamic-text-substitution) page. -3. You are using the latest version of PokeAlarm. - -## Available DTS - -| DTS | Description | -|---------------- |-------------------------------------------------------- | -| gym_id | The gym id. Unique per gym. | -| egg_lvl | The tier level of the egg. | -| hatch_time_left | Time remaining until the egg hatches. | -| 12h_hatch_time | Time when the egg will hatch, formatted in 12h. | -| 24h_hatch_time | Time when the egg will hatch, formatted in 24h. | -| raid_time_left | Time remaining until the raid ends. | -| 12h_raid_end | Time when the raid ends, formatted in 12h. | -| 24h_raid_end | Time when the raid ends, formatted in 24h. | -| lat | Latitude of the raid. | -| lng | Longitude of the raid. | -| lat_5 | Latitude of the raid, truncated to 5 decimal places. | -| lng_5 | Longitude of the raid, truncated to 5 decimal places. | -| distance | Distance of the raid from the set location. | -| direction | Cardinal direction of the raid, from the set location. | -| gmaps | Google Maps link to the location of the raid. | -| applemaps | Apple Maps link to the location of the raid. | -| geofence | Geofence around the event. See 'Geofences' section from [filters](filters-overview#geofence) page.| -| gym_name | * The name of the gym. | -| gym_description | * The description of the gym. | -| gym_image | * The url to the image of the gym. | -| team_id | The id of the team currently in control of the gym. | -| team_name | The team currently in control of the gym. | -| team_leader | The leader of the team currently in control of the gym. | - -\* Gym Info requires caching. See the -[Object Caching](object-caching) page for more information. diff --git a/docs/dts/gym-dts.md b/docs/dts/gym-dts.md deleted file mode 100644 index 35ae9fc8b..000000000 --- a/docs/dts/gym-dts.md +++ /dev/null @@ -1,43 +0,0 @@ -# Gym DTS - -## Overview - -* [Prerequisites](#prerequisites) -* [Available DTS](#available-dts) - -## Prerequisites - -This page assumes: - -1. You have a working scanner. -2. You read and understood the [DTS](dynamic-text-substitution) page. -3. You are using the latest version of PokeAlarm. - -## Available DTS - -| DTS | Description | -|---------------- |--------------------------------------------------------- | -| gym_id | The gym id. Unique per gym. | -| lat | Latitude of the gym. | -| lng | Longitude of the gym. | -| lat_5 | Latitude of the gym, truncated to 5 decimal places. | -| lng_5 | Longitude of the gym, truncated to 5 decimal places. | -| distance | Distance of the gym from the set location. | -| direction | Cardinal direction of the gym, from the set location. | -| gmaps | Google Maps link to the location of the gym. | -| applemaps | Apple Maps link to the location of the gym. | -| geofence | Geofence around the event. See 'Geofences' section from [filters](filters-overview#geofence) page.| -| old_team | The team in control of the gym previously. | -| old_team_id | The id of the team in control of the gym previously. | -| old_team_leader | The leader of the team in control of the gym previously. | -| new_team | The team currently in control of the gym. | -| new_team_id | The id of the team currently in control of the gym. | -| new_team_leader | The leader of the team currently in control of the gym. | -| gym_name | * The name of the gym. | -| gym_description | * The description of the gym. | -| gym_image | * The url to the image of the gym. | -| slots_available | Number of open guard slots available in a gym. | -| guard_count | number of guards assigned to a gym. | - -\* Gym Info require caching. See the -[Object Caching](object-caching) page for more information. diff --git a/docs/dts/monster-dts.md b/docs/dts/monster-dts.md deleted file mode 100644 index 441ce90fa..000000000 --- a/docs/dts/monster-dts.md +++ /dev/null @@ -1,68 +0,0 @@ -# Monster DTS - -## Overview - -* [Prerequisites](#prerequisites) -* [Available DTS](#available-dts) - -## Prerequisites - -This page assumes: - -1. You have a working scanner. -2. You read and understood the [DTS](dynamic-text-substitution) page. -3. You are using the latest version of PokeAlarm. - -## Available DTS - -| DTS | Description | -|---------------- |---------------------------------------------------------- | -| encounter_id | The encounter id. Unique per monster. | -| mon_name | The name of the monster's species. | -| mon_id | ID of the monster's species. | -| mon_id_3 | ID of the monster's species, padded to 3 digits. | -| time_left | Time remaining until the monster expires. | -| 12h_time | Time that the monster will disappear, in a 12h format. | -| 24h_time | Time that the monster will disappear, in a 24h format. | -| spawn_start | Estimated time that the monster spawn starts. | -| spawn_end | Estimated time that the monster spawn ends. | -| spawn_verified | Whether this spawn times have been verified. | -| lat | Latitude of the monster. | -| lng | Longitude of the monster. | -| lat_5 | Latitude of the monster, truncated to 5 decimal places. | -| lng_5 | Longitude of the monster, truncated to 5 decimal places. | -| distance | Distance of the monster from the set location. | -| direction | Cardinal direction of the monster, from the set location. | -| gmaps | Google Maps link to the location of the monster. | -| applemaps | Apple Maps link to the location of the monster. | -| geofence | Geofence around the event. See 'Geofences' section from [filters](filters-overview#geofence) page.| -| mon_lvl | Level of the monster. | -| cp | Combat Points of the monster. | -| iv | Individual Values percentage of the monster. | -| iv_0 | IVs, rounded to the nearest integer. | -| iv_2 | IVs, rounded to 2 decimal places. | -| atk | Attack IV of the monster. | -| def | Defense IV of the monster. | -| sta | Stamina IV of the monster. | -| form | Form name of the monster. | -| form_or_empty | Form name of the monster, or empty string if unknown. | -| form_id | Form ID for the monster. | -| form_id_3 | Form ID of the monster, padded to 3 digits. | -| quick_move | Name of the monster's quick move. | -| quick_id | ID of the monster's quick move. | -| quick_damage | Damage of the monster's quick move. | -| quick_dps | DPS of the monster's quick move. | -| quick_duration | Duration of the monster's quick move. | -| quick_energy | Energy generated by the quick move. | -| charge_move | Name of the monster's charge move. | -| charge_id | ID of the monster's charge move. | -| charge_damage | Damage of the monster's charge move. | -| charge_dps | DPS of the monster's charge move. | -| charge_duration | Duration of the monster's charge move. | -| charge_energy | Energy cost by the quick move. | -| gender | Gender of the monster, represented as a single character. | -| height | Height of the monster. | -| weight | Weight of the monster. | -| size | Estimated size of the monster. | -| big_karp | Return `big` if Magikarp weight is >=13.13. | -| tiny_rat | Return `tiny` if Rattata weight is <=2.41. | diff --git a/docs/dts/raid-dts.md b/docs/dts/raid-dts.md deleted file mode 100644 index 9f5738d12..000000000 --- a/docs/dts/raid-dts.md +++ /dev/null @@ -1,59 +0,0 @@ -# Raid DTS - -## Overview - -* [Prerequisites](#prerequisites) -* [Available DTS](#available-dts) - -## Prerequisites - -This page assumes: - -1. You have a working scanner. -2. You read and understood the [DTS](dynamic-text-substitution) page. -3. You are using the latest version of PokeAlarm. - -## Available DTS - -| DTS | Description | -|----------------- |-------------------------------------------------------- | -| gym_id | The gym id. Unique per gym. | -| raid_lvl | The tier level of the raid. | -| raid_time_left | Time remaining until the raid ends. | -| 12h_raid_end | Time when the raid ends, formatted in 12h. | -| 24h_raid_end | Time when the raid ends, formatted in 24h. | -| lat | Latitude of the raid. | -| lng | Longitude of the raid. | -| lat_5 | Latitude of the raid, truncated to 5 decimal places. | -| lng_5 | Longitude of the raid, truncated to 5 decimal places. | -| distance | Distance of the raid from the set location. | -| direction | Cardinal direction of the raid, from the set location. | -| gmaps | Google Maps link to the location of the raid. | -| applemaps | Apple Maps link to the location of the raid. | -| geofence | Geofence around the event. See 'Geofences' section from [filters](filters-overview#geofence) page.| -| mon_name | The name of the monster's species. | -| mon_id | ID of the monster's species. | -| mon_id_3 | ID of the monster's species, padded to 3 digits. | -| quick_move | Name of the monster's quick move. | -| quick_id | ID of the monster's quick move. | -| quick_damage | Damage of the monster's quick move. | -| quick_dps | DPS of the monster's quick move. | -| quick_duration | Duration of the monster's quick move. | -| quick_energy | Energy generated by the quick move. | -| charge_move | Name of the monster's charge move. | -| charge_id | ID of the monster's charge move. | -| charge_damage | Damage of the monster's charge move. | -| charge_dps | DPS of the monster's charge move. | -| charge_duration | Duration of the monster's charge move. | -| charge_energy | Energy cost by the quick move. | -| min_cp | Minimum potential CP of the monster. | -| max_cp | Maximum potential CP of the monster. | -| gym_name | * The name of the gym. | -| gym_description | * The description of the gym. | -| gym_image | * The url to the image of the gym. | -| team_id | The id of the team currently in control of the gym. | -| team_name | The team currently in control of the gym. | -| team_leader | The leader of the team currently in control of the gym. | - -\* Gym Info requires caching. See the -[Object Caching](object-caching) page for more information. diff --git a/docs/dts/stop-dts.md b/docs/dts/stop-dts.md deleted file mode 100644 index 023b3094b..000000000 --- a/docs/dts/stop-dts.md +++ /dev/null @@ -1,32 +0,0 @@ -# Stop DTS - -## Overview - -* [Prerequisites](#prerequisites) -* [Available DTS](#available-dts) - -## Prerequisites - -This page assumes: - -1. You have a working scanner. -2. You read and understood the [DTS](dynamic-text-substitution) page. -3. You are using the latest version of PokeAlarm. - -## Available DTS - -| DTS | Description | -|------------- |------------------------------------------------------- | -| stop_id | The stop id. Unique per stop. | -| time_left | Time remaining until the lure expires. | -| 12h_time | Time that the lure will disappear, in a 12h format. | -| 24h_time | Time that the lure will disappear, in a 24h format. | -| lat | Latitude of the stop. | -| lng | Longitude of the stop. | -| lat_5 | Latitude of the stop, truncated to 5 decimal places. | -| lng_5 | Longitude of the stop, truncated to 5 decimal places. | -| distance | Distance of the stop from the set location. | -| direction | Cardinal direction of the stop, from the set location. | -| gmaps | Google Maps link to the location of the stop. | -| applemaps | Apple Maps link to the location of the stop. | -| geofence | Geofence around the event. See 'Geofences' section from [filters](filters-overview#geofence) page.| diff --git a/docs/filters/egg-filters.md b/docs/filters/egg-filters.md deleted file mode 100644 index 3d54604b5..000000000 --- a/docs/filters/egg-filters.md +++ /dev/null @@ -1,48 +0,0 @@ -# Egg Filters - -## Overview - -* [Prerequisites](#prerequisites) -* [Introduction](#introduction) -* [Parameters](#parameters) - -## Prerequisites - -This page assumes: - -1. You have a working scanner. -2. You are familiar with -[JSON formatting](https://www.w3schools.com/js/js_json_intro.asp). -3. You are using the latest version of PokeAlarm. -4. You have read and understood the [Filters Overview](filters-overview) -page. - -## Introduction - -The `"eggs"` section has three distinct settings. - -| Setting Name | Description | -| -------------------- |---------------------------------------------------------- | -| enabled | Process Egg Events only if `true` | -| defaults | See [filters](filters-overview#defaults) page on defaults | -| filters | See below parameters | - -## Parameters - -Egg Filters can use the following parameters to filter Egg Events: - -| Parameter | Description | Example | -| ------------- |---------------------------------------------- |---------| -| min_dist | Min distance of event from set location in miles or meters (depending on settings). | `0.0` *| -| max_dist | Max distance of event from set location in miles or meters (depending on settings). | `1000.0` *| -| min_time_left | Minimum time (in seconds) until egg hatches. | `1000` | -| max_time_left | Maximum time (in seconds) until egg hatches. | `2400` | -| min_egg_lvl | Minimum level of the egg when hatched. | `0` | -| max_egg_lvl | Maximum level of the egg when hatched. | `5` | -| current_teams | List of allowed current teams, by id or name. | `[ "Instinct", "Mystic" ]` | -| gym_name_contains | List of regex's required to be in the gym name. | `[ "Sponsored" , "West\\sOak"]` | -| geofences | See [filters](filters-overview#geofence) page on 'Geofences' | `[ "geofence1", "geofence2" ]` | -| custom_dts | See [filters](filters-overview#custom-dts) page on 'Custom DTS' | `{ "dts1" : "substitution" }` | -| is_missing_info | See [filters](filters-overview#missing-info) page on 'Missing Info' | `true` or `false` | - -\* Floats can use `"inf"` to represent infinity diff --git a/docs/filters/filters-overview.md b/docs/filters/filters-overview.md deleted file mode 100644 index 1caf138ea..000000000 --- a/docs/filters/filters-overview.md +++ /dev/null @@ -1,261 +0,0 @@ -# Filters Overview - -## Overview - -* [Prerequisites](#prerequisites) -* [Introduction](#introduction) -* [Filter Parameters](#filter-parameters) -* [Defaults](#defaults) -* [Advanced](#advanced) - * [Missing Info](#missing-info) - * [Geofence](#geofence) - * [Custom DTS](#custom-dts) - -## Prerequisites - -This guide assumes: - -1. You have a working scanner -2. You are familiar with -[JSON formatting](https://www.w3schools.com/js/js_json_intro.asp) -3. You are using the latest version of PokeAlarm - -## Introduction - -**Filters** are used to determine which Events trigger notifications. -When PA receives information about an event, it is compared to the -filters defined in your `filters.json` configuration file. - -A `filters.json` file is composed of a single JSON object with five -different subsections. Each section defines different settings for each -different type of event. A list of parameters available for each type of -filter can be found on the following pages: -* [Monsters](monster-filters) -* [Stops](stop-filters) -* [Gyms](gym-filters) -* [Eggs](egg-filters) -* [Raids](raid-filters) - -The basic structure of `filters.json` is as follows: - -```json -{ - "monsters":{ - "enabled": false, - "defaults": { }, - "filters": { } - }, - "stops":{ - "enabled": false, - "defaults": { }, - "filters": { } - }, - "gyms":{ - "enabled": false, - "ignore_neutral": false, - "defaults": { }, - "filters": { } - }, - "eggs":{ - "enabled": false, - "defaults": { }, - "filters": { } - }, - "raids":{ - "enabled": false, - "defaults": { }, - "filters": { "filter-name" : { } } - } -} -``` - -## Filter Parameters - -Each section contains a `"filters"` subsection as a json object with -filters represented as key-value pairs. The key represents the -**filter name** paired to the corresponding **filter parameters**. Each -type of Event contains it's own parameters, which are listed on the -corresponding filters page for each filter. - -**IMPORTANT:** Filter's ONLY check parameters IF you list them. -Don't enter parameters that you don't want - this can cause unwanted -affects (for example `"min_dist"` with `"is_missing_info":true` will -reject ALL events if the server setting `location` is not set) - -An example filters section looks like this: - -```json -"filters": { - "filter_name_1": { - "monsters": [ 1, 2, 3 ], - "min_iv": 90.0, "max_iv": 100 - }, - "filter_name_2": { - "monsters": [ 4, 5, 6 ], - "min_iv": 90.0, "max_iv": 100 - } -} -``` - -The details of an event are only checked if it is defined as a filter -parameter. For example, a monster's species will only be checked by a -filter if the filter has the `"monsters"` parameter defined. - -Currently, a notification will only be triggered by the first filter it -passes - additional filters will NOT be checked once a match it found. - -## Defaults - -You can use the `"defaults"` section to easily apply default values to -all of the filters in that section. - -For example, the following section: - -```json -"defaults": { "min_iv": 90.0, "max_iv": 100 }, -"filters": { - "filter_name_1": { "monsters": [ 1, 2, 3 ] }, - "filter_name_2": { "monsters": [ 4, 5, 6 ] } -} -``` - -Which is equivalent to: - -```json -"filters": { - "filter_name_1": { - "monsters": [ 1, 2, 3 ], - "min_iv": 90.0, "max_iv": 100 - }, - "filter_name_2": { - "monsters": [ 4, 5, 6 ], - "min_iv": 90.0, "max_iv": 100 - } -} -``` - -Additionally, you can override or even disable defaults. Override them -by adding a new value, or disable them by using `null`. An example of -this is: - -```json -"defaults": { "min_iv": 90.0, "max_iv": 100 }, -"filters": { - "filter_name_1": { - "monsters": [ 1, 2, 3 ], - "min_iv": 85 - }, - "filter_name_2": { - "monsters": [ 4, 5, 6 ], - "min_iv": null, "max_iv": null - } -} -``` - -Which is equivalent to: - -```json -"filters": { - "filter_name_1": { - "monsters": [ 1, 2, 3 ], - "min_iv": 85, "max_iv": 100 - }, - "filter_name_2": { "monsters": [ 4, 5, 6 ] } -} -``` - -If a parameter is set to `null`, it is the same as not being set all. - -## Advanced - -### Missing Info - -For a variety of reasons, an Event may be missing information needed to -properly check it. In these cases, the `"is_missing_info"` parameter -decides how a filter handles it. - -**IMPORTANT:** `"is_missing_info"`: ONLY applies to necessary -information. Information is necessary only if being used to filter. If -`"min_iv"` or `"max_iv"` aren't set, it doesn't matter if `iv` is -unknown or not. - -With the `"is_missing_info": false` parameter, filters will ONLY allow -Events with all necessary information. If `"min_dist"` is set but the -`dist` is unknown, it will be rejected. - -With the `"is_missing_info": true` parameter, filters will ONLY allow -Events that ARE MISSING INFOrmation. If `"max_iv"` is set and the ivs -are unknown, it will be rejected. - -When `"is_missing_info"` is NOT included in the filter, it will simply -skip any checks on missing information. If you have `"min_iv":90.0` set -but no `"is_missing_info`", PA will still pass monsters -where `iv` is unknown. - -### Geofence - -For more information on configuring your `geofence.txt`, see the -[Geofence](geofences) page. - -You can require an Event to be inside specific geofences for a Filter. - -This example will check if an event is inside either `"fence1"` or -`"fence2"` as defined in: - -```json -"filter_name_1": { - "geofences": [ "fence1", "fence2" ] -} -``` - -Geofences are checked in order. The first geofence with the event inside - will be used to define the `` DTS. - -If no geofences are set, the `` DTS will always return -`unknown`. - -If a geofence with the set name does not exist, it will be skipped and -an error will print out to the console. - -Another example would be to configure alerts inside all of your geofences. -You just have to configure the geofences like this: - -```json -"filter_name_1": { - "geofences": [ "all" ] -} -``` - -### Custom DTS - -**Note:** See the [Dynamic Text Substitution](dynamic-text-substitution) -page for an explanation on using DTS. - -Custom DTS are filter specific DTS options that are added to the DTS for -an Event when it passes a filter. The `"custom_dts"` parameter can -contain key-value pairs of DTS that ONLY apply for that filter. - -For example: - -```json -"filters": { - "filter_name_1": { - "monsters": [ 1, 2, 3 ], - "custom_dts": { "family": "Grass starters" } - }, - "filter_name_2": { - "monsters": [ 4, 5, 6 ], - "custom_dts": { "family": "Fire starters" } - } -} -``` - -If the event passes the first filter, the text `` will return -`Grass starters`. If it passes the second filter, the text will return -`Fire Starters`. - -Custom DTS can be used for a variety of different things, including -customizing the Discord Webhook or Slack Channel. However they can never -override original DTS's. - -Currently, Custom DTS cannot make use of regular DTS. diff --git a/docs/filters/gym-filters.md b/docs/filters/gym-filters.md deleted file mode 100644 index 1558f49d7..000000000 --- a/docs/filters/gym-filters.md +++ /dev/null @@ -1,48 +0,0 @@ -# Gym Filters - -## Overview - -* [Prerequisites](#prerequisites) -* [Introduction](#introduction) -* [Parameters](#parameters) - -## Prerequisites - -This page assumes: - -1. You have a working scanner. -2. You are familiar with -[JSON formatting](https://www.w3schools.com/js/js_json_intro.asp). -3. You are using the latest version of PokeAlarm. -4. You have read and understood the [Filters Overview](filters-overview) -page. - -## Introduction - -The `"gyms"` section has four distinct settings. - -| Setting Name | Description | -| -------------------- |---------------------------------------------------------- | -| enabled | Process Gym Events only if `true` | -| ignore_neutral | If `true`, ignore uncontested gyms | -| defaults | See [filters](filters-overview#defaults) page on defaults | -| filters | See below parameters | - -## Parameters - -Gym Filters can use the following parameters to filter Gym Events: - -| Parameter | Description | Example | -| ----------- |------------------------------------------------------------------------- |------------------- | -| min_dist | Min distance of event from set location in miles or meters (depending on settings). | `0.0` * | -| max_dist | Max distance of event from set location in miles or meters (depending on settings). | `1000.0` * | -| old_teams | List of allowed previous teams, by id or name. | `[ "Instinct", "Mystic" ]` | -| new_teams | List of allowed new teams, by id or name. | `[ "Valor", "Mystic" ]` | -| gym_name_contains | List of regex's required to be in the gym name. | `[ "Sponsored" , "West\\sOak"]` | -| min_slots | Minimum number of guard slots available. | `2` | -| max_slots | Maximum number of guard slots available. | `6` | -| geofences | See [filters](filters-overview#geofence) page on 'Geofences'. | `[ "geofence1", "geofence2" ]` | -| custom_dts | See [filters](filters-overview#custom-dts) page on 'Custom DTS'. | `{ "dts1" : "substitution" }` | -| is_missing_info | See [filters](filters-overview#missing-info) page on 'Missing Info'. | `true` or `false` | - -\* Floats can use `"inf"` to represent infinity diff --git a/docs/filters/monster-filters.md b/docs/filters/monster-filters.md deleted file mode 100644 index e6469b09c..000000000 --- a/docs/filters/monster-filters.md +++ /dev/null @@ -1,66 +0,0 @@ -# Monster Filters - -## Overview - -* [Prerequisites](#prerequisites) -* [Introduction](#introduction) -* [Parameters](#parameters) - -## Prerequisites - -This page assumes: - -1. You have a working scanner. -2. You are familiar with -[JSON formatting](https://www.w3schools.com/js/js_json_intro.asp). -3. You are using the latest version of PokeAlarm. -4. You have read and understood the [Filters Overview](filters-overview) -page. - -## Introduction - -The `"monsters"` section has three distinct settings. - -| Setting Name | Description | -| -------------------- |---------------------------------------------------------- | -| enabled | Process Monster Events only if `true` | -| defaults | See [filters](filters-overview#defaults) page on defaults | -| filters | See below parameters | - -## Parameters - -Monster Filters can use the following parameters to filter Events: - -| Parameter | Description | Example | -| ------------- |-------------------------------------------------- |---------- | -| monsters | Array of allowed monsters, by id or name. | `[ "Bulbasaur", "2", 3 ]`| -| min_dist | Min distance of event from set location in miles or meters (depending on settings). | `0.0` *| -| max_dist | Max distance of event from set location in miles or meters (depending on settings). | `1000.0` *| -| min_time_left | Minimum time (in seconds) until monster despawns. | `1000` | -| max_time_left | Maximum time (in seconds) until monster despawns. | `2400` | -| min_lvl | Minimum level of the monster. | `0` | -| max_lvl | Maximum level of the monster. | `40` | -| min_atk | Minimum attack IV of the monster. | `0` | -| max_atk | Maximum attack IV of the monster. | `15` | -| min_def | Minimum defense IV of the monster. | `0` | -| max_def | Maximum defense IV of the monster. | `15` | -| min_sta | Minimum stamina IV of the monster. | `0` | -| max_sta | Maximum stamina IV of the monster. | `15` | -| min_iv | Minimum total IV percentage of the monster. | `0.0` * | -| max_iv | Maximum total IV percentage of the monster. | `100.0` * | -| min_cp | Minimum CP of the monster. | `0` | -| max_cp | Maximum CP of the monster. | `10000` | -| form_ids | Array of allowed form ids for a monster. | `[ 0, "1" ]` | -| quick_moves | Accepted quick moves, by id or name. | `[ "Vine Whip", "Tackle"]` | -| charge_moves | Accepted charge moves, by id or name. | `[ "Sludge Bomb", "Seed Bomb"]` | -| genders | Array of acceptable genders. Options: `"male", "female", "neutral"` | `[ "female" ]` | -| min_height | Minimum height of the monster. | `0.0` * | -| max_height | Maximum height of the monster. | `250.0` * | -| min_weight | Minimum weight of the monster. | `0.0` * | -| max_weight | Maximum weight of the monster. | `250.0` * | -| sizes | Array of acceptable sizes. Options: `"tiny", "small", "normal", "large", "big"` | `[ "tiny", "big" ]` | -| geofences | See [filters](filters-overview#geofence) page on 'Geofences' | `[ "geofence1", "geofence2" ]` | -| custom_dts | See [filters](filters-overview#custom-dts) page on 'Custom DTS' | `{ "dts1" : "substitution" }` | -| is_missing_info | See [filters](filters-overview#missing-info) page on 'Missing Info' | `true` or `false` | - -\* Floats can use `"inf"` to represent infinity diff --git a/docs/filters/raid-filters.md b/docs/filters/raid-filters.md deleted file mode 100644 index 6c308145a..000000000 --- a/docs/filters/raid-filters.md +++ /dev/null @@ -1,53 +0,0 @@ -# Raid Filters - -## Overview - -* [Prerequisites](#prerequisites) -* [Introduction](#introduction) -* [Parameters](#parameters) - -## Prerequisites - -This page assumes: - -1. You have a working scanner. -2. You are familiar with -[JSON formatting](https://www.w3schools.com/js/js_json_intro.asp). -3. You are using the latest version of PokeAlarm. -4. You have read and understood the [Filters Overview](filters-overview) -page. - -## Introduction - -The `"raids"` section has three distinct settings. - -| Setting Name | Description | -| -------------------- |---------------------------------------------------------- | -| enabled | Process Raid Events only if `true` | -| defaults | See [filters](filters-overview#defaults) page on defaults | -| filters | See below parameters | - -## Parameters - -Raid Filters can use the following parameters to filter Raid Events: - -| Parameter | Description | Example | -| ------------- |---------------------------------------------- |--------- | -| monsters | Array of allowed monsters, by id or name. | `[ "Raikou", "244", 245 ]`| -| min_dist | Min distance of event from set location in miles or meters (depending on settings). | `0.0` *| -| max_dist | Max distance of event from set location in miles or meters (depending on settings). | `1000.0` *| -| min_time_left | Minimum time (in seconds) until raid ends. | `1000` | -| max_time_left | Maximum time (in seconds) until raid ends. | `2400` | -| min_raid_lvl | Minimum level of the raid. | `0` | -| max_raid_lvl | Maximum level of the raid. | `5` | -| min_cp | Minimum CP of the monster. | `0` | -| max_cp | Maximum CP of the monster. | `100000` | -| quick_moves | Accepted quick moves, by id or name. | `[ "Vine Whip", "Tackle"]` | -| charge_moves | Accepted charge moves, by id or name. | `[ "Sludge Bomb", "Seed Bomb"]` | -| current_teams | List of allowed current teams, by id or name. | `[ "Instinct", "Mystic" ]` | -| gym_name_contains | List of regex's required to be in the gym name. | `[ "Sponsored" , "West\\sOak"]` | -| geofences | See [filters](filters-overview#geofence) page on 'Geofences' | `[ "geofence1", "geofence2" ]` | -| custom_dts | See [filters](filters-overview#custom-dts) page on 'Custom DTS' | `{ "dts1" : "substitution" }` | -| is_missing_info | See [filters](filters-overview#missing-info) page on 'Missing Info' | `true` or `false` | - -\* Floats can use `"inf"` to represent infinity diff --git a/docs/filters/stop-filters.md b/docs/filters/stop-filters.md deleted file mode 100644 index b21c9dc69..000000000 --- a/docs/filters/stop-filters.md +++ /dev/null @@ -1,44 +0,0 @@ -# Stop Filters - -## Overview - -* [Prerequisites](#prerequisites) -* [Introduction](#introduction) -* [Parameters](#parameters) - -## Prerequisites - -This page assumes: - -1. You have a working scanner. -2. You are familiar with -[JSON formatting](https://www.w3schools.com/js/js_json_intro.asp). -3. You are using the latest version of PokeAlarm. -4. You have read and understood the [Filters Overview](filters-overview) -page. - -## Introduction - -The `"stops"` section has three distinct settings. - -| Setting Name | Description | -| -------------------- |---------------------------------------------------------- | -| enabled | Process Stop Events only if `true` | -| defaults | See [filters](filters-overview#defaults) page on defaults | -| filters | See below parameters | - -## Parameters - -Stop Filters can use the following parameters to filter Stop Events: - -| Parameter | Description | Example | -| ------------- |--------------------------------------------- |---------| -| min_dist | Min distance of event from set location in miles or meters (depending on settings). | `0.0` *| -| max_dist | Max distance of event from set location in miles or meters (depending on settings). | `1000.0` *| -| min_time_left | Minimum time (in seconds) until lure ends. | `1000` | -| max_time_left | Maximum time (in seconds) until lure ends. | `2400` | -| geofences | See [filters](filters-overview#geofence) page on 'Geofences' | `[ "geofence1", "geofence2" ]` | -| custom_dts | See [filters](filters-overview#custom-dts) page on 'Custom DTS' | `{ "dts1" : "substitution" }` | -| is_missing_info | See [filters](filters-overview#missing-info) page on 'Missing Info' | `true` or `false` | - -\* Floats can use `"inf"` to represent infinity diff --git a/docs/getting-started/faq.rst b/docs/getting-started/faq.rst new file mode 100644 index 000000000..15389cfd2 --- /dev/null +++ b/docs/getting-started/faq.rst @@ -0,0 +1,165 @@ +FAQ +===================================== + +.. contents:: Table of Contents + :depth: 2 + :local: + + +General +------------------------------------- + + +Where should I go for support? +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +If, after *carefully* reading the Wiki and the rest of this FAQ, you can visit +our `Discord `_. Make sure to read the +rules channel, so you don't inadvertently get banned. + +Feel free to also open an issue on our +`Github `_ - just make sure +to use the correct template and to fill out all the information! + + +What Scanner should I use? +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +We support a wide variety of scanners and forks - including Monocle, +Monocle-Alt, stock RocketMap, and RocketMap-Alt. PA relies on information from +Scanner via webhook - as a result, certain features may be available for some +scanners and not others. + + +How can I get request features? +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +Feel free to open an issue on our `Github`_ - just make sure to use the correct +template and to fill out all the information! + +If your request is for a new service, use the +`New/Upcoming Services MEGA-THREAD `__ +and mention you would like to see support for a certain service. + +Discord is NOT a good place to request new features - it's highly likely your +request will be missed or ignored. + + +Do you accept Pull Requests? +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Yup! Feel free to open on against our `Github`_ - however it is a significant +change, it is probably best to consult us first. + + +How else can I support PA? +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +Besides submitting PRs or helping with the Wiki, Deadly (the original creator +and maintainer of PA) has a `Patreon `_. + + +Startup Errors +------------------------------------- + + +PA throws a`ValueError` error about a JSON file? +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +First, make sure you haven't used Notepad or TextEdit on your configuration +files - they will disrupt the encoding on your file and cause issues. + +Second, make sure your file is in the correct JSON format - Google "JSON +Formatting" and use a `JSON Editor https://www.jsoneditoronline.org/`__ to +verify you are in the right format. + + +Error about a 'Queue'? +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +PA only supports Python2, and not Python3. + + +ModuleNotFoundError: No module named X +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +After updating PA, make sure you always check for updated requirements. +Run the command ``pip install -r requirements.txt --upgrade`` from the PA +folder. + + +Runtime Errors +------------------------------------- + +DTS reporting "Unknown" +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +If you see a DTS being replaced by "?", "???", or "Unknown", that usually means +that your scanner didn't send enough information to PA for it to determine its +value. This could be + + +Gym Name DTS reporting "Unknown" +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +RM doesn't do a good job of sending gym details through webhooks - to +make up for this, PA caches information between different webhooks. However +this cache takes a while to build up. You can also use the `file` cache to +prevent this cache + + +Why didn't I get an alert for this Event that is on my Map? +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +Make sure that your filters are set up exactly as you want them - in +particular, make sure you understand the "is_missing_info" restriction. You +can use the webhook tester (``python tools/webhook_test.py``) to recreate an +event to verify they are working correctly. + +Finally, check your scanner or PA for errors. If your scanner doesn't send the +info, PA can't process it. + + +Error 10053 (Windows) or Error 53 (Linux) +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +This error means that PA tried to use a closed connection. It generally happens +when the server PA is running on it overloaded. Check your CPU and Disk IO - if +it is spiking when you get these errors, your server is under heavy load. There +some things you can still do: + ++ If on Windows, use Linux (Even a VM will see huge improvements). ++ Run PA, your scanner, or your data base on separate servers if possible. ++ Optimize PA and your scanner setup. ++ Switch to a more efficient scanner (Monocle is typically harder to set up, + but more efficient than RocketMap) ++ If all else fails, upgrade your hardware. + + +How can I optimize PA? +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +Generally, the biggest improvement you can see is to eliminate multiple +instances using managers. Managers can be consolidated by +using Rules. Lower the number of geofences you use, or the number of points +they contain. Finally, you can try to lower the number of filters you are +using. + +Additionally, if you can set the 'concurrency' inside PA to a lower value - +this lowers the number of connections allowed to PA, which allows it to respond +faster. + + +How can I optimize my scanner? +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +For the most part, you should consult the maintainer of your scanner for tips. +Generally, you want to follow the same logic and work towards consolidating +instances. + +For RM in particular, there are default values you can adjust (particularly +around sending webhooks): ++ Disable extra webhooks - Use the blacklist/whitelist and disable types you + don't need. ++ ``wh-lfu-size`` - (increase to 5000 or more) - this will increase RM's cache + size and cause it to send less repeats. ++ ``wh-frame-interval`` - (increase up to 1000) - decreases the frequency in + which RM sends events. ++ ``wh-backoff-factor`` - (increase .5 to 1)- if a connection does fail, this + gives more time between retries. ++ ``wh-connect-timeout`` and ``wh-read-timeout`` - (PA recommends between 5 to + 10 seconds)- if you are experiencing periodic spikes of cpu or disk io, this + gives your server more time to appropriately handle this request. Lowering + this value could cause the connection to expire early, decreasing the chance + of the webhook being delivered successfully and adding additional overhead + from pipe errors and retries. ++ ``wh-threads`` and ``db-threads`` should be as low as possible (generally 1) diff --git a/docs/getting-started/installation.rst b/docs/getting-started/installation.rst new file mode 100644 index 000000000..07c5201c3 --- /dev/null +++ b/docs/getting-started/installation.rst @@ -0,0 +1,93 @@ +Installation +===================================== + +This guide will walk you through installing a fresh copy of PokeAlarm. + +.. contents:: Table of Contents + :depth: 1 + :local: + +Prerequisites +------------------------------------- + +This guide assumes the following: + +- Latest version of + `Python 2.7 `_ installed. +- `Git `_ installed. +- `Monocle `_, + `RocketMap `_, or another supported + scanner successfully installed. +- You are using a quality text editor like Notepad++, Nano, or Vi(m). + +.. warning:: Do **NOT** use (or even open) any files with Notepad or TextEdit - + they change the encoding on the file and prevent it from loading correctly. + + +Installing +------------------------------------- + +1. **Clone a local copy of PokeAlarm** - Navigate a new folder to install + PokeAlarm in (It is recommended you store it in a different folder than + your scanner). In a terminal, run the command + ``git clone https://github.com/PokeAlarm/PokeAlarm.git`` to create a + local copy of the project. This create a folder called 'PokeAlarm' that + will contain the application. + +2. **Install the Requirements** - In a terminal, navigate into the root folder + of your PA installation. Run ``pip install -r requirements.txt --upgrade``. + This will install and update the modules that PokeAlarm needs to run. + +3. **Configure PokeAlarm** - Next you need to configure PokeAlarm. + + - :doc:`../configuration/server-settings` let you configure things like host + IP, port, language, and more. + - :doc:`../configuration/filters/index` represent which Events trigger + notifications. You will need to create a filters file before starting PA. + - :doc:`../configuration/alarms/index` represent where and how + notifications. You will need to create an alarms file before starting PA. + + +Running +------------------------------------- + +1. **Start PokeAlarm** - In a terminal, use the command + ``python start_pokealarm.py`` to start PokeAlarm and begin listening for + information. If successful, you will see the following in the output: + + .. code:: none + + PokeAlarm is listening for webhooks on: http://127.0.0.1:4000 + +.. note:: PokeAlarm installs some dependencies on the fly. If you encounter + errors when first running a new service, try running as root (with `sudo`) to + ensure it can install the dependency. + +2. **Setup Scanner Webhook** - Next, configure your scanner to send information + to PA's address. + + - **For Monocle:** + The webhook info only works in `Hydro's fork `_. + + - **For RocketMap:** + Configure the webhook types to send info as explained in + `RocketMap wiki `_. + + Finally, start your scanner. If everything is set up correctly, PA will start + logging information about what it is doing to the console. + +Updating +------------------------------------- + +.. warning:: Updating PokeAlarm can be complicated if you edit files you aren't + supposed to. For this reason, we recommend not to edit any files ending in + ``.py``. + +1. Check the :doc:`../miscellaneous/patch-notes` for any big changes + that might break your current configuration. +2. Open up a command line and change directory to the root folder of your + install. +3. Run the command ``git pull && pip install -r requirements.txt`` to update to + the latest version. + +.. |br| raw:: html diff --git a/docs/guides/bug-feedback.md b/docs/guides/bug-feedback.md new file mode 100644 index 000000000..adbabeab4 --- /dev/null +++ b/docs/guides/bug-feedback.md @@ -0,0 +1,3 @@ +# Bug Reports / Feedback + +.. note:: This page is still under construction! Check back later! diff --git a/docs/contents/started-guide.md b/docs/guides/getting-started-guide.md similarity index 66% rename from docs/contents/started-guide.md rename to docs/guides/getting-started-guide.md index 832367763..b9a5bfad6 100644 --- a/docs/contents/started-guide.md +++ b/docs/guides/getting-started-guide.md @@ -1,4 +1,4 @@ -# Getting-Started-Guide +# Getting Started ## Overview @@ -21,8 +21,8 @@ and customizing PokeAlarm to fit your needs. This guide assumes the following: -1. You have correctly [installed PokeAlarm](installation), including -setting up a source for your information. +1. You have correctly [installed PokeAlarm](../getting-started/installation.html), +including setting up a source for your information. 2. You are using Notepad++, Nano, or Vi(m) to configure any files. Do **NOT** use or open any files with Notepad or TextEdit - they will @@ -43,27 +43,27 @@ server to do the following: ## Setting up an Alarm -In PokeAlarm, an 'Alarm' is a block in the Alarms.json section that +In PokeAlarm, an 'Alarm' is a block in the `alarms.json` section that represents how you want to receive an alert. For our example, we will use Discord, but the steps are similar between types of Alarms. To create a Discord Alarm, you should be familiar with these two pages: -1. Learn how to configure your alarms file with the [Alarms](alarms) +1. Learn how to configure your alarms file with the [Alarms](../configuration/alarms) wiki page. -2. Learn how to set up a Discord webhook url with the [Discord](discord) +2. Learn how to set up a Discord webhook url with the [Discord](../configuration/alarms/discord.html) wiki page. Once we have our webhook url set up, we can edit the default discord -alarm in the `alarms.json` file: +alarm in the `alarms.json` file: ```json -[ - { - "active": "True", - "type": "discord", - "webhook_url": "https://discordapp.com/api/webhooks/1234567890" +{ + "discord_alarm":{ + "active":true, + "type":"discord", + "webhook_url":"https://discordapp.com/api/webhooks/1234567890" } -] +} ``` **Note**: for brevity only the discord section is shown @@ -74,7 +74,7 @@ you should see a start up message posted in your discord channel! Filters are how PokeAlarm decides which Events get sent to sent to the Alarms to trigger notifications. To get all the details of Filters, -read the [Filters](filters-overview) wiki page. +read the [Filters](../configuration/filters) wiki page. In PokeAlarm, there are five different types of events. In a filter's config file, there is a section for setting filters in each type of @@ -94,12 +94,12 @@ to accept only the Charmander family: ```json { "monsters":{ - "enabled": true, - "defaults": { + "enabled":true, + "defaults":{ }, - "filters": { - "best_monsters": { - "monsters": ["Charmander", "Charmeleon", "Charizard"] + "filters":{ + "best_monsters":{ + "monsters":["Charmander","Charmeleon","Charizard"] } } } @@ -115,15 +115,15 @@ Charmander!). Let's add another filter, but for IV's above 90%. ```json { "monsters":{ - "enabled": true, - "defaults": { + "enabled":true, + "defaults":{ }, - "filters": { - "best_monsters": { - "monsters": ["Charmander", "Charmeleon", "Charizard"] + "filters":{ + "best_monsters":{ + "monsters":["Charmander","Charmeleon","Charizard"] }, - "okay_monsters": { - "monsters": ["Bulbasaur", 2, 3, 7, 8, 9], + "okay_monsters":{ + "monsters":["Bulbasaur", 2, 3, 7, 8, 9], "min_iv": 90 } } @@ -141,18 +141,18 @@ unintended things from happening!). Next, I want need to know when any of my team's gyms switch to another team (so I can go put them back up). I'll start with setting -`"old_teams": [ "Instinct" ]`. +`"old_teams":["Instinct"]`. ```json { "gyms":{ - "enabled": true, - "ignore_neutral": true, - "defaults": { + "enabled":true, + "ignore_neutral":true, + "defaults":{ }, - "filters": { - "clearly_the_best_team" : { - "old_teams": [ "Instinct" ] + "filters":{ + "clearly_the_best_team":{ + "old_teams":["Instinct"] } } }, @@ -162,7 +162,7 @@ team (so I can go put them back up). I'll start with setting This filter will allow in any gym that switches from Instinct to any other team. Additionally, we don't want to know about when it -switches to neutral, so we set `"ignore_neutral":"true"`. You can list +switches to neutral, so we set `"ignore_neutral":true`. You can list multiple different filters in the filters section of gyms, and PA will check them one by one. @@ -176,12 +176,12 @@ section of a filters file set up for legendary birds: ```json { "raids":{ - "enabled": true, - "defaults": { + "enabled":true, + "defaults":{ }, - "filters": { - "legendary-birds" : { - "monsters": [ 144, 145, 146, 249, 250 ] + "filters":{ + "legendary-birds":{ + "monsters":[144, 145, 146, 249, 250] } } } @@ -194,24 +194,24 @@ section of a filters file set up for legendary birds: PokeAlarm allows you to customize the Alerts that it sends out. We want to customize our Raid Alerts to show a more appropriate message. To add custom text to a Discord Alarm, you should be familiar with three pages: -1. Learn how to configure your alarms file with the [Alarms](alarms) +1. Learn how to configure your alarms file with the [Alarms](../configuration/alarms) wiki page. -2. Learn what fields Discord has to change with [Discord](discord) +2. Learn what fields Discord has to change with [Discord](../configuration/alarms/discord.html) wiki page. 3. Learn what DTS options are available to you with the -[Dynamic Text Substitution](dynamic-text-substitution) wiki page. +[Events](../configuration/events) wiki page. ```json -[ - { - "active": "True", - "type": "discord", - "webhook_url": "https://discordapp.com/api/webhooks/1234567890", +{ + "discord_alarm":{ + "active":true, + "type":"discord", + "webhook_url":"https://discordapp.com/api/webhooks/1234567890", "raids":{ - "title": "The Legendary Bird has appeared! It has CP!" + "title":"The Legendary Bird has appeared! It has CP!" } } -] +} ``` **Note**: for brevity only part of the alarms file is shown @@ -230,20 +230,20 @@ to your alarms file. If we wanted to customize pokemon alerts, we use the following: ```json -[ - { - "active": "True", - "type": "discord", - "webhook_url": "https://discordapp.com/api/webhooks/1234567890", - "pokemon":{ - "title": "The starter jumped out of the bushes!", - "body": "It has an IV of %!" +{ + "discord_alarm":{ + "active":true, + "type":"discord", + "webhook_url":"https://discordapp.com/api/webhooks/1234567890", + "monsters":{ + "title":"The starter jumped out of the bushes!", + "body":"It has an IV of %!" }, "raids":{ - "title": "The Legendary Bird has appeared! It has CP!" + "title":"The Legendary Bird has appeared! It has CP!" } } -] +} ``` **Note**: for brevity only part of the alarms file is shown @@ -260,7 +260,7 @@ isn't a starter pokemon! Let's add a second manager that allow us to customize even more. You can find out more about Manager's and their settings on the -[Managers](managers) wiki page. +[Managers](../configuration/managers.html) wiki page. First, lets make two different filter files. We will call the following filter file `starters_filter.json`: @@ -268,15 +268,15 @@ filter file `starters_filter.json`: ```json { "monsters":{ - "enabled": true, - "defaults": { + "enabled":true, + "defaults":{ }, - "filters": { - "best_monsters": { - "monsters": ["Charmander", "Charmeleon", "Charizard"] + "filters":{ + "best_monsters":{ + "monsters":["Charmander","Charmeleon","Charizard"] }, - "okay_monsters": { - "monsters": ["Bulbasaur", 2, 3, 7, 8, 9], + "okay_monsters":{ + "monsters":["Bulbasaur", 2, 3, 7, 8, 9], "min_iv": 90 } } @@ -287,15 +287,16 @@ filter file `starters_filter.json`: Next, we can make a second filter file for Dratini. We will call this one `dratini_filters.json`: + ```json { "monsters":{ - "enabled": true, - "defaults": { + "enabled":true, + "defaults":{ }, - "filters": { - "filter-name": { - "monsters": [ 147, 148, 149 ] + "filters":{ + "filter-name":{ + "monsters":[147, 148, 149] } } } @@ -308,40 +309,39 @@ ones from `dragon_filters.json`. So we need two different alarms files. Here is what our `starter_alarms.json` file looks like: ```json -[ - { - "active": "True", - "type": "discord", - "webhook_url": "https://discordapp.com/api/webhooks/1234567890", - "pokemon":{ - "title": "The starter jumped out of the bushes!", - "body": "It has an IV of %!" +{ + "discord_alarm":{ + "active":true, + "type":"discord", + "webhook_url":"https://discordapp.com/api/webhooks/1234567890", + "monsters":{ + "title":"The starter jumped out of the bushes!", + "body":"It has an IV of %!" } } -] +} ``` As you can see, it is the same one as before. Here is what the `dratini_alarms.json` file looks like: ```json -[ - { - "active": "True", - "type": "discord", - "webhook_url": "https://discordapp.com/api/webhooks/1234567890", - "pokemon":{ - "title": "The high IV dragon appears with a roar!", - "body": "It has an IV of %!" +{ + "discord_alarm":{ + "active":true, + "type":"discord", + "webhook_url":"https://discordapp.com/api/webhooks/1234567890", + "monsters":{ + "title":"The high IV dragon appears with a roar!", + "body":"It has an IV of %!" } } -] +} ``` Now we have two different filters and two different alarm files. Now we just need to set up the manager and link the filter to the alarm we want to use. When we start PokeAlarm, we can use the following: - ``` python start_pokealarm.py -m 2 -f starter_filters.json -a starter_alarms.json -f dratini_filters.json -a dragon_filters.json ``` @@ -354,13 +354,14 @@ Managers run in separate processes, so they run concurrently and scale well with the number of cores on your machine. However running too many managers can be inefficient and waste your computers resources. -> With great power comes great responsibility. +> *With great power comes great responsibility.* > -> \- Uncle Ben (about Managers, probably) +> \- **Uncle Ben** (about Managers, *probably*) Managers are a great tool that allow you to mix and match almost every setting to any filter or alarm settings. For full details on the power -of Managers, don't forget to check out [Managers](managers) wiki page. +of Managers, don't forget to check out [Managers](../configuration/managers.html) +wiki page. ## Advanced: Missing Info @@ -368,27 +369,27 @@ Sometimes, Event's are missing information needed to correctly filter them. In these instances, you can use the `"is_missing_info"` parameter to require a filter to reject or allow Events with missing information. You can read more about the feature on the -[Filters](filters-overview#missing-info) wiki page. +[Filters](../configuration/filters) wiki page. I really only want monsters like Bulbasaur and Squirtle to trigger notifications if they have the right ivs that I am looking for. If my scanner goofs up and doesn't get the ivs, I don't want to be bothered. -Setting `"is_missing_info": false` tells that filter to reject if +Setting `"is_missing_info":false` tells that filter to reject if any necessary information is missing. ```json { "monsters":{ - "enabled": true, - "defaults": { + "enabled":true, + "defaults":{ }, - "filters": { - "best_monsters": { - "monsters": ["Charmander", "Charmeleon", "Charizard"] + "filters":{ + "best_monsters":{ + "monsters":["Charmander","Charmeleon","Charizard"] }, - "okay_monsters": { - "monsters": ["Bulbasaur", 2, 3, 7, 8, 9], - "min_iv": 90, "is_missing_info": false + "okay_monsters":{ + "monsters":["Bulbasaur", 2, 3, 7, 8, 9], + "min_iv": 90, "is_missing_info":false } } } @@ -399,25 +400,25 @@ any necessary information is missing. Custom DTS is a feature that let's you define filter-specific DTS that ONLY work when that filter passes. You can read more about it on the -[Filters](filters-overview#custom-dts) wiki page. +[Filters](../configuration/filters) wiki page. I can use it to change certain text depending on which filters pass. ```json { "monsters":{ - "enabled": true, - "defaults": { + "enabled":true, + "defaults":{ }, - "filters": { - "best_monsters": { - "monsters": ["Charmander", "Charmeleon", "Charizard"], - "custom_dts": { "is_fav": "IS"} + "filters":{ + "best_monsters":{ + "monsters":["Charmander","Charmeleon","Charizard"], + "custom_dts":{"is_fav": "IS"} }, - "okay_monsters": { - "monsters": ["Bulbasaur", 2, 3, 7, 8, 9], - "min_iv": 90, "is_missing_info": false, - "custom_dts": { "is_fav": "IS NOT"} + "okay_monsters":{ + "monsters":["Bulbasaur", 2, 3, 7, 8, 9], + "min_iv": 90, "is_missing_info":false, + "custom_dts":{"is_fav": "IS NOT"} } } } @@ -446,23 +447,23 @@ I would modify my `filters.json` to add in a DTS: ```json { "monsters":{ - "enabled": true, - "defaults": { + "enabled":true, + "defaults":{ }, - "filters": { - "best_monsters": { - "monsters": ["Charmander", "Charmeleon", "Charizard"], - "custom_dts": { "channel_api_key": "11111"} + "filters":{ + "best_monsters":{ + "monsters":["Charmander","Charmeleon","Charizard"], + "custom_dts":{"channel_api_key": "11111"} }, - "okay_monsters": { - "monsters": ["Bulbasaur", 2, 3, 7, 8, 9], - "min_iv": 90, "is_missing_info": false, - "custom_dts": { "channel_api_key": "11111"} + "okay_monsters":{ + "monsters":["Bulbasaur", 2, 3, 7, 8, 9], + "min_iv": 90, "is_missing_info":false, + "custom_dts":{"channel_api_key":"11111"} }, - "okay_monsters_no_iv": { - "monsters": ["Bulbasaur", 2, 3, 7, 8, 9], - "min_iv": 90, "is_missing_info": true, - "custom_dts": { "channel_api_key": "22222"} + "okay_monsters_no_iv":{ + "monsters":["Bulbasaur", 2, 3, 7, 8, 9], + "min_iv": 90, "is_missing_info":true, + "custom_dts":{"channel_api_key":"22222"} } } } @@ -472,13 +473,13 @@ I would modify my `filters.json` to add in a DTS: Next, I can change my `alarms.json`: ```json -[ - { - "active": "True", - "type": "discord", - "webhook_url": "https://discordapp.com/api/webhooks/" +{ + "discord_alarm":{ + "active":true, + "type":"discord", + "webhook_url":"https://discordapp.com/api/webhooks/" } -] +} ``` Now, if it passes "best_monsters" or "okay_monsters" it'll send to the diff --git a/docs/images/01-blank-dashboard.png b/docs/images/01-blank-dashboard.png old mode 100755 new mode 100644 diff --git a/docs/images/02-create-project.png b/docs/images/02-create-project.png old mode 100755 new mode 100644 diff --git a/docs/images/03-new-project-name.png b/docs/images/03-new-project-name.png old mode 100755 new mode 100644 diff --git a/docs/images/04_project_created.png b/docs/images/04_project_created.png old mode 100755 new mode 100644 diff --git a/docs/images/05_library.png b/docs/images/05_library.png old mode 100755 new mode 100644 diff --git a/docs/images/06_enable_geocoding_api.png b/docs/images/06_enable_geocoding_api.png old mode 100755 new mode 100644 diff --git a/docs/images/07_enabled_geocoding_api.png b/docs/images/07_enabled_geocoding_api.png old mode 100755 new mode 100644 diff --git a/docs/images/08_dashboard_with_geocoding_api_enabled.png b/docs/images/08_dashboard_with_geocoding_enabled.png old mode 100755 new mode 100644 similarity index 100% rename from docs/images/08_dashboard_with_geocoding_api_enabled.png rename to docs/images/08_dashboard_with_geocoding_enabled.png diff --git a/docs/images/09_dashboard_with_geocoding_distance_staticmaps_api_enabled.png b/docs/images/09_dashboard_geocoding_distance_enabled.png old mode 100755 new mode 100644 similarity index 100% rename from docs/images/09_dashboard_with_geocoding_distance_staticmaps_api_enabled.png rename to docs/images/09_dashboard_geocoding_distance_enabled.png diff --git a/docs/images/10_credentials.png b/docs/images/10_credentials.png old mode 100755 new mode 100644 diff --git a/docs/images/11_credentials2.png b/docs/images/11_credentials2.png old mode 100755 new mode 100644 diff --git a/docs/images/12_select_browser_key.png b/docs/images/12_select_browser_key.png old mode 100755 new mode 100644 diff --git a/docs/images/13_key_name.png b/docs/images/13_key_name.png old mode 100755 new mode 100644 diff --git a/docs/images/14_here_is_your_key.png b/docs/images/14_here_is_your_key.png old mode 100755 new mode 100644 diff --git a/docs/images/15_find_your_key.png b/docs/images/15_find_your_key.png old mode 100755 new mode 100644 diff --git a/docs/images/fb-example.png b/docs/images/fb-example.png old mode 100755 new mode 100644 index 7f794b809..eb1737de7 Binary files a/docs/images/fb-example.png and b/docs/images/fb-example.png differ diff --git a/docs/images/geofence_central_park_640x640.png b/docs/images/geofence_central_park_640x640.png deleted file mode 100755 index 03eb68745..000000000 Binary files a/docs/images/geofence_central_park_640x640.png and /dev/null differ diff --git a/docs/images/geofence_coronado.png b/docs/images/geofence_coronado.png deleted file mode 100755 index d430809e6..000000000 Binary files a/docs/images/geofence_coronado.png and /dev/null differ diff --git a/docs/images/PokeAlarm.png b/docs/images/logo.png old mode 100755 new mode 100644 similarity index 100% rename from docs/images/PokeAlarm.png rename to docs/images/logo.png diff --git a/docs/images/v3_overview.png b/docs/images/managers.png old mode 100755 new mode 100644 similarity index 100% rename from docs/images/v3_overview.png rename to docs/images/managers.png diff --git a/docs/images/minimap.png b/docs/images/minimap.png old mode 100755 new mode 100644 diff --git a/docs/images/slack_demo.png b/docs/images/slack_example.png old mode 100755 new mode 100644 similarity index 100% rename from docs/images/slack_demo.png rename to docs/images/slack_example.png diff --git a/docs/images/staticmaptest.png b/docs/images/staticmaptest.png old mode 100755 new mode 100644 diff --git a/docs/images/telegram.png b/docs/images/telegram.png old mode 100755 new mode 100644 diff --git a/docs/index.rst b/docs/index.rst index f33910f7d..3d74e908d 100644 --- a/docs/index.rst +++ b/docs/index.rst @@ -3,87 +3,76 @@ Welcome to PokeAlarm's documentation! ===================================== +.. image:: images/logo.png + :align: center + +|discord| |nbsp| |patron| |nbsp| |repo| |nbsp| |issues| + PokeAlarm is a highly configurable application that filters and relays alerts about Pokemon Go to your favorite online service, allowing you to be first to know of any rare spawns or raids. -.. image:: images/PokeAlarm.png - :align: center - -.. image:: https://discordapp.com/api/guilds/215181169761714177/widget.png?style=shield :https://discord.gg/S2BKC7p: .. image:: https://img.shields.io/badge/Donate-Patron-orange.svg :https://www.patreon.com/bePatron?u=5193416: .. image:: https://img.shields.io/badge/python-2.7-blue.svg .. image:: https://img.shields.io/github/license/PokeAlarm/PokeAlarm.svg - -| `GitHub `_ || `Discord `_ || `GitHub Issues `_ | .. toctree:: :titlesonly: - :maxdepth: 2 - :caption: Contents: + :maxdepth: 1 + :caption: Initial Setup :glob: - contents/* + getting-started/installation + getting-started/faq .. toctree:: :titlesonly: - :maxdepth: 2 - :caption: Settings: - :glob: - - settings/* + :maxdepth: 1 + :caption: Basic Configuration -.. toctree:: - :titlesonly: - :maxdepth: 2 - :caption: Filters: - :glob: + configuration/server-settings + configuration/events/index + configuration/filters/index + configuration/alarms/index - filters/filters-overview - filters/monster-filters - filters/stop-filters - filters/gym-filters - filters/egg-filters - filters/raid-filters .. toctree:: :titlesonly: - :maxdepth: 2 - :caption: DTS: - :glob: - - dts/dynamic-text-substitution - dts/monster-dts - dts/stop-dts - dts/gym-dts - dts/egg-dts - dts/raid-dts + :maxdepth: 1 + :caption: Advanced Configuration -.. toctree:: - :titlesonly: - :maxdepth: 2 - :caption: Alarms: - :glob: + configuration/rules + configuration/managers + configuration/geofences - alarms/* .. toctree:: :titlesonly: - :maxdepth: 2 - :caption: Other: + :maxdepth: 1 + :caption: Guides :glob: - other/* + Getting Started + .. toctree:: :titlesonly: - :maxdepth: 2 - :caption: Documentation: + :maxdepth: 1 + :caption: Other :glob: - documentation/* - - -Indices and tables -================== - -* :ref:`genindex` -* :ref:`modindex` -* :ref:`search` + Webhook Standards + Patch Notes + Caching + Docker + Location Services + Contributing + + +.. |discord| image:: https://discordapp.com/api/guilds/215181169761714177/widget.png?style=shield + :target: https://discord.gg/S2BKC7p +.. |patron| image:: https://img.shields.io/badge/Donate-Patron-orange.svg + :target: https://www.patreon.com/pokealarm +.. |repo| image:: https://img.shields.io/badge/github-PokeAlarm-green.svg + :target: https://github.com/PokeAlarm/PokeAlarm +.. |issues| image:: https://img.shields.io/github/issues/PokeAlarm/PokeAlarm.svg + :target: https://github.com/PokeAlarm/PokeAlarm/issues +.. |nbsp| unicode:: 0xA0 + :trim: diff --git a/docs/miscellaneous/contributing.md b/docs/miscellaneous/contributing.md new file mode 100644 index 000000000..cb911c072 --- /dev/null +++ b/docs/miscellaneous/contributing.md @@ -0,0 +1,83 @@ +# Contributing + +## Overview + +This guide will show you how to submit issues, suggestions, feature requests, +and wiki corrections to the PokeAlarm team. + +* [Before You Begin](#before-you-begin) +* [Introduction](#introduction) +* [Submitting an Issue](#submitting-an-issue) +* [Submitting a Pull Request](#submitting-a-pull-request) +* [Submitting a change to the to the readthedocs](#submitting-a-change-to-the-readthedocs) + +## Before You Begin + +If you're trying to troubleshoot an issue that you're having that may not be a +issue needing to be fixed within PokeAlarm itself, try visiting the PokeAlarm +[#troubleshooting](https://discord.gg/S2BKC7p) channel on Discord. + +## Introduction + +There are two ways to submit information to the PokeAlarm Github, each with +its own template to be used. +* An [Issue](https://github.com/PokeAlarm/PokeAlarm/issues) can be submitted to + draw attention to a bug that needs to be fixed, to request a new feature, or + to give suggestions. +* If you know how to implement fix or a change that you'd like to see, you can + submit a [Pull Request](https://github.com/PokeAlarm/PokeAlarm/pulls). + +## Submitting an Issue + +1. From within the master branch of PokeAlarm, click on the Issues tab. +2. Click on the green button labeled "New issue". +3. Create a relevant title for your submission. +4. There are two templates preloaded into the Issue submission box - one for + bugs and user issues and the other for enhancements and suggestions. All + submissions do require the use of a template in order to be considered. + Make sure to address only one issue per submission. Copy the applicable + template and remove the one that you do not need. +5. Click on "Submit new issue" button when finished. + +## Submitting a Pull Request + +Pull Requests (PRs) are submitted through the `dev` branch of PokeAlarm to be +tested prior to being included in periodic patches merged to the Master branch. +All coding to be considered must meet PEP 8 standards for Python and should +be checked using [Flake8](http://flake8.pycqa.org/en/latest/index.html). + +Our development team utilizes Travis CI for automated testing. Travis CI is a +continuous integration service that checks for issues when PRs are first opened +and when commits are added to them. Feedback on PRs will typically be given +within 4 days from the date of the initial submission, excluding holidays. If +changes are requested, please comment on the PR when those changes have been +completed. + +Please keep your PR up to date so that we can pull it without conflicts. For +clean git histories, use `rebase` instead of merging. To do this: + +``` +git fetch origin +git rebase -i origin/dev +(comment out all the commits that aren't related to yours) +(handle any conflicts that arise from rebase) +git push +``` + +## Submitting a change to the readthedocs + +Submissions for changes to the readthedocs are to be made through Pull Requests +on the [PokeAlarm](https://github.com/PokeAlarm/PokeAlarm) repository, all the +readthedocs files are inside `docs` folder. + +The Wiki consists of files written using +[Markdown](https://help.github.com/articles/basic-writing-and-formatting-syntax/) +or [reStructuredText](http://docutils.sourceforge.net/docs/user/rst/quickref.html), +saved with the `.md`/`.rst` file extension. + +1. From within the Master branch of the PokeAlarm repo, click on the **Branch** + dropdown and choose `dev` from the menu. +2. Once the dev branch page loads, click the `New Pull Request` button. +3. Add a title for your request and include some information about your + submission in the textbox. +4. Upload a new or updated file and click `Create Pull Request`. diff --git a/docs/miscellaneous/docker.md b/docs/miscellaneous/docker.md new file mode 100644 index 000000000..ace6494ee --- /dev/null +++ b/docs/miscellaneous/docker.md @@ -0,0 +1,178 @@ +# Docker + +## Overview + +* [Prerequisites](#prerequisites) +* [Introduction](#introduction) +* [Setup](#setup) + * [Cloning the repo](#cloning-the-repo) + * [Configuring the alarm](#configuring-the-alarm) + * [Building the docker image](#building-the-docker-image) + * [Launching PokeAlarm](#launching-pokealarm) + * [Stopping PokeAlarm](#stopping-pokealarm) +* [Integrating with RocketMap](#integrating-with-rocketmap) + * [Docker network](#docker-network) + * [Using links](#using-links) + * [RocketMap running without docker](#rocketmap-running-without-docker) +* [Updating alarms](#updating-alarms) +* [Running multiple alarm containers](#running-multiple-alarm-containers) + +## Prerequisites + +This guide assumes: + +1) You have [Docker](https://docs.docker.com/) installed and running on your machine +2) You have [Git](https://git-scm.com/downloads) installed and running on your machine +3) You have read and understood the [Alarms](../configuration/alarms) wiki + +Please familiarize yourself with all of the above before proceeding. + +## Introduction + +By leveraging [Docker](https://docs.docker.com/), we can run PokeAlarm +instances without the need of installing Python, pip or other tools related to it. + +This means that you don't have to go through the hassle of managing python and +its multiple versions if you don't feel comfortable doing it, or for any +other reason. + +## Setup + +### Cloning the repo + +The first thing that you need to do is to clone the PokeAlarm repository in +the directory you'd like: + +``` +git clone https://github.com/PokeAlarm/PokeAlarm.git +``` + +### Configuring the alarm + +Now, enter the repository's directory and copy the file called +`alarms.json.default` to a file named `alarms.json`. Once that is done, +open `alarms.json` and edit it to your liking. Refer to the alarm +configuration documentation linked above as needed. + +It's also possible, but not required, to edit the configurations file. +This will allow you to set default values to be used for most of the alarm's +configuration, reducing the number of arguments when launching the instance. +To do so, make a copy of the `config.ini.example` file located inside the +config dir and rename it to `config.ini`. Now, just uncomment the desired +lines and provide the values. + +### Building the docker image + +Once alarms.json is edited, we've got to build the docker image that we +will use to launch our PokeAlarm container. To do so, execute the following +command from the repository's root directory: + +``` +docker build -t pokealarm . +``` + +This will create an image with the tag pokealarm, the dot indicates it should +use the contents from the directory it was executed. + +### Launching PokeAlarm + +With the docker image created, we can launch a PokeAlarm container. To do so +is as simple as executing: + +``` +docker run --name alarm -d pokealarm -k YOUR_GMAPS_API_KEY +``` + +This will launch a docker container named `alarm` using the image we just +created and tagged `pokealarm` + +### Stopping PokeAlarm + +Simply execute `docker stop alarm` and `docker rm alarm`. The removal of the +container is a necessary step because we want to reuse its name. + +## Integrating with RocketMap + +We will cover 3 scenarios for integration with your RocketMap. For the +first two scenarios, we will assume that given your interest in PokeAlarm with +docker, you are already running [RocketMap on docker containers](https://rocketmap.readthedocs.io/en/develop/advanced-install/docker.html). +For the last, we will assume you have it running locally with python. + +### Docker network + +If you have followed the RocketMap documentation for docker, you probably have +a docker network already setup. All you would need to do is to add the +network's name to you docker run command that was used before, like this: + +``` +docker run --name alarm --net=NETWORK_NAME -d pokealarm -k YOUR_GMAPS_API_KEY +``` + +Once that's done, you are able to reach your PokeAlarm container from any +other container in the same network, using the container's name as host +value. For example, you could add `-wh 'http://alarm:4000'` to your RocketMap +instances. + +### Using links + +If you are not running a docker network what you need to do is to link your +RocketMap container to your PokeAlarm container. To do so, launch you +PokeAlarm container as we've done before, but this time launch you RocketMap +container with the added flag `--link alarm` before the image's name on your +docker run command. With that link declared, you can add +`-wh 'http://alarm:4000'` to the end of the docker run command and it will +be able to find your PokeAlarm container. + +### RocketMap running without docker + +If you are not running RocketMap on docker, what we need to do for it to be +reachable is to bind a port on your host to the container's port. This is +easily done by adding the `-p` docker flag to your docker run command: + +``` +docker run --name alarm -d -p 4000:4000 pokealarm -k YOUR_GMAPS_API_KEY +``` + +Once you execute that, you will be able to reach your PokeAlarm container on +port `4000` by port `4000` on your localhost. This means you could add +`-wh 'http://127.0.0.1:4000'` to your `./runserver.py` command and it would be +able to post to the webhook. + +## Updating alarms + +If you want to update the `alarms.json` or `config.ini` files or wish to +create any other alarm configuration file, you are free to do so at any time. +However, you will need to rebuild your docker image afterwards, so that it can +copy the new/edited files into the image. + +## Running multiple alarm containers + +All you have to do is to execute the appropriate (described above) docker +run command multiple times, giving each container a new name. For example, +this is how we could do that using the docker network approach described before: + +``` +docker run --name commons --net=NETWORK_NAME -d pokealarm -k YOUR_GMAPS_API_KEY +docker run --name rares --net=NETWORK_NAME -d pokealarm -k YOUR_GMAPS_API_KEY -c rares.json +docker run --name ultra --net=NETWORK_NAME -d pokealarm -k YOUR_GMAPS_API_KEY -c ultra-rares.json +``` + +In the above block we are launching 3 containers of the `pokealarm` image in +a docker network, all of which could be accessed by other containers in the +network by their names. + +* The first is named `commons` and using the default configuration `alarms.json` +* The second is named `rares` and uses the configuration file named `rares.json` +* The third is named `ultra` and used the configuration file named `ultra-rares.json` + +If running RocketMap without docker, you would simply have to add different +port bindings to each container, like: + +``` +docker run --name commons -p 4000:4000 -d pokealarm -k YOUR_GMAPS_API_KEY +docker run --name rares -p 4001:4000 -d pokealarm -k YOUR_GMAPS_API_KEY -c rares.json +docker run --name ultra -p 4002:4000 -d pokealarm -k YOUR_GMAPS_API_KEY -c ultra-rares.json +``` + +Meaning that the containers would be reachable on `http://localhost:4000`, +`http://localhost:4001` and `http://localhost:4002` respectively. diff --git a/docs/miscellaneous/location-services.rst b/docs/miscellaneous/location-services.rst new file mode 100644 index 000000000..d20ec3563 --- /dev/null +++ b/docs/miscellaneous/location-services.rst @@ -0,0 +1,195 @@ +Location Services +===================================== + +.. contents:: Table of Contents + :depth: 2 + :local: + + +Prerequisites +------------------------------------- + +This guide assumes: + +1. You have a functional PokeAlarm installation +2. You have an available Google account (e.g., Gmail) +3. You have read and understood the available Command Line Arguments + in the :doc:`../configuration/server-settings` wiki + +Introduction +------------------------------------- + +Using a Google Maps API key in PokeAlarm is **optional**. It enable additional +features in PokeAlarm. + +In order to use a feature, you must have the corresponding API enabled in +Google API Manager, and have a generated Google Maps API key. Below are the +available features, and Google Map API to enable for that feature: + +============================================================== ============================= +PokeAlarm Feature Google Maps API to Enable +============================================================== ============================= +Set a location by name or address Google Maps Geocoding +Calculate walking/biking/driving distance from a set location Google Maps Distance Matrix +Show a Mini Map of pokemon, gyms, lures, eggs or raids Google Static Maps +============================================================== ============================= + +You will enable the APIs per the requirements of you own PokeAlarm +installation. In other words, if you only want static maps, enable just the +Google Static Maps API. If you want static maps and to set your location, +enable the Google Static Maps and Google Maps Geocoding APIs. + +In this guide, we will: + +1. Enable all 3 APIs and generate an API key that will allow PokeAlarm to + provide these features +2. Test the key to make sure it working correctly +3. Start **PokeAlarm** with your API key + +Enabling the Various Google Maps APIs and Obtaining a Key +------------------------------------- + +Now we're going create a new project, add our 3 APIs to it, then generate our +API key. + +1. Log into `Google API Manager `_. + +2. Click **Dashboard** at the left. If this is your first time visiting the + developers console, you should see "No APIs enabled" in the middle, like the + image below. + +.. image:: ../images/01-blank-dashboard.png + +3. At the top of the page, click the **Project** dropdown, then + select **Create project**. + +.. image:: ../images/02-create-project.png + +4. Name this project whatever you would like, e.g., "PokeAlarm". Click **Create**. + +.. image:: ../images/03-new-project-name.png + +5. You should now see your project name at the top. Click the blue + **+ENABLE API** button at the top middle, which will bring your to the Google + API Library. (You can also click **Library** at the left.) + +.. image:: ../images/04_project_created.png + +6. The Google API Library is where we will select our 3 APIs to enable. Let's + enable the **Google Maps Geocoding** API first. You can either type + **Google Maps Geocoding API** in the middle search bar, or click on it under + the "Google Maps API" section in the middle right. + +.. image:: ../images/05_library.png + +7. You should see **Google Maps Geocoding API**. Click the blue **ENABLE** + button at the top to enable the Google Maps Geocoding API. + +.. image:: ../images/06_enable_geocoding_api.png + +You should see this screen if enabled: + +.. image:: ../images/07_enabled_geocoding_api.png + +Click on **Dashboard** at the left. You should now see **Google Maps Geocoding +API** at the middle bottom. + +.. image:: ../images/08_dashboard_with_geocoding_enabled.png + +8. Click on **Library** at the left and repeat the same process of enabling + APIs for the **Google Maps Distance Matrix** and **Google Static Maps** APIs. + When you are finished, click **Dashboard** on the left and make sure that + you see all 3 APIs at the middle bottom. + +.. image:: ../images/09_dashboard_geocoding_distance_enabled.png + +9. Now that we have the 3 APIs enabled, let's generate our API key. Click on + **Credentials** at the left, then the blue **Create Credentials** in the + middle. + +.. image:: ../images/10_credentials.png + +10. Click **API key** in the middle. + +.. image:: ../images/11_credentials2.png + +11. Select **Browser key**. + +.. image:: ../images/12_select_browser_key.png + +12. If desired, name your key, or leave it as the default name. Click the + blue **Create** button. + +.. image:: ../images/13_key_name.png + +13. Your new API key will appear. Click the blue **OK** button. + +.. image:: ../images/14_here_is_your_key.png + +To find your key later, click on the blue **Credentials** button at the left. + +.. image:: ../images/15_find_your_key.png + +Testing Your API Key +------------------------------------- + +Now that you have your various APIs enabled and your API key created, let's +test to see if it is working correctly. + +Geocoding +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +To verify that your API key is working for geocoding and reverse geocoding, +visit the URLs below and replace ``YOUR_API_KEY`` with your Google Maps API key. + +**Geocoding** + +``https://maps.googleapis.com/maps/api/geocode/json?address=1600+Amphitheatre+Parkway,+Mountain+View,+CA&key=YOUR_API_KEY`` + +**Reverse Geocoding** + +``https://maps.googleapis.com/maps/api/geocode/json?latlng=40.714224,-73.961452&key=YOUR_API_KEY`` + + +Distance Matrix +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +To verify that your API key is working for travel distance and time, visit the +URLs below and replace ``YOUR_API_KEY`` with your Google Maps API key. + +``https://maps.googleapis.com/maps/api/distancematrix/json?units=imperial&origins=Washington,DC&destinations=New+York+City,NY&key=YOUR_API_KEY`` + + +Static Maps +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +To verify that your API key is working for Static Maps, visit the URL below +and replace ``YOUR_API_KEY`` with your Google Maps API key. + +``https://maps.googleapis.com/maps/api/staticmap?center=Brooklyn+Bridge,New+York,NY&zoom=13&size=600x300&maptype=roadmap&markers=color:blue%7Clabel:S%7C40.702147,-74.015794&markers=color:green%7Clabel:G%7C40.711614,-74.012318&markers=color:red%7Clabel:C%7C40.718217,-73.998284&key=YOUR_API_KEY`` + +If your key is valid, you should see this same static map image in your browser: + +.. image:: ../images/staticmaptest.png + +Starting PokeAlarm with a Google Maps API Key + +There are 2 methods to start **PokeAlarm** with your Google Maps API key: + +1. Run the command ``python start_pokealarm.py -k YOUR_GOOGLE_MAPS_API_KEY`` + +2. Add ``key:YOUR_GOOGLE_MAPS_API_KEY`` to ``config.ini`` located in the + ``config`` subfolder of your PokeAlarm installation, then run the command + ``python start_pokealarm.py``. + + +Google API Daily Limit +------------------------------------- + +Google allows up to 2,500 API requests per day for free. You may view your +API usage from the Dashboard of the `Google API Manager `_. +If you have exceeded the free daily quota of 2,500 hits, the mapping elements +in PokeAlarm may not function correctly. If you find that you are exceeding +the free daily 2,500 API calls, you may either switch to another valid Google +Maps API key for the day or sign up for a Google Maps API Premium plan. For +pricing information, visit the `Google Maps API Pricing and Plans page `_. diff --git a/docs/miscellaneous/object-caching.rst b/docs/miscellaneous/object-caching.rst new file mode 100644 index 000000000..8f071488c --- /dev/null +++ b/docs/miscellaneous/object-caching.rst @@ -0,0 +1,76 @@ +.. _object-caching: + +Object Caching +===================================== + +.. contents:: Table of Contents + :depth: 2 + :local: + +Prerequisites +------------------------------------- + +This guide assumes: + +1. You have a functional PokeAlarm installation +2. You have a basic understanding of how to manage binary files +3. You have read and understood the available Command Line Arguments in + the :doc:`../configuration/server-settings` wiki + +Introduction +------------------------------------- + +PokeAlarm uses `Cache` objects to store information that is not present on +runtime. The cached objects store information such as ``gym-info`` and other +dynamic objects sent into PokeAlarm via webhook. Cached data is used for +internal calculations as well as to provide details for :doc:`../configuration/events/index` +in :doc:`../configuration/alarms/index`. + +Caching Methods +------------------------------------- + +There are currently two methods available for object caching: + ++--------------------+------------------------------------------------------------------+ +| Caching Method | Description | ++--------------------+------------------------------------------------------------------+ +| `mem` | Caches data to memory only, information is lost between sessions | ++--------------------+------------------------------------------------------------------+ +| `file` | Caches data to binary files located in the `cache` folder | ++--------------------+------------------------------------------------------------------+ + +.. note:: If no cache-type is selected, ``mem`` will be chosen as the default. + +Memory Cache +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +When using the ``mem`` cache type, cached data is stored in memory only and is +cleared whenever PA exits. This will cause all :doc:`../configuration/events/index` +fields which require this data to display an ``unknown`` or ``null`` value until +the data is received by PA through webhooks. + +Binary File Cache +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +When using the ``file`` cache type, cached data is written to a binary file +located in the ``cache/`` directory. Each :doc:`../configuration/managers` has +a unique binary cache file stored as ``cache/.cache``. Cached +data is backed up to this binary file once per minute and immediately before +PA exits. + +Multiple Instances +------------------------------------- + +Using File caching with multiple instances can cause conflicts as cache files +are stored under ``.cache``. When using the ``file`` cache type +and multiple instances, take caution and ensure that all managers are assigned +an explicitly unique name. + +Clearing Cache +------------------------------------- + ++ **Memory Cache** is cleared whenever PA exits for any reason. ++ **File Caches** may be cleared by deleting the ``cache/.cache`` + file that corresponds to the manager you wish to clear the cache for. (To + clear all cached data, delete all files in the cache folder). PA will need + to be restarted once cache files are erased. diff --git a/docs/miscellaneous/patch-notes.md b/docs/miscellaneous/patch-notes.md new file mode 100644 index 000000000..3adc7191c --- /dev/null +++ b/docs/miscellaneous/patch-notes.md @@ -0,0 +1,502 @@ +# Patch Notes + +## Patch History + +* [Patch 3.7](#patch-3-7) +* [Patch 3.6](#patch-3-6) +* [Patch 3.5](#patch-3-5) +* [Patch 3.4](#patch-3-4) +* [Patch 3.3](#patch-3-3) +* [Patch 3.2](#patch-3-2) +* [Patch 3.1](#patch-3-1) + +--- + +## Patch 3.7 + +### Server Settings +* **File Cache Improvements** + * Decreased chance of corrupted cache if shutdown improperly + * Overwrites corrupted cache if detected, rather than throw error +* **Gmaps Clean Up** + * Automatic enabling for GMaps related DTS has been removed. Instead, + you will need to manually enable these DTS via server settings. See + the `config.ini.example` for usage. + * Fixed a bug where API Quotas caused timeouts + * `gmaps + * `` changed to `` + * `` changed to `` + * `` changed to `` + * `` changed to `` + * `` changed to `` + * `` changed to `` + * `` added + * `` added +* **Example Config Updated** + * `config.ini.example` has been cleaned up and updated for + readability. + +### Events + +* **Monsters** + * Costume DTS: `costume`, `costume_or_empty`, `costume_id`, + `costume_id_3` + * Move Type DTS: `quick_type_id`, `quick_type`, `quick_type_emoji`, + `charge_type_id`, `charge_type`, `charge_type_emoji` + * Moveset Quality DTS: `atk_grade` and `def_grade ` + * Catch Rate DTS: `base_catch`, `great_catch`, `ultra_catch` (and + precision variants) + * Added precision variants for `height` and `weight` DTS + * Added support for RM supported weather + +* **Eggs** + * Park DTS: `park` + * Sponsor DTS: `sponsor_id`, `sponsored` + +* **Raids** + * Form DTS: `form`, `form_or_empty`, `form_id`, `form_id_3` + * Park DTS: `park` + * Sponsor DTS: `sponsor_id`, `sponsored` + +### Filters + +* **All** + * Custom DTS improved - filter level now combines with defaults rather + than replace + * Bugfix: Geofences now always evaluate in order listed + +* **Monsters** + * `monsters_exclude` restriction - list of monsters to ignore, by id + or name + * `costume_ids` restriction - restrict by costume id + +* **Gyms** + * `gym_name_excludes` restriction - restrict gym_name to not contain + a matching regex + +* **Eggs** + * `gym_name_excludes` restriction - restrict gym_name to not contain + a regex match + * `sponsored` restriction - restrict sponsor_id to be zero or not + * `park_contains` restriction - restrict park to contain a regex match + +* **Raids** + * `monsters_exclude` restriction - list of monsters to ignore, by id + or name + * `gym_name_excludes` restriction - restrict gym_name to not contain + a matching regex + * `sponsored` restriction - restrict sponsor_id to be zero or not + * `park_contains` restriction - restrict park to contain a regex match + +### Alarms + +* **Telegram** + * `web_preview` parameter - enable/disable web previews for messages + +### Misc +* Minor fixes for `zh-hk` size translations. + + + +--- + +## Patch 3.6 + +This patch contains several breaking changes - make sure to read +carefully, back up your current configuration, and have some free time +before attempting to upgrade. + +### Rules (Optional) + +**New Feature** - The "Rules" feature will allow users to create rules +that dictate which filters trigger which alarms. Rules are loaded via +a file containing a json object, which has 5 sections similar to the +Filters file. Each section is a key-value pair of "rule names" to "rules". +Each rule can be described as a json object containing just two fields: +"filters" and "alarms". Each field is an array of strings corresponding to +the name of a filter or alarm from a manager. Rules cannot be loaded if +they do not match an existing filter or alarm. + +Rules are evaluated by checking the listed filters one by one (in order), +until a match is found. Once a match is found, PA will them notify each alarm +listed in the Rule. **Every** rule is always evaluated **every** time. + +Rules are an optional configuration setting and if no rules are set then PA +will check every filter in the order that they are listed in the filters file +and will target every alarm. + +Rules can be loaded via a rules file with `-r` and `--rules` via commandline +or `rules: rules.json` in config.ini. + +Each rules file must be configured key-value objects and contain at least one +or more of following rules sections: + +* `monsters` +* `stops` +* `gyms` +* `eggs` +* `raids` + +The inner section of each rule must be configured as a key-value object where +the key is the rule's name, and the value is the rule's setting. + +Each rule can be described as follows: + +```json +"example_rule" : { + "filters": [ "filter1", "filter2" ], + "alarms": [ "alarm1", "alarm2" ] +} +``` + +### Alarms + +**Breaking Changes** - To fully take advantage of the "Rules" feature, the +"Alarms" feature was changed to require a key-value json object instead of +a list. Alarms should now be a list of "name" -> "alarm settings". +The alarms.json.example has been updated to match this. + +#### Changed Alert Sections + +The Alert sections of alarms has been updated to match the event names: + +* `pokemon` -> `monsters` +* `pokestop` -> `stops` +* `gym` -> `gyms` +* `egg` -> `eggs` +* `raid` -> `raids` + +#### Alerts Converter + +A new tool has been added to `tools/convert_alarms_file.py`, this tool is +designed to convert Alerts files from 3.5 and prior to the 3.6 alert format. + +**Usage**: + +```bash +python convert_alarms_file.py /path/to/alarms.json +``` + +#### Telegram Changes + +**Breaking Changes** - Telegram alarms have been reworked to resolve multiple +issues and address Telegram API changes. + +* **Content Changes** - Telegram now uses markdown instead of html to reduce +conflicts caused by using invalid DTS fields. Existing alerts will have to be +reconfigured to make this change. + * The `venue` field does not support markdown or html coding + * `title` and `body` have been merged into `message` to better represent how + the Telegram API actually treats messages. The old behavior can be mimiced + by using the following example content: `*TITLE GOES HERE*\n BODY GOES HERE` +* **Field Changes** - The following fields have been changed: + * `bot_token`: Can now be set at an Alert level. DTS compatible. + * `chat_id`: Now DTS compatible. + * `stickers` -> `sticker`: Set to "true" for sticker with message, + set to "false" for no sticker. + * `sticker_notify`: Whether or not sticker messages causes a notification. + * `sticker_url`: Url to be used for the sticker. Must be .webp file. + * `location` -> `map`: true for map after message, false for no map. + * `map_notify`: Whether or not map messages causes a notification. + * `venue`: Sends the map and message in a single condensed format. + * `venue_notify`: Whether or not venue messages causes a notification. + * `max_retries`: Max attempts to send for each message. + (Telegram no longer uses the command line equivalent) + +### Filters + +* Listed filters now evaluate in the order listed in the file. +* The `"geofences" : [ "all" ]` shortcut now evaluates in the order that the +geofences are listed in the geofence file. +* `gym_name_contains` is now case-insensitive. + +#### Time Based Filtering + +Filters now support filtering based on event timing. This allows for +greater control over event alerts than what was previously supported via the +`timelimit` configuration option. + +* **New Filters** + * `min_time_left` - The minimum amount of time in seconds until the event + * `max_time_left` - The maximum amount of time in seconds until the event +* **Filter Events** + * **Monsters** - Filters based on time until monster despawns + * **Stops** - Filters based on time until the lure ends + * **Raids** - Filters based on time until the raid ends + * **Eggs** - Filters based on time until the egg hatches + +### Locale + +* Added multi-lingual support for the `Size` DTS & Filter setting. + +### Dynamic Text Substitutions + +* **Monsters & Raids** + * `size` - Changed to support locales + * `weather` - Outputs the current weather conditions in the alert + * `weather_id` - Outputs the current weather condition id + * `weather_or_empty` - Same as `weather` or an empty value + * `weather_emoji` - Outputs a unicode emoji for the current weather + * `boosted_weather` - Outputs the weather conditions if boosted + * `boosted_weather_id` - Outputs the boosted weather condition id + * `boosted_weather_or_empty` - `boosted_weather` or an empty value + * `boosted_weather_emoji` - Outputs an emoji for the boosted weather + * `boosted_or_empty` - Outputs the word **boosted** if Raid/Mon is boosted + * `type1` - Outputs the name of the Monster's Primary Type or `?` + * `type1_or_empty` - Same as `type1` or an empty value + * `type1_emoji` - Outputs an emoji for the Monster's Primary Type or Empty + * `type2` - Outputs the name of the Monster's Secondary Type or ? + * `type2_or_empty` - Same as `type2` or an empty value + * `type2_emoji` - Outputs an emoji for the Monster's Primary Type or Empty + * `types` - Outputs the Monster's Type formatted as "type1/type2" + * `types_emoji` - Outputs an emoji for the Monster's Type(s) or Empty + +* **Eggs** + * `weather` - Outputs the current weather conditions in the alert + * `weather_id` - Outputs the current weather condition id + * `weather_or_empty` - Same as `weather` or an empty value + * `weather_emoji` - Outputs an emoji for the current weather conditions + +### Server Settings + +* **Performance Fixes** - Users should now see improved performance + and less system resource usage overall. + +### Bug Fixes + +* **Twitter Alarms** + * Maximum length has been extended to 280 characters to match Twitter + standards and settings + * All URLs are now counted as 23 characters towards the overall + character limit detection. URLs that would cause the tweet to exceed + 280 characters will be dropped from the tweet. + * DTS is now evaluated before the length of the status update is + calculated. This corrects issues with improper Twitter Status Truncation + +--- + +## Patch 3.5 + +This patch contains several breaking changes - make sure to read +carefully, back up your current configuration, and have some free time +before attempting to upgrade. + +### Filters + +**Breaking Changes** - Filters have been completely reworked, with the +design focused on reducing managers and optimizing system resources. +Several filter parameter's have changed or been updated. For full +instructions on the new system, please see the new +[Filters](Filters-Overview) page in the wiki. + +Some highlights include: + + * Custom DTS - new feature to define filter specific DTS + +### Server Settings + +* Added `concurrency` setting - Determines the maximum number of +concurrent connections PA will accept. Lowering this may help lower-end +systems improve the response time for their machines. + +### Alarms + +* **All** + * Updated default image urls for `icon_url` and `avatar_url`. These + default urls have built in cache busting + +* **Discord** + * `webhook_url` field is now DTS compatible + +* **Twilio** + * Now supports using an array of numbers for the `to` field in Alert + configurations. + +### Dynamic Text Substitutions + +* **Pokemon** + * `enc_id` changed to `encounter_id` + * `level` changed to `mon_lvl` + * `pkmn` changed to `mon_name` + * `pkmn_id` changed to `mon_id` + * `pkmn_id_3` changed to `mon_id_3` + * `form_id_3_or_empty` replaced with `form_id_3` + * `tiny_rat` - Updated to use weight instead of size. + * `big_karp` - Updated to use weight instead of size. + +* **Pokestops** + * `id` changed to `stop_id` + +* **Raids** + * `team_leader` - Reports the name of the team leader of the team in + control of the gym. + * `pkmn` changed to `mon_name` + * `raid_level` changed to `raid_lvl` + * `time_left` changed to `raid_time_left` + * `24h_time` changed to `24h_raid_end` + * `gym_image_url` changed to `gym_image` + +* **Eggs** + * `raid_level` changed to `egg_lvl` + * `begin_time_left` changed to `hatch_time_left` + * `time_left` changed to `raid_time_left` + * `begin_12h_time` changed to `12h_hatch_time` + * `begin_24h_time` changed to `24h_hatch_time` + * `gym_image_url` changed to `gym_image` + +* **Gyms** + * `gym_image_url` changed to `gym_image` + * `slots_available` - displays the number of open guard slots + available in a gym + * `guard_count` - displays the number of guards assigned to a gym + +### Misc + +* Added Gen3 Move information +* Updated Kyogre and Groudon stats +* Added Portuguese language translations - `pt` + +--- + +## Patch 3.4 + +### Server Settings + +* Implemented caching for managers with `-ct` or `--cache_type`. Cache is used to handling remembering things like pokemon history and gym names. + * (default) `mem` - data persists only in memory. + * `file` - data is saved and loaded from a file. +* PA now gracefully exits on ctrl+c, finishing items in queue and logging the status of managers. + +### Dynamic Text Substitutions + +* **All** + + * `lat_5` and `lng_5` - Latitude and Longitude for the event, truncated to 5 decimal places. + * `address_eu` - same as ` `. + +* **Pokemon** + + * `form_or_empty` - Reports the form name of the pokemon if known, or an empty string if unknown. + * `pkmn_id_3` - pokemon id padded to 3 digits. + * `form_id_or_emtpy` - prints form_id padded to 3 digits if known, or and empty string if unknown. + +* **Raids** + * `form_or_empty` - Reports the form name of the pokemon if known, or an empty string if unknown. + * `team_name` - Reports the current team for a Raid gym if known, or 'unknown' if not. + * `team_id` - Reports the current team id for a Raid gym if known, or '?' if not. + * `min_cp` and `max_cp` - min and max potential cp for the raid boss if caught. + * `pkmn_id_3` - pokemon id padded to 3 digits. + * `form_id_or_emtpy` - prints form_id padded to 3 digits if known, or and empty string if unknown. + +### Tools + +* Webhook Tester + * Added `webhook_tester.py` for users to simulate sending events. + +--- + +## Patch 3.3 + +### Dynamic Text Substitution +* **Pokemon** + * (Re) added `'form'` DTS (and made it more robust). + +#### Server Settings +* **Reverse Location** + * Location services have been completely reworked to be more reliable. + * Location results now retrieve results set in whatever language is set for that manager. + * Location results now cache in memory - lowering overall API usage. + +--- + +## Patch 3.2 + +#### Filters +* **Pokemon** + * Pokemon can now be filtered by their form_id (example": `"form": [0, 1, 2]`). + * Pokemon can now be filtered by their gender (example": `"gender": ["male", "female"`). + * `'min_cp'` and `'max_cp'` are used to limit the CP of pokemon to alert. +* **Egg** + * "Egg" section is now added to the filters.json. + * `'enabled'` allows incoming raid alerts to be toggled on or off. + * `'min_level'` and `'max_level'` are used to limit the levels of incoming raids to alert on. +* **Raids** + * "Raids" section is now added to the filters.json. + * `'enabled'` allows raid alerts to be toggled on or off. + * `'default'` allows setting default settings for filters, and has the same options as pokemon filters do. + * Filters for pokemon raids can be set similar to the "pokemon" section, with the `"name": {}` scheme. + +#### Dynamic Text Substitution +* **General** + * Added `'applemaps'` to most alerts for AppleMaps link for iOS users. + * Time DTS now switch to ##h##m format when longer than one hour. +* **Pokemon** + * Added support for the following substitutions: `'cp', 'form', 'form_id', 'level'`. + * Added `'big_karp'` that displays 'big' on big magikarp and `'tiny_rat'` that displays 'tiny' on small rattata. +* **Egg** + * "Egg" alerts have the following substitutions: `'type', 'id', 'raid_level', 'raid_end', 'raid_being', 'lat', 'lng', 'gym_name', 'gym_description', 'gym_url'`. +* **Raid** + * "Raid" alerts have the following substitutions: `'type', 'id', 'pkmn_id', 'cp', 'quick_id', 'quick_damage', 'quick_dps', 'quick_duration', 'quick_energy', 'charge_id', 'charge_damage', 'charge_dps', 'charge_duration', 'charge_energy', 'raid_level', 'raid_end', 'raid_begin' 'lat', 'lng', 'gym_name', 'gym_description', 'gym_url'`. +* **Gyms** + * Added the following Gym substitutions: `'name', 'description', 'url'`. + * Added the following 'Gym Leader' substitutions: `'old_team_id', 'new_team_leader', 'old_team_leader'`. + +#### Alarms +* **Twitter** + * Twitter now automatically truncates to 140 characters - it will preserve links if added to the end. +* **Discord** + * Discord usernames now automatically truncates usernames to 32 characters. + * Added `'avatar_url'` to change the avatar of the post. + * Added `content` field that posts a message before the embed, allows for taging by user or roll. + * Added `'disable_embed'` that disables the discord embeds when set to `true`. + +--- + +## Patch 3.1 + +#### Filters +* **Multifilters** - Each filter can now be one of the following: + * `'True'` for all defaults, `'False'` for entirely disabled. + * A single filter in a json object (Ex: `{ "min_iv":"0", "max_iv" : "0" ... }`). + * Multiple filters inside an array: `[{"min_iv":"0", "max_iv":"25" }, {"min_iv":"75", "max_iv":"100"} ]`. + +* **Pokemon** + * All default filter parameters are now encapsulated in a single filter under the label `default`. + * `size` requires an array of valid sizes from the following: `['tiny', 'small', 'normal', 'large', 'big']`. + * `move_1` and `move_2` are now `quick_move` and `charge_move`. + * `size`, `quick_move`, `charge_move`, `moveset` filter parameters will accept any value when set to `null`. + +* **Pokestops** + * Now only two fields: `enabled` and `filters`. + * `filters` supports the Multifilter format with `min_dist` and `max_dist` fields. + +* **Gym** + * Now only three fields `enabled`, `ignore_neutral`, and `filters`. + * `filters` supports multifilters with the following fields: + * `from_team` - Array of valid previous team names. + * `to_team` - Array of valid current team names. + * `min_dist` and `max_dist` working as before. + +#### Dynamic Text Substitution +* `` added - the name of the first geofence in which the notification is in. +* `` now list either `'tiny'`, `'small'`, `'normal'`, `'large'`, or `'big'`. +* Quick moves now use the following: ``, ``, ``, ``, ``, ``. +* Charges moves now use the following: ``, ``, ``, ``, ``, ``. + +#### Alarms +* All Services + * `startup_list` is officially gone. +* Boxcar + * No longer supported. +* Discord + * `api_key` renamed to `webhook_url`. + * Will now retry if webhook was not received correctly. + * New optional alarm and alert level field: `map`. + * `enabled` - True of False to enabled/disabled map. + * Added other static map parameters. +* Slack + * `channel` parameter is now required at the Alarm level. + * Slack will no longer default to general if the correct channel cannot be found. + * Slack will still default to the Alarm level channel over the Alert level channel is not found (so everyone can still use ``!). +* Pushover + * No longer supported. diff --git a/docs/documentation/webhook-standard.md b/docs/miscellaneous/webhook-standard.md similarity index 71% rename from docs/documentation/webhook-standard.md rename to docs/miscellaneous/webhook-standard.md index b6de66669..6ab669845 100644 --- a/docs/documentation/webhook-standard.md +++ b/docs/miscellaneous/webhook-standard.md @@ -7,9 +7,9 @@ * [Gyms](#gyms) * [Gym-details Example](#gym-details-example) * [Egg example](#egg-example) -* [Raid Example](#raid-example) +* [Raid example](#raid-example) -## ***Pokemon*** +## Pokemon Pokemon standard now includes moveset and IVs as of commit [oc1b4](https://github.com/RocketMap/PokeAlarm/commit/0c1b4cce80e0ceb3cc6dbb2d802204af4dd3ce60). @@ -24,22 +24,22 @@ Pokemon standard now includes moveset and IVs as of commit [oc1b4](https://githu "pokemon_id": 201, "pokemon_level": 30, "player_level": 31, - "latitude": 37.7876146, - "longitude": -122.390624, + "latitude": 37.7876146, + "longitude": -122.390624, "disappear_time": 1506897031, "last_modified_time": 1475033386661, "time_until_hidden_ms": 5000, - "seconds_until_despawn": 1754, - "spawn_start": 2153, - "spawn_end": 3264, - "verified": false, - "cp_multiplier": 0.7317000031471252, - "form": 15, + "seconds_until_despawn": 1754, + "spawn_start": 2153, + "spawn_end": 3264, + "verified": false, + "cp_multiplier": 0.7317000031471252, + "form": 15, "cp": 768, "individual_attack": 10, "individual_defense": 1, "individual_stamina": 9, - "move_1": 281, + "move_1": 281, "move_2": 133, "height": 0.5694651007652283, "weight": 5.733094215393066, @@ -58,8 +58,8 @@ Pokemon standard now includes moveset and IVs as of commit [oc1b4](https://githu "message": { "pokestop_id": 0, "enabled": "True", - "latitude": 37.7876146, - "longitude": -122.390624, + "latitude": 37.7876146, + "longitude": -122.390624, "last_modified_time": 1572241600, "lure_expiration": 1572241600, "active_fort_modifier": 0 @@ -75,37 +75,37 @@ Pokemon standard now includes moveset and IVs as of commit [oc1b4](https://githu { "type": "gyms", "message": { - "raid_active_until": 0, - "gym_id": 0, - "team_id": 0, - "guard_pokemon_id": 0, - "slots_available": 0, - "guard_pokemon_id": 99, - "lowest_pokemon_motivation": 0.8795773983001709, - "total_cp": 11099, - "occupied_since": 1506886787, - "enabled": "True", - "latitude": 37.7876146, - "longitude": -122.390624, - "last_modified": 1572241600 + "raid_active_until": 0, + "gym_id": 0, + "team_id": 0, + "guard_pokemon_id": 0, + "slots_available": 0, + "guard_pokemon_id": 99, + "lowest_pokemon_motivation": 0.8795773983001709, + "total_cp": 11099, + "occupied_since": 1506886787, + "enabled": "True", + "latitude": 37.7876146, + "longitude": -122.390624, + "last_modified": 1572241600 } } ``` -#### Gym-details Example: +#### Gym-details example: ```json { "type": "gym_details", "message": { - "id": "OWNmOTFmMmM0YTY3NGQwYjg0Y2I1N2JlZjU4OWRkMTYuMTY=", - "url": "http://lh3.ggpht.com/yBqXtFfq3nOlZmLc7DbgSIcXcyfvsWfY3VQs_gBziPwjUx7xOfgvucz6uxP_Ri-ianoWFt5mgJ7_zpsa7VNK", - "name": "Graduate School of Public Health Sculpture", - "description": "Sculpture on the exterior of the Graduate School of Public Health building.", - "team": 1, - "latitude": 37.7876146, - "longitude": -122.390624, - "pokemon": [{ + "id": "OWNmOTFmMmM0YTY3NGQwYjg0Y2I1N2JlZjU4OWRkMTYuMTY=", + "url": "http://lh3.ggpht.com/yBqXtFfq3nOlZmLc7DbgSIcXcyfvsWfY3VQs_gBziPwjUx7xOfgvucz6uxP_Ri-ianoWFt5mgJ7_zpsa7VNK", + "name": "Graduate School of Public Health Sculpture", + "description": "Sculpture on the exterior of the Graduate School of Public Health building.", + "team": 1, + "latitude": 37.7876146, + "longitude": -122.390624, + "pokemon": [{ "num_upgrades": 0, "move_1": 234, "move_2": 99, @@ -172,8 +172,8 @@ Pokemon standard now includes moveset and IVs as of commit [oc1b4](https://githu ## Egg example -Take note that the type for egg is `raid` because it is collected from the -same webhook event from RocketMap as raids are. +Take note that the type for egg is `raid` because it is collected from the same +webhook event from RocketMap as raids are. ```json { @@ -181,15 +181,15 @@ same webhook event from RocketMap as raids are. "message": { "gym_id": "gym_id", "start": 1499244052, - "end": 1499246052 , + "end": 1499246052, "level": 5, - "latitude": 37.7876146, - "longitude": -122.390624 + "latitude": 37.7876146, + "longitude": -122.390624 } } ``` -## Raid Example +## Raid example ```json { @@ -201,10 +201,10 @@ same webhook event from RocketMap as raids are. "move_1": 123, "move_2": 123, "start": 1499244052, - "end": 1499246052 , + "end": 1499246052, "level": 5, - "latitude": 37.7876146, - "longitude": -122.390624 + "latitude": 37.7876146, + "longitude": -122.390624 } } ``` diff --git a/docs/other/google-maps-api-key.md b/docs/other/google-maps-api-key.md deleted file mode 100644 index 117dd60c1..000000000 --- a/docs/other/google-maps-api-key.md +++ /dev/null @@ -1,191 +0,0 @@ -# Google Maps API Keys - -## Overview - -* [Prerequisites](#prerequisites) -* [Introduction](#introduction) -* [Enabling the Various Google Maps APIs and Obtaining a Key](#enabling-the-various-google-maps-apis-and-obtaining-a-key) -* [Testing Your API Key](#testing-your-api-key) - * [Geocoding](#geocoding) - * [Distance Matrix](#distance-matrix) - * [Static Maps](#static-maps) -* [Starting PokeAlarm with a Google Maps API Key](#starting-pokealarm-with-a-google-maps-api-key) -* [Google API Daily Limit](#google-api-daily-limit) - -## Prerequisites - -This guide assumes: - -1. You have a functional PokeAlarm installation -2. You have an available Google account (e.g., Gmail) -3. You have read and understood the available Command Line Arguments in the [Server Settings](server-settings) wiki - -## Introduction - -Using a Google Maps API key in PokeAlarm is **optional**. -It enable additional features in PokeAlarm. - -In order to use a feature, you must have the corresponding API enabled in -Google API Manager, and have a generated Google Maps API key. - -Below are the available features, and Google Map API to enable for that feature: - -| PokeAlarm Feature | Google Maps API to Enable | -|:--------------------------------------------------------------|:-----------------------------| -| Set a location by name or address | Google Maps Geocoding | -| Calculate walking/biking/driving distance from a set location | Google Maps Distance Matrix | -| Show a Mini Map of pokemon, gyms, lures, eggs or raids | Google Static Maps | - -You will enable the APIs per the requirements of you own PokeAlarm installation. -In other words, if you only want static maps, enable just the Google Static -Maps API. If you want static maps and to set your location, enable the Google -Static Maps and Google Maps Geocoding APIs. - -In this guide, we will: - -1. Enable all 3 APIs and generate an API key that will allow PokeAlarm to -provide these features -2. Test the key to make sure it working correctly -3. Start **PokeAlarm** with your API key - -## Enabling the Various Google Maps APIs and Obtaining a Key -Now we're going create a new project, add our 3 APIs to it, then generate our -API key. - -1. Log into [Google API Manager](https://console.developers.google.com/). - -2. Click **Dashboard** at the left. If this is your first time visiting the -developers console, you should see "No APIs enabled" in the middle, like the -image below. - -![](../images/01-blank-dashboard.png) - -3. At the top of the page, click the **Project** dropdown, then select -**Create project**. - -![](../images/02-create-project.png) - -4. Name this project whatever you would like, e.g., "PokeAlarm". Click **Create**. - -![](../images/03-new-project-name.png) - -5. You should now see your project name at the top. Click the blue -**+ENABLE API** button at the top middle, which will bring your to the -Google API Library. (You can also click **Library** at the left.) - -![](../images/04_project_created.png) - -6. The Google API Library is where we will select our 3 APIs to enable. -Let's enable the **Google Maps Geocoding** API first. You can either -type **Google Maps Geocoding API** in the middle search bar, or click -on it under the "Google Maps API" section in the middle right. - -![](../images/05_library.png) - -7. You should see **Google Maps Geocoding API**. Click the blue -**ENABLE** button at the top to enable the Google Maps Geocoding API. - -![](../images/06_enable_geocoding_api.png) - -You should see this screen if enabled: - -![](../images/07_enabled_geocoding_api.png) - -Click on **Dashboard** at the left. You should now see **Google Maps -Geocoding API** at the middle bottom. - -![](../images/08_dashboard_with_geocoding_api_enabled.png) - -8. Click on **Library** at the left and repeat the same process of enabling -APIs for the **Google Maps Distance Matrix** and **Google Static Maps** APIs. -When you are finished, click **Dashboard** on the left and make sure that you -see all 3 APIs at the middle bottom. - -![](../images/09_dashboard_with_geocoding_distance_staticmaps_api_enabled.png) - -9. Now that we have the 3 APIs enabled, let's generate our API key. Click -on **Credentials** at the left, then the blue **Create Credentials** in -the middle. - -![](../images/10_credentials.png) - -10. Click **API key** in the middle. - -![](../images/11_credentials2.png) - -11. Select **Browser key**. - -![](../images/12_select_browser_key.png) - -12. If desired, name your key, or leave it as the default name. Click the -blue **Create** button. - -![](../images/13_key_name.png) - -13. Your new API key will appear. Click the blue **OK** button. - -![](../images/14_here_is_your_key.png) - -To find your key later, click on the blue **Credentials** button at the left. - -![](../images/15_find_your_key.png) - -## Testing Your API Key - -Now that you have your various APIs enabled and your API key created, -let's test to see if it is working correctly. - -### Geocoding - -To verify that your API key is working for geocoding and reverse geocoding, -visit the URLs below and replace `YOUR_API_KEY` with your Google Maps API key. - -**Geocoding** -``` -https://maps.googleapis.com/maps/api/geocode/json?address=1600+Amphitheatre+Parkway,+Mountain+View,+CA&key=YOUR_API_KEY -``` -**Reverse Geocoding** -``` -https://maps.googleapis.com/maps/api/geocode/json?latlng=40.714224,-73.961452&key=YOUR_API_KEY -``` - -### Distance Matrix - -To verify that your API key is working for travel distance and time, visit -the URLs below and replace `YOUR_API_KEY` with your Google Maps API key. - -``` -https://maps.googleapis.com/maps/api/distancematrix/json?units=imperial&origins=Washington,DC&destinations=New+York+City,NY&key=YOUR_API_KEY -``` - -### Static Maps - -To verify that your API key is working for Static Maps, visit the URL below -and replace `YOUR_API_KEY` with your Google Maps API key. -``` -https://maps.googleapis.com/maps/api/staticmap?center=Brooklyn+Bridge,New+York,NY&zoom=13&size=600x300&maptype=roadmap&markers=color:blue%7Clabel:S%7C40.702147,-74.015794&markers=color:green%7Clabel:G%7C40.711614,-74.012318&markers=color:red%7Clabel:C%7C40.718217,-73.998284&key=YOUR_API_KEY -``` -If your key is valid, you should see this same static map image in your browser: - -![](../images/staticmaptest.png) - -## Starting PokeAlarm with a Google Maps API Key - -There are 2 methods to start **PokeAlarm** with your Google Maps API key: - -1. Run the command `python start_pokealarm.py -k YOUR_GOOGLE_MAPS_API_KEY` - -2. Add `key:YOUR_GOOGLE_MAPS_API_KEY` to `config.ini` located in the `config` -subfolder of your PokeAlarm installation, then run the command -`python start_pokealarm.py`. - -## Google API Daily Limit - -Google allows up to 2,500 API requests per day for free. You may view your -API usage from the Dashboard of the -[Google API Manager](https://console.developers.google.com/). If you have -exceeded the free daily quota of 2,500 hits, the mapping elements in PokeAlarm -may not function correctly. If you find that you are exceeding the free daily -2,500 API calls, you may either switch to another valid Google Maps API key -for the day or sign up for a Google Maps API Premium plan. For pricing -information, visit the [Google Maps API Pricing and Plans page](https://developers.google.com/maps/pricing-and-plans/#details). diff --git a/docs/other/object-caching.md b/docs/other/object-caching.md deleted file mode 100644 index 5e3a760a6..000000000 --- a/docs/other/object-caching.md +++ /dev/null @@ -1,67 +0,0 @@ -# Object Caching - -## Overview - -* [Prerequisites](#prerequisites) -* [Introduction](#introduction) -* [Caching Methods](#caching-methods) - * [Memory Cache](#memory-cache) - * [Binary File Cache](#binary-file-cache) - * [Multiple Instances](#multiple-instances) -* [Clearing Cache](#clearing-cache) - -## Prerequisites - -This guide assumes: - -1. You have a functional PokeAlarm installation -2. You have a basic understanding of how to manage binary files -3. You have read and understood the available Command Line Arguments in the -[Server Settings](server-settings) Wiki - -## Introduction - -PokeAlarm uses `Cache` objects to store information that is not present on -runtime. The cached objects store information such as `gym-info` and other -dynamic objects sent into PokeAlarm via webhook. Cached data is used for -internal calculations as well as to provide details for [Dynamic Text Substitution](dynamic-text-substitution) in [Alarms](alarms). - -## Caching Methods - -There are currently two methods available for object caching: - -| Caching Method | Description | -|:------------------------|:-----------------------------------------------------------------| -| `mem` | Caches data to memory only, information is lost between sessions | -| `file` | Caches data to binary files located in the `cache` folder | - -_Note: If no cache-type is selected, `mem` will be chosen as the default._ - -## Memory Cache - -When using the `mem` cache type, cached data is stored in memory only and is -cleared whenever PA exits. This will cause all [DTS](dynamic-text-substitution) -fields which require this data to display an `unknown` or `null` value until -the data is received by PA through webhooks. - -## Binary File Cache - -When using the `file` cache type, cached data is written to a binary file -located in the `cache/` directory. Each [Manager](managers) has a unique -binary cache file stored as `cache/.cache`. Cached data is -backed up to this binary file once per minute and immediately before PA exits. - -# Multiple Instances - -Using File caching with multiple instances can cause conflicts as cache files -are stored under `.cache`. When using the `file` cache type and -multiple instances, take caution and ensure that all managers are assigned an -explicitly unique name. - -### Clearing Cache - -* **Memory Cache** is cleared whenever PA exits for any reason. -* **File Caches** may be cleared by deleting the `cache/.cache` -file that corresponds to the manager you wish to clear the cache for. (To clear - all cached data, delete all files in the cache folder). PA will need to be - restarted once cache files are erased. diff --git a/docs/other/v3-guide.md b/docs/other/v3-guide.md deleted file mode 100644 index 0158ecbb3..000000000 --- a/docs/other/v3-guide.md +++ /dev/null @@ -1,422 +0,0 @@ -# Remedy's v3 Guide - -Updated: 28 August 2017 - -## Purpose - -* This document is intended to quickly provide PokeAlarm users with info to -get started. It is not intended to replace the full wiki. - -## Overview - -* [Before you begin](#before-you-begin) -* [Notes](#notes) -* [Introduction](#introduction) - * [Changes to JSON files](#changes-to-json-files) - * [Config file: `filters.json`](#config-file-filtersjson) - * [Gyms](#gyms) - * [Changes in move filtering](#changes-in-move-filtering) - * [Filtering on a single `quick_move`](#filtering-on-a-single-quick_move) - * [Filtering on more than one `charge_move`](#filtering-on-multiple-charge_move-moves) - * [NEW: filtering on `moveset`](#new-filtering-on-moveset) - * [NEW: filtering on `size`](#new-filtering-on-size) - * [New: Optional ignoring of pokemon with missing IVs or moves](#new-optional-ignoring-of-pokemon-with-missing-ivs-or-moves) - * [Config file: `geofence.txt` (optional)](#config-file-geofencetxt-optional) - * [Config file: `alarms.json`](#config-file-alarmsjson) - * [New and updated Dynamic Text Substitutions](#new-and-updated-dynamic-text-substitutions) -* [Upgrading from PokeAlarm Version 2 to Version 3](#upgrading-from-pokealarm-version-2-to-version-31) -* [Running PokeAlarm v3](#running-pokealarm-v3) - * [Optional Arguments for `start_pokealarm.py`](#optional-arguments-for-start_pokealarmpy) - * [Running multiple alarms, filters, etc., in a single `start_pokealarm.py` instance from the command line](#running-multiple-alarms-filters-etc-in-a-single-start_pokealarmpy-instance-from-the-command-line) - * [Running one Manager from the command line](#running-one-manager-from-the-command-line) - * [Running two Managers from the command line](#running-two-managers-from-the-command-line) - * [Special case: using one `filters.json`, `geofence.txt`, `alarms.json`, etc., for all Managers in the command line](#special-case-using-one-filtersjson-geofencetxt-alarmsjson-etc-for-all-managers-from-the-command-line) - * [Using `config.ini` to simplify Manager... management](#using-configini-to-simplify-manager-management) - * [Naming your Managers](#naming-your-managers) - * [Running Multiple Instances of the PokeAlarm Server](#running-multiple-instances-of-the-pokealarm-server) -* [Final notes](#final-notes) - -## Before you begin - -* Deadly has to eat! Get the word out about PokeAlarm and send a [Paypal tip](https://www.paypal.com/cgi-bin/webscr?cmd=_donations&business=5W9ZTLMS5NB28&lc=US&item_name=PokeAlarm¤cy_code=USD) or [Patreon pledge](https://www.patreon.com/pokealarm) his way for a job well done and to keep the features coming. -* Version 3.1 is now in the master branch. Read the patch notes if you are upgrading from version 3. -* Version 2 is now in a separate branch, [v2](https://github.com/kvangent/PokeAlarm/tree/v2) -* If you have experience with PokeAlarm v2, use the .example files in v3 root to quickly get started -* Features are constantly being added. Always visit the #announcements discord channel for udpates -* Contact us in the [#troubleshooting discord channel](https://discordapp.com/channels/215181169761714177/218822834225545216) or open a ticket on our [github page](https://github.com/RocketMap/PokeAlarm/issues) - -## Notes - -* If RocketMap is not configured to send moves or IVs for particular pokemon, e.g., `-eblk`, then you will get a `unkn` message for stats if you do not set that particular pokemon to `"false"` in `filters.json`. This behavior is intentional in PokeAlarm v3. This is to ensure that you get the snorlax notification even if RocketMap sends the webhook without IVs or moves. To bypass, use `"ignore_missing":"True"` in your `filters.json` either globally or individually for each Pokemon. -* RocketMap webhooks have been recently undergoing changes. You may see errors in the PokeAlarm v3 log such as `[ MainProcess][WebhookStr][ ERROR] Encountered error while processing webhook (TypeError: int() argument must be a string or a number, not 'NoneType') -`. This is because RocketMap is sending new webhook information that PokeAlarm hasn't yet incorporated. Your PokeAlarm setup will still function normally. -* Remember - you only need to edit the JSON, `geofence.txt`, and `config.ini` files. Other modifications to the code are not supported!!! -* PyCharm is a great IDE to manage your JSON and config files. The EDU edition is free: https://www.jetbrains.com/pycharm-edu . This will will help you avoid those pesky formatting errors. -* Alternatively, use an online JSON editor like http://www.jsoneditoronline.org which will yell at you if the json is incorrectly formatted - -## Introduction -PokeAlarm v3 takes advantage of multiprocessing to simplify running multiple configurations. To further simplify configuration, the `alarms.json` as you know it in v2 has been split into `alarms.json` and `filters.json`. Geofencing is still handled by `geofence.txt`, which now allows for multiple geofences in the same file. You can add multiple config files in a list in `config.ini`. - -Here's a visual on the PokeAlarm v3 workflow: - -![](../images/v3_overview.png) - -* The PokeAlarm Server is initiated by `start_pokealarm.py` -* The number of managers is set etiher in the command line or `config.ini` -* Each Manager is assigned a `filters.json`, `geofence.txt` (optional), and `alarms.json` -* `filters.json` contains the pokemon, gym, and pokestop configs -* `geofences.txt` is optional, and contains coordinates for one or more areas to limit notifications -* `alarms.json` contains one or more services, e.g., twitter, slack, discord, to send the custom notifications - -## Changes to JSON files - -The `alarms.json` in PokeAlarm v2 contained four sections - alarms, gyms, pokemon, pokestops. - -In PokeAlarm v3, the configuration has been split between three files - filters, geofences, and alarms: - -| config file | description | -|:-----------:|:----------| -`filters.json` | enables pokemon, gym, and pokestop settings -`geofence.txt` | optional, handles geofence(s) -`alarms.json` | configures alarms only - -See the .example files in your PokeAlarm root directory for sample setups. - -### Config file: `filters.json` - -* This is a **required** file -* The `pokemon:` section in the PokeAlarm v2 has been moved to its own file, `filters.json`. - -#### Gyms - -``` -"gyms":{ - "enabled":"False", - "ignore_neutral":"False", - "filters":[ - { - "from_team":["Valor", "Instinct", "Mystic"], "to_team":["Valor", "Instinct", "Mystic"], - "min_dist":"0", "max_dist":"inf" - } - ] -}, -``` - -* A new key, `ignore_neutral`, has been added. This is to prevent those "It is now controlled by Neutral" gym messages. -* The keys for each team have been simplified. Setting a team value to `True` will filter for any gym action for that particular team. - -### Changes in move filtering - -#### Filtering on a single `quick_move` -The following example will filter for Dragonites with Dragon Breath. In Version 3, you must wrap the move in brackets `[ ]`. - -`"Dragonite": { "quick_move": [ "Dragon Breath" ] }` - -#### Filtering on multiple `charge_move` moves - -The following example will filter for Dragonites with either Dragon Claw or Hyper Beam. In Version 3, you must wrap the moves in brackets `[ ]`, and separate each move with a comma `,`. - -`"Dragonite": { "charge_move": [ "Dragon Claw", "Hyper Beam" ] }` - -#### NEW: filtering on `moveset` - -New to PokeAlarm Version 3 is the ability to filter on a moveset, that is, a specific combination of `quick_move` AND `charge_move`. This is useful for looking for attacking or defending Pokemon. - -The following example will filter for Dewgong with Frost Breath and Blizzard: - -`"Dewgong": { "moveset": [ "Frost Breath/Blizzard" ] }` - -The following example will filter for Dragonites with either -* Dragon Breath AND Dragon Claw - -OR - -* Steel Wing AND Dragon Pulse - -`"Dragonite": { "moveset": [ "Dragon Breath/Dragon Claw", "Steel Wing/Dragon Pulse" ] }` - -### NEW: filtering on `size` - -Want those tiny Rattata and big Magikarp badges? Here's how to add them to your `filters.json`. (Remember, you'll need two different JSON files if you're looking for either high IV or XL karp.) - -```json -"Rattata":{"size":['tiny'] }, -"Magikarp":{ "size":['big'] }, -``` - -If you'd like to filter on other sizes, select from the following: - -**PokeAlarm Version 3** - -| Filter | Description, Version 3 | -|:------:|:------------| -| `size` | `"XS"`,`"Small"`, `"Normal"`, `"Large"`, `"XL"` - -**PokeAlarm Version 3.1** renames `XS` and `XL` to `tiny` and `big`, to better match in-game text. - -| Filter | Description, Version 3.1 | -|:------:|:------------| -| `size` |`"tiny"`,`"small"`, `"normal"`, `"large"`, `"big"` - -#### New: Optional ignoring of pokemon with missing IVs or moves -If RocketMap is not configured to send moves or IVs for particular pokemon, e.g., `-eblk`, then you will get a `unknown` message for notifications if you do not set that particular pokemon to `"false"` in `filters.json`. This behavior is intentional in PokeAlarm v3. This is to ensure that you get the Snorlax notification even if RocketMap sends the webhook without IVs or moves. - -To bypass, use `"ignore_missing":"True"` in your `filters.json` either globally or individually for each Pokemon. - -`"Pidgey": { "ignore_missing":"True" }` - -It is highly recommended to disable this option for the rares - snorax, dragonite, lapras - since you'll want to be notified of those, regardless of stats. - -### Config file: `geofence.txt` (optional) - -* This is an *optional* file -* In version 3, you are permitted to have multiple geofences in a single file. In order to distinguish between different geofences, each set of coordinates in your geofence.txt file must contain a header with a set of brackets, like so: - -``` -[Central Park] -40.801206,-73.958520 -40.767827,-73.982835 -40.763798,-73.972808 -40.797343,-73.948385 - -[Other Place] -61.801206,-100.958520 -61.767827,-100.982835 -61.763798,-100.972808 -61.797343,-100.948385 - -``` - -PokeAlarm v3 will fail otherwise. - -### Config file: `alarms.json` -* This is a **required** file -* the `alarms:[]` section in PokeAlarm v2 configuration file has been moved into its own file, `alarms.json` -* The `alarms:` key has been removed from the file. Otherwise, everything is the same from v2 -* You may copy your alarm configuration from v2 into v3 -* The existing documentation for Alarm services should still be applicable to PokeAlarm v3. Some keys have changed in v3.1 - -#### New Filters - - -#### New and updated Dynamic Text Substitutions -Version 3 adds new DTS options and makes slight changes to some existing ones. - -| Version 2 | Version 3 | Version 3.1 | Notes | -|:---------:|:----------:|:------------:|:------| -| | | `` | Name of the geofence where the alerted Pokemon originated -| `` | ``| No Change | Pokemon ID. Primarily affects Pokemon image URL in notification -| `` | `` | `` | Added underscore to match code styling of project -| `` | `` | `` | Added underscore to match code styling of project -| | `` | No Change | New option -| | `` | No Change | | New option. When coupled with ``, useful for filtering on a specific IV range of pokemon. Or useful for finding 0% IV pokemon? :) -| | `` | No Change | IV, rounded to 0 decimals (great for Twitter) -| | `` | No Change | IV, rounded to 2 decimals -| | |`` -| | `` | `` | -| | `` |`` | -| | `` | `` -| | `` | `` -| | |`` -| | `` | `` -| | `` | `` -| | `` | `` -| | `` | `` -| | `` | No Change -| | `` | No Change -| | ``| No Change -| | `` | No Change -Want more options? [Buy Deadly a beer](https://www.paypal.com/cgi-bin/webscr?cmd=_donations&business=5W9ZTLMS5NB28&lc=US&item_name=PokeAlarm¤cy_code=USD) and maybe he'll come around. =P - -## Upgrading from PokeAlarm Version 2 to Version 3.1 - -Run the following commands: -``` -git pull -pip install -r requirements.txt -``` - -If you run into significant issues during the pull, back up your JSON and config.ini files, then clone Pokelarm again. - -Remember that there are significant changes to the JSON files, so be sure that you've completed the prior steps before running PokeAlarm version 3. - - -## Running PokeAlarm v3 -PokeAlarm v3 is now started by running `start_pokealarm.py`. - -### Optional Arguments for `start_pokealarm.py` -Type `start_pokealarm.py -h` to view a list of arguments. Arguments that start with `--`, e.g., `--key`, can also be set in `config.ini`, located in the `config` folder of your PokeAlarm root directory. Command line values will override values stored in `config.ini`. - -The list of arguments are below: - - -| Argument | Default | Description -|:------------|:-------:|:-----------| -| `-h`, `--help` | | show this help message and exit -| `-cf`, `--config`| `config/config.ini` | Specify configuration file other than config.ini -| `-d`, `--debug` | | Debug Mode -| `-H HOST`, `--host HOST` | `127.0.0.1` | Set web server listening host -| `-P PORT`, `--port PORT` | `4000` | Set web server listening port -| `-m MANAGER_COUNT`, `--manager_count MANAGER_COUNT` | `1` | Number of Manager processes to start -| `-M MANAGER_NAME`, `--manager_name MANAGER_NAME` | | Names of Manager processes to start -| `-k KEY`, `--key KEY` | | Specify a Google API Key to use. -| `-f FILTERS`, `--filters FILTERS` | `filters.json` | Filters configuration file -| `-a ALARMS`, `--alarms ALARMS` | `alarms.json` | Alarms configuration file -| `-gf GEOFENCES`, `--geofences GEOFENCES` | | file containing list of coordinates to define a geofence -| `-l LOCATION`, `--location LOCATION` | | Location, can be an address or coordinates -| `-L {de,en,es,fr,it,pt,zh_hk}`, `--locale {de,en,es,fr,it,pt,zh_hk}` | |Locale for Pokemon and Move names: default en, check locale folder for more options -| `-u {metric,imperial}`, `--units {metric,imperial}` | | Specify either metric or imperial units to use for distance measurements. -| `-tl TIMELIMIT`, `--timelimit TIMELIMIT` | | Minimum number of seconds remaining on a pokemon to send a notify -| `-tz TIMEZONE`, `--timezone TIMEZONE` | | Timezone used for notifications. Ex: `America/Los_Angeles`. Visit [this article](https://en.wikipedia.org/wiki/List_of_tz_database_time_zones) for a list of valid timezones. - -Running `start_pokealarm.py` will start the PokeAlarm server and assume the following as default: - -``` -Host: 127.0.0.1 -Port: 4000 -filters: filters.json -alarms: alarms.json -``` - -Which is equivalent to running the command below: - -`start_pokealarm.py -H 127.0.0.1 -P 4000 -f filters.json -a alarms.json` - -### Running multiple alarms, filters, etc., in a single `start_pokealarm.py` instance from the command line -Version 3 requires `filters.json` and `alarms.json`. `Geofence.txt` is optional. - -| Command line parameter | default | Desciption | -|-----------|:----------:|---------------------| -`-f FILTERS.JSON` | `filters.json` | your desired pokemon, gym, and pokestop filters. Visit the [Filters](Filters) wiki article for more details. -`-gf GEOFENCE_FILE` | `geofence.txt` | File containing a list of coordinates for one or more geofence. Requires a header, in brackets `[ ]`, before each list of coordinates. Visit the [Geofences](geofences) wiki article for more details. -`-a ALARMS.JSON` | `alarms.json` | set of alarms, or services, e.g., Twitter, Discord, Slack. Visit the [Alarms](alarms) wiki article for details. -`-m NUMBER_OF_MANAGERS` | `1` | number of total PokeAlarm Managers (processes) - -### Running one Manager from the command line -If you want just one manager with one geofence, filter, and alarm config, run like so: - -`start_pokealarm.py -m 1 -f filters.json -gf geofences.txt -a alarms.json` - -(`-m 1` is the default. It's added above just for clarity. You can skip if you plan on running only 1 Manager.) - -### Running two Managers from the command line -If you want to run 2 managers, each with it's own filters, geofence, and alarms, you need to specify them in the desired order like so: - -`start_pokealarm.py -m 2 -f filters1.json -gf geofences1.txt -a alarms1.json -f filters2.json -gf geofences2.txt -a alarms2.json` - -This way, the configs are matched like so: - -| Manager Number | filter | geofence | alarm | -|:--------------:|:------:|:--------:|:-----:| -| Manager 1 | `filters1.json`| `geofences1.txt` | `alarms1.json` | -| Manager 2 | `filters2.json`|`geofences2.txt` | `alarms2.json` | - -### Special case: using one `filters.json`, `geofence.txt`, `alarms.json`, etc., for all Managers from the command line -Let's say you want one `filters_all.json` for two managers, like so: - -| Manager | Description | -|:-------:|:-----------:| -| PokeAlarm Manager 1 | `filters_all.json`, `geofences1.txt`, and `alarms1.json` -| PokeAlarm Manager 2 | `filters_all.json`, `geofences2.txt`, and `alarms2.json` - -If you run `start_pokealarm.py` with more than one manager and only specify one `-f filters_all.json` in the command line, PokeAlarm v3 will assign that `filters_all.json` to all managers. For example: - -`start_pokealarm.py -m 2 -f filters_all.json -gf geofences1.txt -a alarms1.json -gf geofences2.txt -a alarms2.json` - -### Using `config.ini` to simplify Manager... management -To faciliate multiple combinations of managers, filters, alarms, geofences, etc., PokeAlarm v3 allows you add a list of these parameters in `config.ini`. - -Scenario: Let's say you want to run PokeAlarm for 2 areas - Los Angeles and Tokyo - with 2 filters each (`filters_main.json`, `filters_nearby.json`). Three geofences are desired (`geofence_la.txt`, `None`, and `geofence_tk.txt`), and one alarm config each (`alarms_la_v3.json` and `alarms_tk_v3.json`) is added, for a total of 4 PokeAlarm managers. - -In a table, it looks like this: - -| Manager Number | Parameter | Value | -|:--------------:|:---------:|:-----:| -| 1 | location | `"Los Angeles CA"` | -| 1 | filter | `filters_main.json`| -| 1 | geofence | `geofence_la.txt` | -| 1 | alarms | `alarms_la.json` | -| 1 | unit | `imperial` | -| 1 | timezone | `Amer\Los_Angeles` | -| --------|---------- |-------| -| 2 | location | `"Los Angeles CA"` | -| 2 | filter | `filters_nearby.json`| -| 2 | geofence | `None` | -| 2 | alarms | `alarms_la.json` | -| 2 | unit | `imperial` | -| 2 | timezone | `Amer\Los_Angeles` | -| --------|---------- |-------| -| 3 | location | `"Tokyo Japan"` | -| 3 | filter | `filters_main.json`| -| 3 | geofence | `geofence_tk.txt` | -| 3 | alarms | `alarms_tk.json` | -| 3 | unit | `metric` | -| 3 | timezone | `Amer\Los_Angeles` | -| --------|---------- |-------| -| 4 | location | `"Tokyo Japan"` | -| 4 | filter | `filters_nearby.json`| -| 4 | geofence | `None` | -| 4 | alarms | `alarms_tk.json` | -| 4 | unit | `metric` | -| 4 | timezone | `Amer\Los_Angeles` | - -In the CLI, it would look like this: - -`start_pokealarm.py -l "Los Angeles CA" -l "Los Angeles CA" -l "Tokyo Japan" -l "Tokyo Japan" -f filters_main.json -f filters_nearby.json -f filters_main.json -f filters_nearby.json -gf geofence_la.txt -gf None -gf geofence_tk.txt -gf geofence_tk.txt -a alarms_la_v3.json -a alarms_la_v3.json -a alarms_tk_v3.json -a alarms_tk_v3.json -u imperial -u imperial -u metric -u metric -tz America/Los_Angeles` - -Pretty beastly, right? Here's an example of how to configure `config.ini` to achieve the same goal: - -``` -manager_count: 4 -location: [ "Los Angeles CA", "Los Angeles CA", "Tokyo Japan", "Tokyo Japan" ] -filter: [ filters_main.json, filters_nearby.json, filters_main.json, filters_nearby.json ] -geofence: [ geofence_la.txt, None, geofence_tk.txt, geofence_tk.txt ] -alarms: [ alarms_la_v3.json, alarms_la_v3.json, alarms_tk_v3.json, alarms_tk_v3.json ] -unit: [ imperial, imperial, metric, metric ] -timezone: America/Los_Angeles - -``` -(The spacing for alignment is purely for aesthetic purposes.) - -You would then run the following to launch the PokeAlarm server: - -`start_pokealarm.py` - -That's it. (=0 - -Some notes: - -* Order is important - the list elements are index matched with each other -* The geofence line in the example above contains a `None` entry, meaning that the second Manager will not use a geofence -* Location syntax is finicky. Use `"Los Angeles CA"` but not `"Los Angeles, CA"`. The comma will mess things up -* The `timezone` with only one element, `America/Los_Angeles`, will apply to all 4 managers. Don't wrap the timezone in double quotes - -The following parameters can be set in a list in `config.ini`: -* key -* manager name -* location -* filters -* geofences -* alarms -* unit -* timelimit - -### Naming your Managers -Similar to `-sn` in RocketMap, you can name individual PokeAlarm Managers. This helps to make the log files easier to read. - -* Use `-M "Manager 1" -M "Manager 2" -M "Manager 3"` in the commandline -* In `config.ini`, use `manager_name: [ "Manager 1, "Manager 2", "Manager 3" ]` in a list. - * Tip: As I did above, you can add extra white spaces to line up the different managers in `config.ini` for aesthetics - -### Running Multiple Instances of the PokeAlarm Server -Use the `-cf` flag for each instance you plan to run. Make sure that each instance is using a different port. -``` -start_pokealarm.py -cf config1.ini -start pokealarm.py -cf config2.ini -``` - -## Final notes - -* The wiki is being overhauled to reflect the above notes and more. -* If you have questions that haven't been addressed in this quick start guide, hit us up in the discord channel or submit a ticket on the Github page. -* If you enjoy PokeAlarm, [please support the developer by sending a small donation.](https://www.paypal.com/cgi-bin/webscr?cmd=_donations&business=5W9ZTLMS5NB28&lc=US&item_name=PokeAlarm¤cy_code=USD) PokeAlarm is used by literally thousands of people on a daily basis. Pretty much every public twitter feed uses PokeAlarm - why not send a beer to the dev for a job well done? (=0 Happy Hunting and Good Luck! diff --git a/docs/other/v3.2-guide.md b/docs/other/v3.2-guide.md deleted file mode 100644 index f10f15270..000000000 --- a/docs/other/v3.2-guide.md +++ /dev/null @@ -1,145 +0,0 @@ -# Remedy's v3.2 Guide - -Updated: 18 July 2017 - -## Purpose - -* This document is intended to quickly provide PokeAlarm users with info to get started. It is not intended to replace the full wiki. - -## Overview - -* [Before you begin](#before-you-begin) -* [Notes](#notes) -* [Introduction](#introduction) - * [Upgrading from 3.1](#upgrading-from-31) - * [Filters](#updating-filter-configuration) - * [Alarms](#alarms) - -## Before you begin -* Version 3.2 is now in the master branch. Read the patch notes if you are upgrading from version 3. -* Features are constantly being added. Always visit the #announcements discord channel for udpates -* Contact us in the [#troubleshooting discord channel](https://discordapp.com/channels/215181169761714177/218822834225545216) or open a ticket on our [github page](https://github.com/PokeAlarm/PokeAlarm/issues) - -## Notes -* Remember - you only need to edit the JSON, `geofence.txt`, and `config.ini` files. Other modifications to the code are not supported!!! -* PyCharm is a great IDE to manage your JSON and config files. The EDU edition is free: https://www.jetbrains.com/pycharm-edu . This will will help you avoid those pesky formatting errors. -* Alternatively, use an online JSON editor like http://www.jsoneditoronline.org which will yell at you if the json is incorrectly formatted - -## Introduction -PokeAlarm v3.2 introduces support for -* Raid alarms -* New Dynamic Text Substitution for pokemon CP, level and more gym information - -## Upgrading from 3.1 - -1. Update PokeAlarm `git pull` -2. Make sure requirements are in oder `pip install -r requirements.txt` -3. Change the configuration with the new raid filters - see the information below -4. (Optional) modify your `alarms.json` to customize egg and raid messages. - -### Updating Filter Configuration -To use 3.2, existing filters.json file must be updated with the two new sections describing eggs and raids in filters.example.json. Either copy the new sections into your existing configuration(s) or start from scratch by making a copy of the example file. - -The filter following new egg filters are available: - -- **min_level**: An integer describing the minimum level of the raid you want to send alarms about. Raids with a lower level will not be sent -- **max_level**: An integer describing he maximum level of the raid you want to send alarms about. Raids with a higher level will not be sent - -Example eggs filter: -```json - "eggs": { - "enabled":"True", - "min_level": "1", - "max_level": "5" - }, -``` - -The default pokemon filter is used for raids and kept the same way as pokemon filters for simplicity, but some values like iv and size will not have a meaningful use. Raid pokemon will only report CP and have perfect IVs. - -See the pokemon filter documentation ([Filters] ) for more information. - -Example raids filter: -```json - "raids":{ - "enabled":"True", - "default": { - "min_dist":"0", "max_dist":"inf", "min_cp": "0", "max_cp": "999999", "min_iv":"0", "max_iv":"100", - "min_atk": "0", "max_atk":"15", "min_def": "0", "max_def":"15", "min_sta": "0", "max_sta":"15", - "quick_move": null, "charge_move": null, "moveset": null, - "size": null, "gender": null, "form": null, "ignore_missing": "False" - }, - "Bayleef":"True", - "Croconaw":"True", - "Magikarp":"True", - "Quilava":"True", - "Electabuzz":"True", - "Exeggutor":"True", - "Magmar":"True", - "Muk":"True", - "Weezing":"True", - "Alakazam":"True", - "Arcanine":"True", - "Flareon":"True", - "Gengar":"True", - "Jolteon":"True", - "Machamp":"True", - "Vaporeon":"True", - "Blastoise":"True", - "Charizard":"True", - "Lapras":"True", - "Rhydon":"True", - "Snorlax":"True", - "Tyranitar":"True", - "Venusaur":"True", - "Articuno":"True", - "Zapdos":"True", - "Moltres":"True", - "Mewtwo":"True", - "Mew":"True", - "Raikou":"True", - "Entei":"True", - "Suicune":"True", - "Lugia":"True", - "Ho-Oh":"True", - "Celebi":"True" - } -``` - -## Alarms -if you want custom alarm messages you can use dynamic text substitution as with existing alarms. There are two new messages to set up: -- **egg** - Alarm when a raid battle is announced - only contains raid level and start/end times but no pokemon -- **raid** - Alarm when a pokemon battle has started in a gym. Contains raid level, start and end times and pokemon information - -For raid messages you can use the same keywords as pokemon alarms, including cp and moves. - -Additionally there are a few new keywords: -- : Puts in the level of the raid -- , , the time for the raid start in 24 hour, 12 hour and time left until start. - -The following is the default alarms for egg and raid in Discord: - -### Egg -```json - "egg": { - "username": "Egg", - "content": "", - "icon_url": "https://raw.githubusercontent.com/PokeAlarm/PokeAlarm/master/icons/egg_.png", - "avatar_url": "https://raw.githubusercontent.com/PokeAlarm/PokeAlarm/master/icons/egg_.png", - "title": "Raid is incoming!", - "url": "", - "body": "A level raid will hatch ()." - } -``` - -### Raid -```json - "raid": { - "username": "Raid", - "content": "", - "icon_url": "https://raw.githubusercontent.com/PokeAlarm/PokeAlarm/master/icons/.png", - "avatar_url": "https://raw.githubusercontent.com/PokeAlarm/PokeAlarm/master/icons/egg_.png", - "title": "Level Raid is available against !", - "url": "", - "body": "The raid is available until <24h_time> ()." - } -``` diff --git a/docs/settings/alarms.md b/docs/settings/alarms.md deleted file mode 100644 index f860941a0..000000000 --- a/docs/settings/alarms.md +++ /dev/null @@ -1,236 +0,0 @@ -# Alarms - -## Overview - -* [Prerequisites](#prerequisites) -* [Introduction](#introduction) -* [Editing or Adding Alarms](#editing-or-adding-alarms) -* [Customizing Alerts](#customizing-alerts) -* [Example `alarms.json`](#example-alarmsjson) - -## Prerequisites - -This guide assumes: - -1. You have a working RocketMap installation -2. You are familiar with [JSON formatting](https://www.w3schools.com/js/js_json_intro.asp) - -## Introduction - -In PokeAlarm, an "Alarm" is defined as a supported message service that sends a notification. Slack, Twitter, Telegram, each are considered message service. - -PokeAlarm allows you to add as many different supported message services as you'd like (e.g., Slack, Twitter, Telegram), and as many of each message service that you would like (e.g., 3 Slack channels, 10 Twitter feeds, 5 Telegrams.) - -You add alarms to the PokeAlarm alarm configuration file, which is `alarms.json` by default. - -`alarms.json` is where: - -1. Alarms are enable/disabled -2. Notification messages for each alarm are customized - -The alarm configuration file follows the JSON format and has six sections: - -1. `alarms` -2. `pokestop` -3. `gym` -4. `pokemon` -5. `egg` -6. `raid` - - -## Editing or Adding Alarms -To add, edit, or remove alarms, edit the `alarms.json` file. If you haven't created an `alarms.json` file before, you can make a copy of `alarms.json.example` and rename it to `alarms.json`. PokeAlarm uses `alarms.json` by default. - -Alarms are represented as a list of JSON Objects, inside an array labeled alarms. Each alarm should be surrounded by curly brackets, and the space in between fields should have a comma. Your default `alarms.json` looks like this: -```json -[ - { - "active": "False", - "type": "discord", - "webhook_url": "YOUR_WEBHOOK_URL" - }, - { - "active": "False", - "type": "facebook_page", - "page_access_token": "YOUR_PAGE_ACCESS_TOKEN" - }, - { - "active": "False", - "type": "pushbullet", - "api_key": "YOUR_API_KEY" - }, - { - "active": "False", - "type": "slack", - "api_key": "YOUR_API_KEY" - }, - { - "active": "False", - "type": "telegram", - "bot_token": "YOUR_BOT_TOKEN", - "chat_id": "YOUR_CHAT_ID" - }, - { - "active": "False", - "type": "twilio", - "account_sid": "YOUR_API_KEY", - "auth_token": "YOUR_AUTH_TOKEN", - "from_number": "YOUR_FROM_NUM", - "to_number": "YOUR_TO_NUM" - }, - { - "active": "False", - "type": "twitter", - "access_token": "YOUR_ACCESS_TOKEN", - "access_secret": "YOUR_ACCESS_SECRET", - "consumer_key": "YOUR_CONSUMER_KEY", - "consumer_secret": "YOUR_CONSUMER_SECRET" - } -] -``` - -Each alarm requires some sort of API key or URL so that PokeAlarm can gain -permissions to post. Visit the wiki page of the service you are setting up -to make sure you have the proper config. - -Each alarm setting runs independent of the other alarms, so changes to one -alarm do not affect the others (even if they are of the same type). - -If is perfectly valid to have any combination of services, including repeats. - -## Customizing Alerts - -Most alarms have customizable fields for each alert that allow you to insert -your own message. This allows your to override the standard message and -provide your own. You may customize as few or as many fields as you want - -any field not present in your config will reset to default. - -In order to customize an Alert, you must specify what type of alert you -want to config: Either `pokemon`, `pokestop`, `gym`, `egg` or `raid`. Each -of these has different defaults available. The following is a config where -a portion of the Alert has been updated: - -```json -{ - "type":"slack", - "active":"True", - "api_key":"YOUR_API_KEY_HERE", - "pokemon":{ - "channel":"Pokemon", - "username":"", - "title":"A GIANT jumped out of the grass!", - "body": "Available until <24h_time> ()." - }, - "pokestop":{ - "channel":"Pokestop", - "title":"Someone has placed a lure on a Pokestop!", - "body":"Better hurry! The lure only has remaining!" - } -} -``` - -For more information about Dynamic Text Substitutions (the ``), please see the Dynamic Text Substitution wiki. - -For what service has what fields, please check the specific wiki page for that service. - -## Example `alarms.json` - -Below is a working alarm configuration for Discord and Slack: - -```json -[ - { - "active": "True", - "type":"discord", - "webhook_url":"DISCORD_WEBHOOK_URL_FOR_FALLBACK", - "startup_message":"False", - "pokemon":{ - "webhook_url":"DISCORD_WEBHOOK_URL_FOR_POKEMON_CHANNEL", - "username":"", - "title": " **CP** (**% //**, /) at
", - "url": "", - "body": "Available until <24h_time> ( remaining)" - }, - "pokestop":{ - "username":"Pokestop", - "webhook_url":"DISCORD_WEBHOOK_URL_FOR_POKESTOP_CHANNEL", - "title": "[]
", - "url": "", - "body": "expires at <24h_time> ()." - }, - "gym":{ - "webhook_url":"DISCORD_WEBHOOK_URL_FOR_GYM_CHANNEL", - "username":" Gym Alerts", - "title": "[]
", - "url": "", - "body": "A team gym has fallen to ." - }, - "egg": { - "webhook_url":"DISCORD_WEBHOOK_URL_FOR_EGG_CHANNEL", - "username": "Egg", - "title": "Raid is incoming!", - "url": "", - "body": "A level raid will hatch at <24h_hatch_time> ()." - }, - "raid": { - "webhook_url":"DISCORD_WEBHOOK_URL_FOR_RAID_CHANNEL", - "username": " Raid", - "title": "Level raid is available against !", - "url": "", - "body": "The raid is available until <24h_raid_end> ()." - } - }, - { - "active": "True", - "type": "slack", - "api_key": "YOUR_SLACK_API_KEY", - "startup_message": "False", - "pokemon": { - "channel": "pokemon", - "username": "Pokemon", - "title": "** (% //) in at
", - "url": "", - "body": "Available until <24h_time> ()\n*Moves:* / ", - "map": { - "enabled": "True", - "width": "330", - "height": "250", - "maptype": "roadmap", - "zoom": "17" - } - }, - "pokestop": { - "channel": "pokestops", - "username": "Pokestop", - "title": "[]
", - "url": "", - "body": "expires at <24h_time> ().", - "map": { - "enabled": "False", - "width": "330", - "height": "250", - "maptype": "roadmap", - "zoom": "15" - } - }, - "gym": { - "channel": "gyms", - "username": " Gym Alerts", - "title": "[]
", - "url": "", - "body": "A team gym has fallen to .", - "map": { - "enabled": "True", - "width": "330", - "height": "250", - "maptype": "terrain", - "zoom": "13" - } - } - } -] -``` - -Note both have `"active":"true"` set, meaning both alarms are enabled. Setting either to "false" will disable the specific alarm.. This allows you to have alarms set up and ready to go, but only enabled when you want them. - -Visit the wiki article on [Filters](filters-overview) to limit pokemon notifications by distance, %IV, and moves with the `filters.json` file. diff --git a/docs/settings/geofences.md b/docs/settings/geofences.md deleted file mode 100644 index cca3194e8..000000000 --- a/docs/settings/geofences.md +++ /dev/null @@ -1,229 +0,0 @@ -# Geofences - -## Overview - -* [Introduction](#introduction) -* [Instructions](#instructions) -* [Example: 4 point geofence - Central Park, New York, NY](#example-4-point-geofence---central-park-new-york-ny) -* [Example: 21 point geofence - Coronado, San Diego, CA](#example-21-point-geofence---corando-island-san-diego-ca) -* [Example: Multiple Geofences in the same `geofences.txt` file](#example-multiple-geofences-in-the-same-geofencestxt-file) -* [Geofence Generator: Draw Your Own Geofence](#geofence-generator-draw-your-own-geofence) - -## Introduction -Geofencing will restrict PokeAlarm alerts to a defined geographical area. -The area is defined by a list of at least 2 sets of latitude and longitude -coordinates. You may provide as many coordinates as you'd like to define -your area of interest, provided that these sets are in the order that -defines your polygon. - -**Note:** PokeAlarm will first check pokemon alert distance, *then* will -check to see if the pokemon is located within your geofence. -See [Filters](monster-filters#parameters) on how to limit alerts -based on distance. - -## Instructions - -Create a text file with with a series of at least 3 *latitude,longitude* -sets and place this in the same folder as `start_pokealarm.py`. -(A minimum of 3 points are required as of PokeAlarm v3.1.) - -**To define a rectangular geofence:** Use 2 lat/lon sets, with the first -set defining the top left of the rectangle, and the second defining the -bottom right of the rectangle. - -**To define a polygonal geofence:** Provide as many lat/lon sets as it -takes to define your polygon. Make sure that you provide the points -**in order** to describe the polygon. - -Execute `start_pokealarm.py` with the `-gf` or `--geofences` flag, -along with the path to your geofence file, or add -`geofence:YOUR_GEOFENCE_FILE` to `config.ini`. - -## Example: 4 point geofence - Central Park, New York, NY - -The text file below defines the northwest, southwest, southeast and -northeast corners of central park. The heading in brackets -`[NAME_OF_GEOFENCE]` is mandatory, and PokeAlarm will fail if not -included in the geofence file. - -file: `central-park-geofence.txt` -``` -[Central Park, NY] -40.801206,-73.958520 -40.767827,-73.982835 -40.763798,-73.972808 -40.797343,-73.948385 -``` - -![](../images/geofence_central_park_640x640.png) - -In the image above, each numbered marker 1-4 represents the lat,lon -coordinates found in central-park-geofence.txt, respectively. - -To run PokeAlarm with geofencing enabled, execute: - -`python start_pokealarm.py -gf central-park-geofence.txt` - -or - -`python start_pokealarm.py --geofences central-park-geofence.txt` - -or you can include `geofences:central-park-geofence.txt` in your -`config.ini` file. - -If successful, you should receive a confirmation in your log: - -``` -2018-01-20 18:05:26 [ Geofence][ INFO] Geofence Central Park, NY added! -``` - -For our Central Park example, all 4 points encompass the entire park. -The visual of the geofenced area is below. -The red marker in the image denotes a selected location, here, -"The Pond, Central Park, NY". - -![](../images/geofence_central_park_bounded.png) - -PokeAlarm will then notify you of pokemon within the shaded area. - -**Note:** Remember to configure the filters to use this area of ​​the geofence -or will not apply to alerts. Example: - -``` -"filter_tiny_central_park": { - "geofences": [ "Central Park, NY" ] -} -``` - -## Example: 21 point geofence - Coronado Island, San Diego, CA - -You may add as many lat,lon points to define you polygon, provided that the -points in your geofence file are in order of defining said polygon. Below is -an example of a 21 point polygon encompassing an area. - -file: `geofence_coronado.txt` -``` -[Coronado, CA] -32.7134997863394,-117.18893051147461 -32.71508853568461,-117.19330787658691 -32.715305181130056,-117.20541000366211 -32.71046664083005,-117.2189712524414 -32.69977759183938,-117.22764015197754 -32.6864144801245,-117.22832679748535 -32.679985027301136,-117.22412109375 -32.6859810484179,-117.21107482910156 -32.685619853722,-117.19390869140625 -32.67239912263756,-117.1721076965332 -32.675794797699766,-117.1677303314209 -32.68020175796835,-117.17494010925293 -32.68164661564297,-117.17279434204102 -32.677600955252075,-117.16695785522461 -32.68540313620318,-117.16155052185059 -32.692626770053714,-117.16197967529297 -32.698549713686894,-117.16541290283203 -32.70346112493775,-117.17897415161133 -32.704400040429604,-117.18008995056152 -32.70700006253934,-117.18978881835938 -32.711983226476136,-117.18704223632812 -``` - -And remember to set filters to apply geofence like this example: - -``` -"filter_coronado": { - "geofences": [ "Coronado, CA" ] -} -``` - -Below is the resulting geofence: - -![](../images/geofence_coronado.png) - -## Example: Multiple Geofences in the same `geofences.txt` file - -You are permitted to add more than one geofence area in a single -`geofences.txt` file. Add a bracketed header before each set of -coordinates. For example: - -``` -[Central Park, NY] -40.801206,-73.958520 -40.767827,-73.982835 -40.763798,-73.972808 -40.797343,-73.948385 -[Coronado, CA] -32.7134997863394,-117.18893051147461 -32.71508853568461,-117.19330787658691 -32.715305181130056,-117.20541000366211 -32.71046664083005,-117.2189712524414 -32.69977759183938,-117.22764015197754 -32.6864144801245,-117.22832679748535 -32.679985027301136,-117.22412109375 -32.6859810484179,-117.21107482910156 -32.685619853722,-117.19390869140625 -32.67239912263756,-117.1721076965332 -32.675794797699766,-117.1677303314209 -32.68020175796835,-117.17494010925293 -32.68164661564297,-117.17279434204102 -32.677600955252075,-117.16695785522461 -32.68540313620318,-117.16155052185059 -32.692626770053714,-117.16197967529297 -32.698549713686894,-117.16541290283203 -32.70346112493775,-117.17897415161133 -32.704400040429604,-117.18008995056152 -32.70700006253934,-117.18978881835938 -32.711983226476136,-117.18704223632812 -``` - -In this example, you can configure an individual alarm to only check one -geofence from your geofence.txt. This filter will only check the geofence -named "Central Park, NY: - -``` -"filter_central_park": { - "geofences": [ "Central Park, NY" ] -} -``` - -Or check the 2 geofence zones with: - -``` -"filter_central_park_coronado": { - "geofences": [ "Central Park, NY", "Coronado, CA" ] -} -``` - -Additionally, you can use "geofences": [ "all" ] as a shortcut for checking -all geofences in a geofence file. Example: - -``` -"filter_all_geofences": { - "geofences": [ "all" ] -} -``` - -## Geofence Generator: Draw Your Own Geofence -These are handy web tool to create and visualize your desired geofence. - -Jason's [A Better Fence Editor](http://geo.jasparke.net/) - Recommended by PokeAlarm team - -To use it: -1. Create a fence name, color and click Create. (If you have a fence already -paste it into the Coordinate Set) -2. Click for each geofence point until you have made made a full circle. -3. Click exp (Export) from there you can copy, paste or click Download with -or without fence name tag. -4. To better manage all your geofences in one file you can save a json file -that saves everything as you have it. -5. Click load to load previously generated geofences and continue. - -JennerPalacios's Codepen [Geofence Generator](https://codepen.io/jennerpalacios/full/mWWVeJ) - -To use it: -1. Type your desired location. -2. Click for each geofence point that you would like to add to the -coordinate list. -3. Complete your geofence area by clicking the original point, the last -point, or double clicking. -4. Click "Show Coordinates", Assign a name - ie: [Seattle] and then -click "Copy to Clipboard" diff --git a/docs/settings/server-settings.md b/docs/settings/server-settings.md deleted file mode 100644 index 7eab9c174..000000000 --- a/docs/settings/server-settings.md +++ /dev/null @@ -1,127 +0,0 @@ -## Overview -This guide will walk you through configuring server settings for PokeAlarm. - -* [Prerequisites](#prerequisites) -* [Server Settings](#server-settings) -* [Command Line](#command-line) -* [Configuration File](#configuration-file) - -## Prerequisites -This guide assumes the following: - -1. You have correctly [installed PokeAlarm](installation). - -2. You are using Notepad++, Nano, or Vi(m) to configure any files. Do **NOT** -use or open any files with Notepad or TextEdit - they will break your files! - -## Server Settings - -Settings for the PokeAlarm server can be done the following two ways: - -1. **Command Line** - When starting PokeAlarm, you can specify certain -settings with flags following the start up command. For example, you can -change the IP that PokeAlarm binds itself to by using either -`python start_pokealarm.py -H 192.168.0.1` or `python start_pokealarm.py --host 192.168.0.1`. - **Note**: when used together, command line flags will override arguments - specified in the configuration file. - -2. **Configuration File** - You can also use a configuration file in `ini` -format to set server settings for PokeAlarm. These settings use the same -flags at the command line. For example, you either `host: 192.168.0.1` or -`H: 192.168.0.1` line to the configuration file to change the IP that -PokeAlarm binds itself to. - -For files, all relative paths will being from the PokeAlarm root folder, but -absolute file paths can still be used. - -## Command Line - -To get the most recent command line settings for your version, use the -following command: `python start_pokealarm.py --help`. - -``` -usage: start_pokealarm.py [-h] [-cf CONFIG] [-d] [-H HOST] [-P PORT] - [-m MANAGER_COUNT] [-M MANAGER_NAME] [-k KEY] - [-f FILTERS] [-a ALARMS] [-gf GEOFENCES] - [-l LOCATION] [-L {de,en,es,fr,it,ko,pt,zh_hk}] - [-u {metric,imperial}] [-tl TIMELIMIT] - [-ma MAX_ATTEMPTS] [-tz TIMEZONE] - [-ct {mem,file}] - - -optional arguments: - -h, --help show this help message and exit - -cf CONFIG, --config CONFIG - Configuration file - -d, --debug Debug Mode - -H HOST, --host HOST Set web server listening host - -P PORT, --port PORT Set web server listening port - -m MANAGER_COUNT, --manager_count MANAGER_COUNT - Number of Manager processes to start. - -M MANAGER_NAME, --manager_name MANAGER_NAME - Names of Manager processes to start. - -k KEY, --key KEY Specify a Google API Key to use. - -f FILTERS, --filters FILTERS - Filters configuration file. default: filters.json - -a ALARMS, --alarms ALARMS - Alarms configuration file. default: alarms.json - -gf GEOFENCES, --geofences GEOFENCES - Alarms configuration file. default: None - -l LOCATION, --location LOCATION - Location, can be an address or coordinates - -L {de,en,es,fr,it,ko,pt,zh_hk}, --locale {de,en,es,fr,it,ko,pt,zh_hk} - Locale for Pokemon and Move names: default en, check - locale folder for more options - -u {metric,imperial}, --units {metric,imperial} - Specify either metric or imperial units to use for - distance measurements. - -tl TIMELIMIT, --timelimit TIMELIMIT - Minimum number of seconds remaining on a pokemon to - send a notify - -ma MAX_ATTEMPTS, --max_attempts MAX_ATTEMPTS - Maximum number of attempts an alarm makes to send a - notification. - -tz TIMEZONE, --timezone TIMEZONE - Timezone used for notifications. Ex: - "America/Los_Angeles" - -ct {mem,file}, --cache_type {mem,file} - Caching method used to cache data objects for use - in Alerts. default: `mem` -``` - -## Configuration File - -A copy of the most recent configuration file should be located at -`config/config.ini.example`. You can copy this file as a starting point. - -By default, PokeAlarm will load the file at `config/config.ini` if it -exists. You can manually specify a configuration file with either the -`-cf` or `--config` file via the command line. - -```ini -# Copy this file to config.ini and modify to suit your needs -# Uncomment a line (remove the #) when you want to change its default value. -# Multiple arguments can be listed as [arg1, arg2, ... ] -# Number of arguments must match manager_count or be a single argument (single arguments will apply to all Managers) -# To exclude an argument for a specific manager, use 'None' - -# Server Settings -#debug # Enables debugging mode -#host: # Address to listen on (default 127.0.0.1) -#port: # Port to listen on (default: 4000) -#manager_count: 1 # Number of Managers to run. (default: 1) - -# Manager-Specific Settings -#manager_name # Name of the Manager in the logs. Default(manager_0). -#key: # Google Maps API Key to use -#filters: # File containing filter rules (default: filters.json) -#alarms: # File containing alarm rules (default: alarms.json) -#geofence: # File containing geofence(s) used to filter (default: None) -#location: # Location for the manager. 'Name' or 'lat lng' (default: None) -#locale: # Language to be used to translate names (default: en) -#unit: # Units used to measure distance. Either 'imperial' or 'metric' (default: imperial) -#timelimit: # Minimum number of seconds remaining to send a notification (default: 0) -#max_attempts: # Maximum number of attempts an alarm makes to send a notification. (default: 3) -#timezone: # Timezone used for notifications Ex: 'America/Los_Angeles' or '[America/Los_Angeles, America/New_York]' -#cache_type: # Method used to cache dynamic objects used in Alerts. (default: mem) -``` diff --git a/filters.json.example b/filters.json.example index cf2acfbee..f8671c6fe 100644 --- a/filters.json.example +++ b/filters.json.example @@ -5,7 +5,7 @@ }, "filters":{ "filter_by_monsters_example":{ - "monsters":["Bulbasaur","Charmander",7], + "monsters":["Bulbasaur","Charmander",7] }, "filter_by_ivs_example":{ "min_atk": 0, "max_atk": 15, diff --git a/locales/de.json b/locales/de.json index 405a2ab95..e245c2f69 100644 --- a/locales/de.json +++ b/locales/de.json @@ -1,38 +1,99 @@ { + "costumes": { + "025": { + "001": "Festlicher Hut", + "002": "Partyhut", + "003": "Ash Cap", + "004": "Hexenhut" + }, + "026": { + "001": "Festlicher Hut", + "002": "Partyhut", + "003": "Ash Cap", + "004": "Hexenhut" + }, + "172": { + "001": "Festlicher Hut", + "002": "Partyhut", + "003": "Ash Cap", + "004": "Hexenhut" + } + }, "leaders": { - "0": "Professor Willow", - "1": "Blanche", - "2": "Candela", - "3": "Spark" - }, - "sizes": { - "1": "winzig", - "2": "klein", - "3": "\u00dcblich", - "4": "gro\u00DF", - "5": "riesig" - }, - "types": { - "1": "Normal", - "2": "Kampf", - "3": "Flug", - "4": "Gift", - "5": "Boden", - "6": "Stein", - "7": "K\u00E4fer", - "8": "Geist", - "9": "Stahl", - "10": "Feuer", - "11": "Wasser", - "12": "Pflanze", - "13": "Elektro", - "14": "Psycho", - "15": "Eis", - "16": "Drache", - "17": "Fee", - "18": "Unlicht" - }, + "000": "Professor Willow", + "001": "Blanche", + "002": "Candela", + "003": "Spark" + }, + "misc": { + "boosted": "verst\u00e4rktes" + }, "moves": { + "013": "Wickel", + "014": "Hyperstrahl", + "016": "Finsteraura", + "018": "Schlammbad", + "020": "Klammer", + "021": "Flammenrad", + "022": "Vielender", + "024": "Flammenwurf", + "026": "Schaufler", + "028": "Kreuzhieb", + "030": "Psystrahl", + "031": "Erdbeben", + "032": "Steinkante", + "033": "Eishieb", + "034": "Herzstempel", + "035": "Ladungssto\u00df", + "036": "Lichtkanone", + "038": "Bohrschnabel", + "039": "Eisstrahl", + "040": "Blizzard", + "042": "Hitzewelle", + "045": "Aero-Ass", + "046": "Schlagbohrer", + "047": "Bl\u00fctenwirbel", + "048": "Megasauger", + "049": "K\u00e4fergebrumm", + "050": "Giftzahn", + "051": "Nachthieb", + "053": "Blubbstrahl", + "054": "\u00dcberroller", + "056": "Fu\u00dftritt", + "057": "Wasserd\u00fcse", + "058": "Nassschweif", + "059": "Samenbomben", + "060": "Psychoschock", + "062": "Antik-Kraft", + "063": "Felsgrab", + "064": "Steinhagel", + "065": "Juwelenkraft", + "066": "Schattensto\u00df", + "067": "Finsterfaust", + "069": "Unheilb\u00f6en", + "070": "Spukball", + "072": "Magnetbombe", + "074": "Eisensch\u00e4del", + "075": "Parabolladung", + "077": "Donnerschlag", + "078": "Donner", + "079": "Donnerblitz", + "080": "Windhose", + "082": "Drachenpuls", + "083": "Drachenklaue", + "084": "S\u00e4uselstimme", + "085": "Diebeskuss", + "086": "Zauberschein", + "087": "Mondgewalt", + "088": "Knuddler", + "089": "Giftstreich", + "090": "Matschbombe", + "091": "Schlammwoge", + "092": "M\u00fclltreffer", + "094": "Knochenkeule", + "095": "Dampfwalze", + "096": "Schlammbombe", + "099": "Ampelleuchte", "100": "Kreuzschere", "101": "Nitroladung", "102": "Funkenflug", @@ -56,7 +117,6 @@ "126": "Hornattacke", "127": "Stampfer", "129": "Hyperzahn", - "13": "Wickel", "131": "Bodyslam", "132": "Erholung", "133": "Verzweifler", @@ -64,10 +124,6 @@ "135": "Hydropumpe (Turtok)", "136": "Wickel (Gr\u00fcn)", "137": "Wickel (Lila)", - "14": "Hyperstrahl", - "16": "Finsteraura", - "18": "Schlammbad", - "20": "Klammer", "200": "Zornklinge", "201": "K\u00e4ferbiss", "202": "Biss", @@ -78,7 +134,6 @@ "207": "Fu\u00dfkick", "208": "Karateschlag", "209": "Glut", - "21": "Flammenrad", "210": "Fl\u00fcgelschlag", "211": "Schnabel", "212": "Schlecker", @@ -89,7 +144,6 @@ "217": "Eissplitter", "218": "Eisesodem", "219": "Ruckzuckhieb", - "22": "Vielender", "220": "Kratzer", "221": "Tackle", "222": "Pfund", @@ -109,7 +163,6 @@ "237": "Blubber", "238": "Finte", "239": "Stahlfl\u00fcgel", - "24": "Flammenwurf", "240": "Feuerzahn", "241": "Zertr\u00fcmmerer", "242": "Wandler", @@ -130,7 +183,6 @@ "257": "Himmelsfeger", "258": "Sandgrab", "259": "Felswurf", - "26": "Schaufler", "260": "Plage", "261": "K\u00e4fertrutz", "262": "Silberhauch", @@ -151,79 +203,119 @@ "277": "Wutanfall", "278": "Standpauke", "279": "Knirscher", - "28": "Kreuzhieb", "280": "Schmarotzer", "281": "Kraftreserve", - "30": "Psystrahl", - "31": "Erdbeben", - "32": "Steinkante", - "33": "Eishieb", - "34": "Herzstempel", - "35": "Ladungssto\u00df", - "36": "Lichtkanone", - "38": "Bohrschnabel", - "39": "Eisstrahl", - "40": "Blizzard", - "42": "Hitzewelle", - "45": "Aero-Ass", - "46": "Schlagbohrer", - "47": "Bl\u00fctenwirbel", - "48": "Megasauger", - "49": "K\u00e4fergebrumm", - "50": "Giftzahn", - "51": "Nachthieb", - "53": "Blubbstrahl", - "54": "\u00dcberroller", - "56": "Fu\u00dftritt", - "57": "Wasserd\u00fcse", - "58": "Nassschweif", - "59": "Samenbomben", - "60": "Psychoschock", - "62": "Antik-Kraft", - "63": "Felsgrab", - "64": "Steinhagel", - "65": "Juwelenkraft", - "66": "Schattensto\u00df", - "67": "Finsterfaust", - "69": "Unheilb\u00f6en", - "70": "Spukball", - "72": "Magnetbombe", - "74": "Eisensch\u00e4del", - "75": "Parabolladung", - "77": "Donnerschlag", - "78": "Donner", - "79": "Donnerblitz", - "80": "Windhose", - "82": "Drachenpuls", - "83": "Drachenklaue", - "84": "S\u00e4uselstimme", - "85": "Diebeskuss", - "86": "Zauberschein", - "87": "Mondgewalt", - "88": "Knuddler", - "89": "Giftstreich", - "90": "Matschbombe", - "91": "Schlammwoge", - "92": "M\u00fclltreffer", - "94": "Knochenkeule", - "95": "Dampfwalze", - "96": "Schlammbombe", - "99": "Ampelleuchte", - "281": "Kraftreserve", - "282": "Bodycheck", - "283": "Kaskade", - "284": "Surfer", - "285": "Draco Meteor", - "286": "Kismetwunsch", - "287": "G\u0344hner", - "288": "Psyschub", - "289": "Ursprungswoge", - "290": "Abgrundsklinge", + "282": "Bodycheck", + "283": "Kaskade", + "284": "Surfer", + "285": "Draco Meteor", + "286": "Kismetwunsch", + "287": "G\u0344hner", + "288": "Psyschub", + "289": "Ursprungswoge", + "290": "Abgrundsklinge", "291": "Geschenk" }, "pokemon": { - "1": "Bisasam", - "10": "Raupy", + "001": "Bisasam", + "002": "Bisaknosp", + "003": "Bisaflor", + "004": "Glumanda", + "005": "Glutexo", + "006": "Glurak", + "007": "Schiggy", + "008": "Schillok", + "009": "Turtok", + "010": "Raupy", + "011": "Safcon", + "012": "Smettbo", + "013": "Hornliu", + "014": "Kokuna", + "015": "Bibor", + "016": "Taubsi", + "017": "Tauboga", + "018": "Tauboss", + "019": "Rattfratz", + "020": "Rattikarl", + "021": "Habitak", + "022": "Ibitak", + "023": "Rettan", + "024": "Arbok", + "025": "Pikachu", + "026": "Raichu", + "027": "Sandan", + "028": "Sandamer", + "029": "Nidoran\u2640", + "030": "Nidorina", + "031": "Nidoqueen", + "032": "Nidoran\u2642", + "033": "Nidorino", + "034": "Nidoking", + "035": "Piepi", + "036": "Pixi", + "037": "Vulpix", + "038": "Vulnona", + "039": "Pummeluff", + "040": "Knuddeluff", + "041": "Zubat", + "042": "Golbat", + "043": "Myrapla", + "044": "Duflor", + "045": "Giflor", + "046": "Paras", + "047": "Parasek", + "048": "Bluzuk", + "049": "Omot", + "050": "Digda", + "051": "Digdri", + "052": "Mauzi", + "053": "Snobilikat", + "054": "Enton", + "055": "Entoron", + "056": "Menki", + "057": "Rasaff", + "058": "Fukano", + "059": "Arkani", + "060": "Quapsel", + "061": "Quaputzi", + "062": "Quappo", + "063": "Abra", + "064": "Kadabra", + "065": "Simsala", + "066": "Machollo", + "067": "Maschock", + "068": "Machomei", + "069": "Knofensa", + "070": "Ultrigaria", + "071": "Sarzenia", + "072": "Tentacha", + "073": "Tentoxa", + "074": "Kleinstein", + "075": "Georok", + "076": "Geowaz", + "077": "Ponita", + "078": "Gallopa", + "079": "Flegmon", + "080": "Lahmus", + "081": "Magnetilo", + "082": "Magneton", + "083": "Porenta", + "084": "Dodu", + "085": "Dodri", + "086": "Jurob", + "087": "Jugong", + "088": "Sleima", + "089": "Sleimok", + "090": "Muschas", + "091": "Austos", + "092": "Nebulak", + "093": "Alpollo", + "094": "Gengar", + "095": "Onix", + "096": "Traumato", + "097": "Hypno", + "098": "Krabby", + "099": "Kingler", "100": "Voltobal", "101": "Lektrobal", "102": "Owei", @@ -234,7 +326,6 @@ "107": "Nockchan", "108": "Schlurp", "109": "Smogon", - "11": "Safcon", "110": "Smogmog", "111": "Rihorn", "112": "Rizeros", @@ -245,7 +336,6 @@ "117": "Seemon", "118": "Goldini", "119": "Golking", - "12": "Smettbo", "120": "Sterndu", "121": "Starmie", "122": "Pantimos", @@ -256,7 +346,6 @@ "127": "Pinsir", "128": "Tauros", "129": "Karpador", - "13": "Hornliu", "130": "Garados", "131": "Lapras", "132": "Ditto", @@ -267,7 +356,6 @@ "137": "Porygon", "138": "Amonitas", "139": "Amoroso", - "14": "Kokuna", "140": "Kabuto", "141": "Kabutops", "142": "Aerodactyl", @@ -278,7 +366,6 @@ "147": "Dratini", "148": "Dragonir", "149": "Dragoran", - "15": "Bibor", "150": "Mewtu", "151": "Mew", "152": "Endivie", @@ -289,7 +376,6 @@ "157": "Tornupto", "158": "Karnimani", "159": "Tyracroc", - "16": "Taubsi", "160": "Impergator", "161": "Wiesor", "162": "Wiesenior", @@ -300,7 +386,6 @@ "167": "Webarak", "168": "Ariados", "169": "Iksbat", - "17": "Tauboga", "170": "Lampi", "171": "Lanturn", "172": "Pichu", @@ -311,7 +396,6 @@ "177": "Natu", "178": "Xatu", "179": "Voltilamm", - "18": "Tauboss", "180": "Waaty", "181": "Ampharos", "182": "Blubella", @@ -322,7 +406,6 @@ "187": "Hoppspross", "188": "Hubelupf", "189": "Papungha", - "19": "Rattfratz", "190": "Griffel", "191": "Sonnkern", "192": "Sonnflora", @@ -333,8 +416,6 @@ "197": "Nachtara", "198": "Kramurx", "199": "Laschoking", - "2": "Bisaknosp", - "20": "Rattikarl", "200": "Traunfugil", "201": "Icognito", "202": "Woingenau", @@ -345,7 +426,6 @@ "207": "Skorgla", "208": "Stahlos", "209": "Snubbull", - "21": "Habitak", "210": "Granbull", "211": "Baldorfish", "212": "Scherox", @@ -356,7 +436,6 @@ "217": "Ursaring", "218": "Schneckmag", "219": "Magcargo", - "22": "Ibitak", "220": "Quiekel", "221": "Keifel", "222": "Corasonn", @@ -367,7 +446,6 @@ "227": "Panzaeron", "228": "Hunduster", "229": "Hundemon", - "23": "Rettan", "230": "Seedraking", "231": "Phanpy", "232": "Donphan", @@ -378,7 +456,6 @@ "237": "Kapoera", "238": "Kussilla", "239": "Elekid", - "24": "Arbok", "240": "Magby", "241": "Miltank", "242": "Heiteira", @@ -389,7 +466,6 @@ "247": "Pupitar", "248": "Despotar", "249": "Lugia", - "25": "Pikachu", "250": "Ho-Oh", "251": "Celebi", "252": "Geckarbor", @@ -400,7 +476,6 @@ "257": "Lohgock", "258": "Hydropi", "259": "Moorabbel", - "26": "Raichu", "260": "Sumpex", "261": "Fiffyen", "262": "Magnayen", @@ -411,7 +486,6 @@ "267": "Papinella", "268": "Panekon", "269": "Pudox", - "27": "Sandan", "270": "Loturzel", "271": "Lombrero", "272": "Kappalores", @@ -422,7 +496,6 @@ "277": "Schwalboss", "278": "Wingull", "279": "Pelipper", - "28": "Sandamer", "280": "Trasla", "281": "Kirlia", "282": "Guardevoir", @@ -433,7 +506,6 @@ "287": "Bummelz", "288": "Muntier", "289": "Letarking", - "29": "Nidoran\u2640", "290": "Nincada", "291": "Ninjask", "292": "Ninjatom", @@ -444,8 +516,6 @@ "297": "Hariyama", "298": "Azurill", "299": "Nasgnet", - "3": "Bisaflor", - "30": "Nidorina", "300": "Eneco", "301": "Enekoro", "302": "Zobiris", @@ -456,7 +526,6 @@ "307": "Meditie", "308": "Meditalis", "309": "Frizelbliz", - "31": "Nidoqueen", "310": "Voltenso", "311": "Plusle", "312": "Minun", @@ -467,7 +536,6 @@ "317": "Schlukwech", "318": "Kanivanha", "319": "Tohaido", - "32": "Nidoran\u2642", "320": "Wailmer", "321": "Wailord", "322": "Camaub", @@ -478,7 +546,6 @@ "327": "Pandir", "328": "Knacklion", "329": "Vibrava", - "33": "Nidorino", "330": "Libelldra", "331": "Tuska", "332": "Noktuska", @@ -489,7 +556,6 @@ "337": "Lunastein", "338": "Sonnfel", "339": "Schmerbe", - "34": "Nidoking", "340": "Welsar", "341": "Krebscorps", "342": "Krebutack", @@ -500,7 +566,6 @@ "347": "Anorith", "348": "Armaldo", "349": "Barschwa", - "35": "Piepi", "350": "Milotic", "351": "Formeo", "352": "Kecleon", @@ -511,7 +576,6 @@ "357": "Tropius", "358": "Palimpalim", "359": "Absol", - "36": "Pixi", "360": "Isso", "361": "Schneppke", "362": "Firnontor", @@ -522,7 +586,6 @@ "367": "Aalabyss", "368": "Saganabyss", "369": "Relicanth", - "37": "Vulpix", "370": "Liebiskus", "371": "Kindwurm", "372": "Draschel", @@ -533,7 +596,6 @@ "377": "Regirock", "378": "Regice", "379": "Registeel", - "38": "Vulnona", "380": "Latias", "381": "Latios", "382": "Kyogre", @@ -544,7 +606,6 @@ "387": "Chelast", "388": "Chelcarain", "389": "Chelterrar", - "39": "Pummeluff", "390": "Panflam", "391": "Panpyro", "392": "Panferno", @@ -555,8 +616,6 @@ "397": "Staravia", "398": "Staraptor", "399": "Bidiza", - "4": "Glumanda", - "40": "Knuddeluff", "400": "Bidifas", "401": "Zirpurze", "402": "Zirpeise", @@ -567,7 +626,6 @@ "407": "Roserade", "408": "Koknodon", "409": "Rameidon", - "41": "Zubat", "410": "Schilterus", "411": "Bollterus", "412": "Burmy", @@ -578,7 +636,6 @@ "417": "Pachirisu", "418": "Bamelin", "419": "Bojelin", - "42": "Golbat", "420": "Kikugi", "421": "Kinoso", "422": "Schalellos", @@ -589,7 +646,6 @@ "427": "Haspiror", "428": "Schlapor", "429": "Traunmagil", - "43": "Myrapla", "430": "Kramshef", "431": "Charmian", "432": "Shnurgarst", @@ -600,7 +656,6 @@ "437": "Bronzong", "438": "Mobai", "439": "Pantimimi", - "44": "Duflor", "440": "Wonneira", "441": "Plaudagei", "442": "Kryppuk", @@ -611,7 +666,6 @@ "447": "Riolu", "448": "Lucario", "449": "Hippopotas", - "45": "Giflor", "450": "Hippoterus", "451": "Pionskora", "452": "Piondragi", @@ -622,7 +676,6 @@ "457": "Lumineon", "458": "Mantirps", "459": "Shnebedeck", - "46": "Paras", "460": "Rexblisar", "461": "Snibunna", "462": "Magnezone", @@ -633,7 +686,6 @@ "467": "Magbrant", "468": "Togekiss", "469": "Yanmega", - "47": "Parasek", "470": "Folipurba", "471": "Glaziola", "472": "Skorgro", @@ -644,7 +696,6 @@ "477": "Zwirrfinst", "478": "Frosdedje", "479": "Rotom", - "48": "Bluzuk", "480": "Selfe", "481": "Vesprit", "482": "Tobutz", @@ -655,7 +706,6 @@ "487": "Giratina", "488": "Cresselia", "489": "Phione", - "49": "Omot", "490": "Manaphy", "491": "Darkrai", "492": "Shaymin", @@ -666,8 +716,6 @@ "497": "Serpiroyal", "498": "Floink", "499": "Ferkokel", - "5": "Glutexo", - "50": "Digda", "500": "Flambirex", "501": "Ottaro", "502": "Zwottronin", @@ -678,7 +726,6 @@ "507": "Terribark", "508": "Bissbark", "509": "Felilou", - "51": "Digdri", "510": "Kleoparda", "511": "Vegimak", "512": "Vegichita", @@ -689,7 +736,6 @@ "517": "Somniam", "518": "Somnivora", "519": "Dusselgurr", - "52": "Mauzi", "520": "Navitaub", "521": "Fasasnob", "522": "Elezeba", @@ -700,7 +746,6 @@ "527": "Fleknoil", "528": "Fletiamo", "529": "Rotomurf", - "53": "Snobilikat", "530": "Stalobor", "531": "Ohrdoch", "532": "Praktibalk", @@ -711,7 +756,6 @@ "537": "Branawarz", "538": "Jiutesto", "539": "Karadonis", - "54": "Enton", "540": "Strawickl", "541": "Folikon", "542": "Matrifol", @@ -722,7 +766,6 @@ "547": "Elfun", "548": "Lilminip", "549": "Dressella", - "55": "Entoron", "550": "Barschuft", "551": "Ganovil", "552": "Rokkaiman", @@ -733,7 +776,6 @@ "557": "Lithomith", "558": "Castellith", "559": "Zurrokex", - "56": "Menki", "560": "Irokex", "561": "Symvolara", "562": "Makabaja", @@ -744,7 +786,6 @@ "567": "Aeropteryx", "568": "Unrat\u00fctox", "569": "Deponitox", - "57": "Rasaff", "570": "Zorua", "571": "Zoroark", "572": "Picochilla", @@ -755,7 +796,6 @@ "577": "Monozyto", "578": "Mitodos", "579": "Zytomega", - "58": "Fukano", "580": "Piccolente", "581": "Swaroness", "582": "Gelatini", @@ -766,7 +806,6 @@ "587": "Emolga", "588": "Laukaps", "589": "Cavalanzas", - "59": "Arkani", "590": "Tarnpignon", "591": "Hutsassa", "592": "Quabbel", @@ -777,8 +816,6 @@ "597": "Kastadur", "598": "Tentantel", "599": "Klikk", - "6": "Glurak", - "60": "Quapsel", "600": "Kliklak", "601": "Klikdiklak", "602": "Zapplardin", @@ -789,7 +826,6 @@ "607": "Lichtel", "608": "Laternecto", "609": "Skelabra", - "61": "Quaputzi", "610": "Milza", "611": "Sharfax", "612": "Maxax", @@ -800,7 +836,6 @@ "617": "Hydragil", "618": "Flunschlik", "619": "Lin-Fu", - "62": "Quappo", "620": "Wie-Shu", "621": "Shardrago", "622": "Golbit", @@ -811,7 +846,6 @@ "627": "Geronimatz", "628": "Washakwil", "629": "Skallyk", - "63": "Abra", "630": "Grypheldis", "631": "Furnifra\u00df", "632": "Fermicula", @@ -822,7 +856,6 @@ "637": "Ramoth", "638": "Kobalium", "639": "Terrakium", - "64": "Kadabra", "640": "Viridium", "641": "Boreos", "642": "Voltolos", @@ -833,7 +866,6 @@ "647": "Keldeo", "648": "Meloetta", "649": "Genesect", - "65": "Simsala", "650": "Igamaro", "651": "Igastarnish", "652": "Brigaron", @@ -844,7 +876,6 @@ "657": "Amphizel", "658": "Quajutsu", "659": "Scoppel", - "66": "Machollo", "660": "Grebbit", "661": "Dartiri", "662": "Dartignis", @@ -855,7 +886,6 @@ "667": "Leufeo", "668": "Pyroleo", "669": "Flab\u00e9b\u00e9", - "67": "Maschock", "670": "FLOETTE", "671": "Florges", "672": "M\u00e4hikel", @@ -866,7 +896,6 @@ "677": "Psiau", "678": "Psiaugon", "679": "Gramokles", - "68": "Machomei", "680": "Duokles", "681": "Durengard", "682": "Parfi", @@ -877,7 +906,6 @@ "687": "Calamanero", "688": "Bithora", "689": "Thanathora", - "69": "Knofensa", "690": "Algitt", "691": "Tandrak", "692": "Scampisto", @@ -888,8 +916,6 @@ "697": "Monargoras", "698": "Amarino", "699": "Amagarga", - "7": "Schiggy", - "70": "Ultrigaria", "700": "Feelinara", "701": "Resladero", "702": "DEDENNE", @@ -900,7 +926,6 @@ "707": "Clavion", "708": "Paragoni", "709": "Trombork", - "71": "Sarzenia", "710": "Irrbis", "711": "Pumpdjinn", "712": "Arktip", @@ -911,56 +936,50 @@ "717": "Yveltal", "718": "Zygarde", "719": "Diancie", - "72": "Tentacha", "720": "Hoopa", - "721": "Volcanion", - "73": "Tentoxa", - "74": "Kleinstein", - "75": "Georok", - "76": "Geowaz", - "77": "Ponita", - "78": "Gallopa", - "79": "Flegmon", - "8": "Schillok", - "80": "Lahmus", - "81": "Magnetilo", - "82": "Magneton", - "83": "Porenta", - "84": "Dodu", - "85": "Dodri", - "86": "Jurob", - "87": "Jugong", - "88": "Sleima", - "89": "Sleimok", - "9": "Turtok", - "90": "Muschas", - "91": "Austos", - "92": "Nebulak", - "93": "Alpollo", - "94": "Gengar", - "95": "Onix", - "96": "Traumato", - "97": "Hypno", - "98": "Krabby", - "99": "Kingler" + "721": "Volcanion" + }, + "sizes": { + "001": "winzig", + "002": "klein", + "003": "\u00dcblich", + "004": "gro\u00df", + "005": "riesig" }, "teams": { - "0": "Neutral", - "1": "Weisheit", - "2": "Wagemut", - "3": "Intuition" - }, + "000": "Neutral", + "001": "Weisheit", + "002": "Wagemut", + "003": "Intuition" + }, + "types": { + "001": "Normal", + "002": "Kampf", + "003": "Flug", + "004": "Gift", + "005": "Boden", + "006": "Stein", + "007": "K\u00e4fer", + "008": "Geist", + "009": "Stahl", + "010": "Feuer", + "011": "Wasser", + "012": "Pflanze", + "013": "Elektro", + "014": "Psycho", + "015": "Eis", + "016": "Drache", + "017": "Fee", + "018": "Unlicht" + }, "weather": { - "0": "Keiner", - "1": "klar", - "2": "Regen", - "3": "Teilweise wolkig", - "4": "Bew\u00F6lkt", - "5": "Windig", - "6": "Schnee", - "7": "Nebel" - }, - "misc": { - "boosted": "verstärktes" + "000": "Keiner", + "001": "klar", + "002": "Regen", + "003": "Teilweise wolkig", + "004": "Bew\u00f6lkt", + "005": "Windig", + "006": "Schnee", + "007": "Nebel" } -} +} \ No newline at end of file diff --git a/locales/en.json b/locales/en.json index af5583e64..3d3c00968 100644 --- a/locales/en.json +++ b/locales/en.json @@ -1,997 +1,1029 @@ { + "costumes": { + "025": { + "001": "Festive Hat", + "002": "Party Hat", + "003": "Ash Hat", + "004": "Witch Hat" + }, + "026": { + "001": "Festive Hat", + "002": "Party Hat", + "003": "Ash Hat", + "004": "Witch Hat" + }, + "172": { + "001": "Festive Hat", + "002": "Party Hat", + "003": "Ash Hat", + "004": "Witch Hat" + } + }, "forms": { "201": { - "1": "A", - "2": "B", - "3": "C", - "4": "D", - "5": "E", - "6": "F", - "7": "G", - "8": "H", - "9": "I", - "10": "J", - "11": "K", - "12": "L", - "13": "M", - "14": "N", - "15": "O", - "16": "P", - "17": "Q", - "18": "R", - "19": "S", - "20": "T", - "21": "U", - "22": "V", - "23": "W", - "24": "X", - "25": "Y", - "26": "Z", - "27": "!", - "28": "?" + "001": "A", + "002": "B", + "003": "C", + "004": "D", + "005": "E", + "006": "F", + "007": "G", + "008": "H", + "009": "I", + "010": "J", + "011": "K", + "012": "L", + "013": "M", + "014": "N", + "015": "O", + "016": "P", + "017": "Q", + "018": "R", + "019": "S", + "020": "T", + "021": "U", + "022": "V", + "023": "W", + "024": "X", + "025": "Y", + "026": "Z", + "027": "!", + "028": "?" + }, + "351": { + "029": "Normal", + "030": "Sunny", + "031": "Rainy", + "032": "Snowy" + }, + "386": { + "033": "Normal", + "034": "Attack", + "035": "Defense", + "036": "Speed" } - }, - "teams": { - "0": "Neutral", - "1": "Mystic", - "2": "Valor", - "3": "Instinct" - }, - "weather": { - "0": "None", - "1": "Clear", - "2": "Rain", - "3": "Partly Cloudy", - "4": "Cloudy", - "5": "Windy", - "6": "Snow", - "7": "Fog" - }, + }, "leaders": { - "0": "Professor Willow", - "1": "Blanche", - "2": "Candela", - "3": "Spark" - }, - "sizes": { - "1": "tiny", - "2": "small", - "3": "normal", - "4": "large", - "5": "big" - }, - "types": { - "1": "Normal", - "2": "Fighting", - "3": "Flying", - "4": "Poison", - "5": "Ground", - "6": "Rock", - "7": "Bug", - "8": "Ghost", - "9": "Steel", - "10": "Fire", - "11": "Water", - "12": "Grass", - "13": "Electric", - "14": "Psychic", - "15": "Ice", - "16": "Dragon", - "17": "Fairy", - "18": "Dark" - }, + "000": "Professor Willow", + "001": "Blanche", + "002": "Candela", + "003": "Spark" + }, + "misc": { + "boosted": "boosted" + }, "moves": { - "13": "Wrap", - "14": "Hyper Beam", - "16": "Dark Pulse", - "18": "Sludge", - "20": "Vice Grip", - "21": "Flame Wheel", - "22": "Megahorn", - "24": "Flamethrower", - "26": "Dig", - "28": "Cross Chop", - "30": "Psybeam", - "31": "Earthquake", - "32": "Stone Edge", - "33": "Ice Punch", - "34": "Heart Stamp", - "35": "Discharge", - "36": "Flash Cannon", - "38": "Drill Peck", - "39": "Ice Beam", - "40": "Blizzard", - "42": "Heat Wave", - "45": "Aerial Ace", - "46": "Drill Run", - "47": "Petal Blizzard", - "48": "Mega Drain", - "49": "Bug Buzz", - "50": "Poison Fang", - "51": "Night Slash", - "53": "Bubble Beam", - "54": "Submission", - "56": "Low Sweep", - "57": "Aqua Jet", - "58": "Aqua Tail", - "59": "Seed Bomb", - "60": "Psyshock", - "62": "Ancient Power", - "63": "Rock Tomb", - "64": "Rock Slide", - "65": "Power Gem", - "66": "Shadow Sneak", - "67": "Shadow Punch", - "69": "Ominous Wind", - "70": "Shadow Ball", - "72": "Magnet Bomb", - "74": "Iron Head", - "75": "Parabolic Charge", - "77": "Thunder Punch", - "78": "Thunder", - "79": "Thunderbolt", - "80": "Twister", - "82": "Dragon Pulse", - "83": "Dragon Claw", - "84": "Disarming Voice", - "85": "Draining Kiss", - "86": "Dazzling Gleam", - "87": "Moonblast", - "88": "Play Rough", - "89": "Cross Poison", - "90": "Sludge Bomb", - "91": "Sludge Wave", - "92": "Gunk Shot", - "94": "Bone Club", - "95": "Bulldoze", - "96": "Mud Bomb", - "99": "Signal Beam", - "100": "X-Scissor", - "101": "Flame Charge", - "102": "Flame Burst", - "103": "Fire Blast", - "104": "Brine", - "105": "Water Pulse", - "106": "Scald", - "107": "Hydro Pump", - "108": "Psychic", - "109": "Psystrike", - "111": "Icy Wind", - "114": "Giga Drain", - "115": "Fire Punch", - "116": "Solar Beam", - "117": "Leaf Blade", - "118": "Power Whip", - "121": "Air Cutter", - "122": "Hurricane", - "123": "Brick Break", - "125": "Swift", - "126": "Horn Attack", - "127": "Stomp", - "129": "Hyper Fang", - "131": "Body Slam", - "132": "Rest", - "133": "Struggle", - "134": "Scald (Blastoise)", - "135": "Hydro Pump (Blastoise)", - "136": "Wrap (Green)", - "137": "Wrap (Pink)", - "200": "Fury Cutter", - "201": "Bug Bite", - "202": "Bite", - "203": "Sucker Punch", - "204": "Dragon Breath", - "205": "Thunder Shock", - "206": "Spark", - "207": "Low Kick", - "208": "Karate Chop", - "209": "Ember", - "210": "Wing Attack", - "211": "Peck", - "212": "Lick", - "213": "Shadow Claw", - "214": "Vine Whip", - "215": "Razor Leaf", - "216": "Mud Shot", - "217": "Ice Shard", - "218": "Frost Breath", - "219": "Quick Attack", - "220": "Scratch", - "221": "Tackle", - "222": "Pound", - "223": "Cut", - "224": "Poison Jab", - "225": "Acid", - "226": "Psycho Cut", - "227": "Rock Throw", - "228": "Metal Claw", - "229": "Bullet Punch", - "230": "Water Gun", - "231": "Splash", - "233": "Mud Slap", - "234": "Zen Headbutt", - "235": "Confusion", - "236": "Poison Sting", - "237": "Bubble", - "238": "Feint Attack", - "239": "Steel Wing", - "240": "Fire Fang", - "241": "Rock Smash", - "242": "Transform", - "243": "Counter", - "244": "Powder Snow", - "245": "Close Combat", - "246": "Dynamic Punch", - "247": "Focus Blast", - "248": "Aurora Beam", - "249": "Charge Beam", - "250": "Volt Switch", - "251": "Wild Charge", - "252": "Zap Cannon", - "253": "Dragon Tail", - "254": "Avalanche", - "255": "Air Slash", - "256": "Brave Bird", - "257": "Sky Attack", - "258": "Sand Tomb", - "259": "Rock Blast", - "260": "Infestation", - "261": "Struggle Bug", - "262": "Silver Wind", - "263": "Astonish", - "264": "Hex", - "265": "Night Shade", - "266": "Iron Tail", - "267": "Gyro Ball", - "268": "Heavy Slam", - "269": "Fire Spin", - "270": "Overheat", - "271": "Bullet Seed", - "272": "Grass Knot", - "273": "Energy Ball", - "274": "Extrasensory", - "275": "Future Sight", - "276": "Mirror Coat", - "277": "Outrage", - "278": "Snarl", - "279": "Crunch", - "280": "Foul Play", - "281": "Hidden Power", - "282": "Take Down", - "283": "Waterfall", - "284": "Surf", - "285": "Draco Meteor", - "286": "Doom Desire", - "287": "Yawn", - "288": "Psycho Boost", - "289": "Origin Pulse", - "290": "Precipice Blades", + "013": "Wrap", + "014": "Hyper Beam", + "016": "Dark Pulse", + "018": "Sludge", + "020": "Vice Grip", + "021": "Flame Wheel", + "022": "Megahorn", + "024": "Flamethrower", + "026": "Dig", + "028": "Cross Chop", + "030": "Psybeam", + "031": "Earthquake", + "032": "Stone Edge", + "033": "Ice Punch", + "034": "Heart Stamp", + "035": "Discharge", + "036": "Flash Cannon", + "038": "Drill Peck", + "039": "Ice Beam", + "040": "Blizzard", + "042": "Heat Wave", + "045": "Aerial Ace", + "046": "Drill Run", + "047": "Petal Blizzard", + "048": "Mega Drain", + "049": "Bug Buzz", + "050": "Poison Fang", + "051": "Night Slash", + "053": "Bubble Beam", + "054": "Submission", + "056": "Low Sweep", + "057": "Aqua Jet", + "058": "Aqua Tail", + "059": "Seed Bomb", + "060": "Psyshock", + "062": "Ancient Power", + "063": "Rock Tomb", + "064": "Rock Slide", + "065": "Power Gem", + "066": "Shadow Sneak", + "067": "Shadow Punch", + "069": "Ominous Wind", + "070": "Shadow Ball", + "072": "Magnet Bomb", + "074": "Iron Head", + "075": "Parabolic Charge", + "077": "Thunder Punch", + "078": "Thunder", + "079": "Thunderbolt", + "080": "Twister", + "082": "Dragon Pulse", + "083": "Dragon Claw", + "084": "Disarming Voice", + "085": "Draining Kiss", + "086": "Dazzling Gleam", + "087": "Moonblast", + "088": "Play Rough", + "089": "Cross Poison", + "090": "Sludge Bomb", + "091": "Sludge Wave", + "092": "Gunk Shot", + "094": "Bone Club", + "095": "Bulldoze", + "096": "Mud Bomb", + "099": "Signal Beam", + "100": "X-Scissor", + "101": "Flame Charge", + "102": "Flame Burst", + "103": "Fire Blast", + "104": "Brine", + "105": "Water Pulse", + "106": "Scald", + "107": "Hydro Pump", + "108": "Psychic", + "109": "Psystrike", + "111": "Icy Wind", + "114": "Giga Drain", + "115": "Fire Punch", + "116": "Solar Beam", + "117": "Leaf Blade", + "118": "Power Whip", + "121": "Air Cutter", + "122": "Hurricane", + "123": "Brick Break", + "125": "Swift", + "126": "Horn Attack", + "127": "Stomp", + "129": "Hyper Fang", + "131": "Body Slam", + "132": "Rest", + "133": "Struggle", + "134": "Scald (Blastoise)", + "135": "Hydro Pump (Blastoise)", + "136": "Wrap (Green)", + "137": "Wrap (Pink)", + "200": "Fury Cutter", + "201": "Bug Bite", + "202": "Bite", + "203": "Sucker Punch", + "204": "Dragon Breath", + "205": "Thunder Shock", + "206": "Spark", + "207": "Low Kick", + "208": "Karate Chop", + "209": "Ember", + "210": "Wing Attack", + "211": "Peck", + "212": "Lick", + "213": "Shadow Claw", + "214": "Vine Whip", + "215": "Razor Leaf", + "216": "Mud Shot", + "217": "Ice Shard", + "218": "Frost Breath", + "219": "Quick Attack", + "220": "Scratch", + "221": "Tackle", + "222": "Pound", + "223": "Cut", + "224": "Poison Jab", + "225": "Acid", + "226": "Psycho Cut", + "227": "Rock Throw", + "228": "Metal Claw", + "229": "Bullet Punch", + "230": "Water Gun", + "231": "Splash", + "233": "Mud Slap", + "234": "Zen Headbutt", + "235": "Confusion", + "236": "Poison Sting", + "237": "Bubble", + "238": "Feint Attack", + "239": "Steel Wing", + "240": "Fire Fang", + "241": "Rock Smash", + "242": "Transform", + "243": "Counter", + "244": "Powder Snow", + "245": "Close Combat", + "246": "Dynamic Punch", + "247": "Focus Blast", + "248": "Aurora Beam", + "249": "Charge Beam", + "250": "Volt Switch", + "251": "Wild Charge", + "252": "Zap Cannon", + "253": "Dragon Tail", + "254": "Avalanche", + "255": "Air Slash", + "256": "Brave Bird", + "257": "Sky Attack", + "258": "Sand Tomb", + "259": "Rock Blast", + "260": "Infestation", + "261": "Struggle Bug", + "262": "Silver Wind", + "263": "Astonish", + "264": "Hex", + "265": "Night Shade", + "266": "Iron Tail", + "267": "Gyro Ball", + "268": "Heavy Slam", + "269": "Fire Spin", + "270": "Overheat", + "271": "Bullet Seed", + "272": "Grass Knot", + "273": "Energy Ball", + "274": "Extrasensory", + "275": "Future Sight", + "276": "Mirror Coat", + "277": "Outrage", + "278": "Snarl", + "279": "Crunch", + "280": "Foul Play", + "281": "Hidden Power", + "282": "Take Down", + "283": "Waterfall", + "284": "Surf", + "285": "Draco Meteor", + "286": "Doom Desire", + "287": "Yawn", + "288": "Psycho Boost", + "289": "Origin Pulse", + "290": "Precipice Blades", "291": "Present" - }, + }, "pokemon": { - "1": "Bulbasaur", - "2": "Ivysaur", - "3": "Venusaur", - "4": "Charmander", - "5": "Charmeleon", - "6": "Charizard", - "7": "Squirtle", - "8": "Wartortle", - "9": "Blastoise", - "10": "Caterpie", - "11": "Metapod", - "12": "Butterfree", - "13": "Weedle", - "14": "Kakuna", - "15": "Beedrill", - "16": "Pidgey", - "17": "Pidgeotto", - "18": "Pidgeot", - "19": "Rattata", - "20": "Raticate", - "21": "Spearow", - "22": "Fearow", - "23": "Ekans", - "24": "Arbok", - "25": "Pikachu", - "26": "Raichu", - "27": "Sandshrew", - "28": "Sandslash", - "29": "Nidoran♀", - "30": "Nidorina", - "31": "Nidoqueen", - "32": "Nidoran♂", - "33": "Nidorino", - "34": "Nidoking", - "35": "Clefairy", - "36": "Clefable", - "37": "Vulpix", - "38": "Ninetales", - "39": "Jigglypuff", - "40": "Wigglytuff", - "41": "Zubat", - "42": "Golbat", - "43": "Oddish", - "44": "Gloom", - "45": "Vileplume", - "46": "Paras", - "47": "Parasect", - "48": "Venonat", - "49": "Venomoth", - "50": "Diglett", - "51": "Dugtrio", - "52": "Meowth", - "53": "Persian", - "54": "Psyduck", - "55": "Golduck", - "56": "Mankey", - "57": "Primeape", - "58": "Growlithe", - "59": "Arcanine", - "60": "Poliwag", - "61": "Poliwhirl", - "62": "Poliwrath", - "63": "Abra", - "64": "Kadabra", - "65": "Alakazam", - "66": "Machop", - "67": "Machoke", - "68": "Machamp", - "69": "Bellsprout", - "70": "Weepinbell", - "71": "Victreebel", - "72": "Tentacool", - "73": "Tentacruel", - "74": "Geodude", - "75": "Graveler", - "76": "Golem", - "77": "Ponyta", - "78": "Rapidash", - "79": "Slowpoke", - "80": "Slowbro", - "81": "Magnemite", - "82": "Magneton", - "83": "Farfetch'd", - "84": "Doduo", - "85": "Dodrio", - "86": "Seel", - "87": "Dewgong", - "88": "Grimer", - "89": "Muk", - "90": "Shellder", - "91": "Cloyster", - "92": "Gastly", - "93": "Haunter", - "94": "Gengar", - "95": "Onix", - "96": "Drowzee", - "97": "Hypno", - "98": "Krabby", - "99": "Kingler", - "100": "Voltorb", - "101": "Electrode", - "102": "Exeggcute", - "103": "Exeggutor", - "104": "Cubone", - "105": "Marowak", - "106": "Hitmonlee", - "107": "Hitmonchan", - "108": "Lickitung", - "109": "Koffing", - "110": "Weezing", - "111": "Rhyhorn", - "112": "Rhydon", - "113": "Chansey", - "114": "Tangela", - "115": "Kangaskhan", - "116": "Horsea", - "117": "Seadra", - "118": "Goldeen", - "119": "Seaking", - "120": "Staryu", - "121": "Starmie", - "122": "Mr. Mime", - "123": "Scyther", - "124": "Jynx", - "125": "Electabuzz", - "126": "Magmar", - "127": "Pinsir", - "128": "Tauros", - "129": "Magikarp", - "130": "Gyarados", - "131": "Lapras", - "132": "Ditto", - "133": "Eevee", - "134": "Vaporeon", - "135": "Jolteon", - "136": "Flareon", - "137": "Porygon", - "138": "Omanyte", - "139": "Omastar", - "140": "Kabuto", - "141": "Kabutops", - "142": "Aerodactyl", - "143": "Snorlax", - "144": "Articuno", - "145": "Zapdos", - "146": "Moltres", - "147": "Dratini", - "148": "Dragonair", - "149": "Dragonite", - "150": "Mewtwo", - "151": "Mew", - "152": "Chikorita", - "153": "Bayleef", - "154": "Meganium", - "155": "Cyndaquil", - "156": "Quilava", - "157": "Typhlosion", - "158": "Totodile", - "159": "Croconaw", - "160": "Feraligatr", - "161": "Sentret", - "162": "Furret", - "163": "Hoothoot", - "164": "Noctowl", - "165": "Ledyba", - "166": "Ledian", - "167": "Spinarak", - "168": "Ariados", - "169": "Crobat", - "170": "Chinchou", - "171": "Lanturn", - "172": "Pichu", - "173": "Cleffa", - "174": "Igglybuff", - "175": "Togepi", - "176": "Togetic", - "177": "Natu", - "178": "Xatu", - "179": "Mareep", - "180": "Flaaffy", - "181": "Ampharos", - "182": "Bellossom", - "183": "Marill", - "184": "Azumarill", - "185": "Sudowoodo", - "186": "Politoed", - "187": "Hoppip", - "188": "Skiploom", - "189": "Jumpluff", - "190": "Aipom", - "191": "Sunkern", - "192": "Sunflora", - "193": "Yanma", - "194": "Wooper", - "195": "Quagsire", - "196": "Espeon", - "197": "Umbreon", - "198": "Murkrow", - "199": "Slowking", - "200": "Misdreavus", - "201": "Unown", - "202": "Wobbuffet", - "203": "Girafarig", - "204": "Pineco", - "205": "Forretress", - "206": "Dunsparce", - "207": "Gligar", - "208": "Steelix", - "209": "Snubbull", - "210": "Granbull", - "211": "Qwilfish", - "212": "Scizor", - "213": "Shuckle", - "214": "Heracross", - "215": "Sneasel", - "216": "Teddiursa", - "217": "Ursaring", - "218": "Slugma", - "219": "Magcargo", - "220": "Swinub", - "221": "Piloswine", - "222": "Corsola", - "223": "Remoraid", - "224": "Octillery", - "225": "Delibird", - "226": "Mantine", - "227": "Skarmory", - "228": "Houndour", - "229": "Houndoom", - "230": "Kingdra", - "231": "Phanpy", - "232": "Donphan", - "233": "Porygon2", - "234": "Stantler", - "235": "Smeargle", - "236": "Tyrogue", - "237": "Hitmontop", - "238": "Smoochum", - "239": "Elekid", - "240": "Magby", - "241": "Miltank", - "242": "Blissey", - "243": "Raikou", - "244": "Entei", - "245": "Suicune", - "246": "Larvitar", - "247": "Pupitar", - "248": "Tyranitar", - "249": "Lugia", - "250": "Ho-Oh", - "251": "Celebi", - "252": "Treecko", - "253": "Grovyle", - "254": "Sceptile", - "255": "Torchic", - "256": "Combusken", - "257": "Blaziken", - "258": "Mudkip", - "259": "Marshtomp", - "260": "Swampert", - "261": "Poochyena", - "262": "Mightyena", - "263": "Zigzagoon", - "264": "Linoone", - "265": "Wurmple", - "266": "Silcoon", - "267": "Beautifly", - "268": "Cascoon", - "269": "Dustox", - "270": "Lotad", - "271": "Lombre", - "272": "Ludicolo", - "273": "Seedot", - "274": "Nuzleaf", - "275": "Shiftry", - "276": "Taillow", - "277": "Swellow", - "278": "Wingull", - "279": "Pelipper", - "280": "Ralts", - "281": "Kirlia", - "282": "Gardevoir", - "283": "Surskit", - "284": "Masquerain", - "285": "Shroomish", - "286": "Breloom", - "287": "Slakoth", - "288": "Vigoroth", - "289": "Slaking", - "290": "Nincada", - "291": "Ninjask", - "292": "Shedinja", - "293": "Whismur", - "294": "Loudred", - "295": "Exploud", - "296": "Makuhita", - "297": "Hariyama", - "298": "Azurill", - "299": "Nosepass", - "300": "Skitty", - "301": "Delcatty", - "302": "Sableye", - "303": "Mawile", - "304": "Aron", - "305": "Lairon", - "306": "Aggron", - "307": "Meditite", - "308": "Medicham", - "309": "Electrike", - "310": "Manectric", - "311": "Plusle", - "312": "Minun", - "313": "Volbeat", - "314": "Illumise", - "315": "Roselia", - "316": "Gulpin", - "317": "Swalot", - "318": "Carvanha", - "319": "Sharpedo", - "320": "Wailmer", - "321": "Wailord", - "322": "Numel", - "323": "Camerupt", - "324": "Torkoal", - "325": "Spoink", - "326": "Grumpig", - "327": "Spinda", - "328": "Trapinch", - "329": "Vibrava", - "330": "Flygon", - "331": "Cacnea", - "332": "Cacturne", - "333": "Swablu", - "334": "Altaria", - "335": "Zangoose", - "336": "Seviper", - "337": "Lunatone", - "338": "Solrock", - "339": "Barboach", - "340": "Whiscash", - "341": "Corphish", - "342": "Crawdaunt", - "343": "Baltoy", - "344": "Claydol", - "345": "Lileep", - "346": "Cradily", - "347": "Anorith", - "348": "Armaldo", - "349": "Feebas", - "350": "Milotic", - "351": "Castform", - "352": "Kecleon", - "353": "Shuppet", - "354": "Banette", - "355": "Duskull", - "356": "Dusclops", - "357": "Tropius", - "358": "Chimecho", - "359": "Absol", - "360": "Wynaut", - "361": "Snorunt", - "362": "Glalie", - "363": "Spheal", - "364": "Sealeo", - "365": "Walrein", - "366": "Clamperl", - "367": "Huntail", - "368": "Gorebyss", - "369": "Relicanth", - "370": "Luvdisc", - "371": "Bagon", - "372": "Shelgon", - "373": "Salamence", - "374": "Beldum", - "375": "Metang", - "376": "Metagross", - "377": "Regirock", - "378": "Regice", - "379": "Registeel", - "380": "Latias", - "381": "Latios", - "382": "Kyogre", - "383": "Groudon", - "384": "Rayquaza", - "385": "Jirachi", - "386": "Deoxys", - "387": "Turtwig", - "388": "Grotle", - "389": "Torterra", - "390": "Chimchar", - "391": "Monferno", - "392": "Infernape", - "393": "Piplup", - "394": "Prinplup", - "395": "Empoleon", - "396": "Starly", - "397": "Staravia", - "398": "Staraptor", - "399": "Bidoof", - "400": "Bibarel", - "401": "Kricketot", - "402": "Kricketune", - "403": "Shinx", - "404": "Luxio", - "405": "Luxray", - "406": "Budew", - "407": "Roserade", - "408": "Cranidos", - "409": "Rampardos", - "410": "Shieldon", - "411": "Bastiodon", - "412": "Burmy", - "413": "Wormadam", - "414": "Mothim", - "415": "Combee", - "416": "Vespiquen", - "417": "Pachirisu", - "418": "Buizel", - "419": "Floatzel", - "420": "Cherubi", - "421": "Cherrim", - "422": "Shellos", - "423": "Gastrodon", - "424": "Ambipom", - "425": "Drifloon", - "426": "Drifblim", - "427": "Buneary", - "428": "Lopunny", - "429": "Mismagius", - "430": "Honchkrow", - "431": "Glameow", - "432": "Purugly", - "433": "Chingling", - "434": "Stunky", - "435": "Skuntank", - "436": "Bronzor", - "437": "Bronzong", - "438": "Bonsly", - "439": "Mime Jr.", - "440": "Happiny", - "441": "Chatot", - "442": "Spiritomb", - "443": "Gible", - "444": "Gabite", - "445": "Garchomp", - "446": "Munchlax", - "447": "Riolu", - "448": "Lucario", - "449": "Hippopotas", - "450": "Hippowdon", - "451": "Skorupi", - "452": "Drapion", - "453": "Croagunk", - "454": "Toxicroak", - "455": "Carnivine", - "456": "Finneon", - "457": "Lumineon", - "458": "Mantyke", - "459": "Snover", - "460": "Abomasnow", - "461": "Weavile", - "462": "Magnezone", - "463": "Lickilicky", - "464": "Rhyperior", - "465": "Tangrowth", - "466": "Electivire", - "467": "Magmortar", - "468": "Togekiss", - "469": "Yanmega", - "470": "Leafeon", - "471": "Glaceon", - "472": "Gliscor", - "473": "Mamoswine", - "474": "Porygon-Z", - "475": "Gallade", - "476": "Probopass", - "477": "Dusknoir", - "478": "Froslass", - "479": "Rotom", - "480": "Uxie", - "481": "Mesprit", - "482": "Azelf", - "483": "Dialga", - "484": "Palkia", - "485": "Heatran", - "486": "Regigigas", - "487": "Giratina", - "488": "Cresselia", - "489": "Phione", - "490": "Manaphy", - "491": "Darkrai", - "492": "Shaymin", - "493": "Arceus", - "494": "Victini", - "495": "Snivy", - "496": "Servine", - "497": "Serperior", - "498": "Tepig", - "499": "Pignite", - "500": "Emboar", - "501": "Oshawott", - "502": "Dewott", - "503": "Samurott", - "504": "Patrat", - "505": "Watchog", - "506": "Lillipup", - "507": "Herdier", - "508": "Stoutland", - "509": "Purrloin", - "510": "Liepard", - "511": "Pansage", - "512": "Simisage", - "513": "Pansear", - "514": "Simisear", - "515": "Panpour", - "516": "Simipour", - "517": "Munna", - "518": "Musharna", - "519": "Pidove", - "520": "Tranquill", - "521": "Unfezant", - "522": "Blitzle", - "523": "Zebstrika", - "524": "Roggenrola", - "525": "Boldore", - "526": "Gigalith", - "527": "Woobat", - "528": "Swoobat", - "529": "Drilbur", - "530": "Excadrill", - "531": "Audino", - "532": "Timburr", - "533": "Gurdurr", - "534": "Conkeldurr", - "535": "Tympole", - "536": "Palpitoad", - "537": "Seismitoad", - "538": "Throh", - "539": "Sawk", - "540": "Sewaddle", - "541": "Swadloon", - "542": "Leavanny", - "543": "Venipede", - "544": "Whirlipede", - "545": "Scolipede", - "546": "Cottonee", - "547": "Whimsicott", - "548": "Petilil", - "549": "Lilligant", - "550": "Basculin", - "551": "Sandile", - "552": "Krokorok", - "553": "Krookodile", - "554": "Darumaka", - "555": "Darmanitan", - "556": "Maractus", - "557": "Dwebble", - "558": "Crustle", - "559": "Scraggy", - "560": "Scrafty", - "561": "Sigilyph", - "562": "Yamask", - "563": "Cofagrigus", - "564": "Tirtouga", - "565": "Carracosta", - "566": "Archen", - "567": "Archeops", - "568": "Trubbish", - "569": "Garbodor", - "570": "Zorua", - "571": "Zoroark", - "572": "Minccino", - "573": "Cinccino", - "574": "Gothita", - "575": "Gothorita", - "576": "Gothitelle", - "577": "Solosis", - "578": "Duosion", - "579": "Reuniclus", - "580": "Ducklett", - "581": "Swanna", - "582": "Vanillite", - "583": "Vanillish", - "584": "Vanilluxe", - "585": "Deerling", - "586": "Sawsbuck", - "587": "Emolga", - "588": "Karrablast", - "589": "Escavalier", - "590": "Foongus", - "591": "Amoonguss", - "592": "Frillish", - "593": "Jellicent", - "594": "Alomomola", - "595": "Joltik", - "596": "Galvantula", - "597": "Ferroseed", - "598": "Ferrothorn", - "599": "Klink", - "600": "Klang", - "601": "Klinklang", - "602": "Tynamo", - "603": "Eelektrik", - "604": "Eelektross", - "605": "Elgyem", - "606": "Beheeyem", - "607": "Litwick", - "608": "Lampent", - "609": "Chandelure", - "610": "Axew", - "611": "Fraxure", - "612": "Haxorus", - "613": "Cubchoo", - "614": "Beartic", - "615": "Cryogonal", - "616": "Shelmet", - "617": "Accelgor", - "618": "Stunfisk", - "619": "Mienfoo", - "620": "Mienshao", - "621": "Druddigon", - "622": "Golett", - "623": "Golurk", - "624": "Pawniard", - "625": "Bisharp", - "626": "Bouffalant", - "627": "Rufflet", - "628": "Braviary", - "629": "Vullaby", - "630": "Mandibuzz", - "631": "Heatmor", - "632": "Durant", - "633": "Deino", - "634": "Zweilous", - "635": "Hydreigon", - "636": "Larvesta", - "637": "Volcarona", - "638": "Cobalion", - "639": "Terrakion", - "640": "Virizion", - "641": "Tornadus", - "642": "Thundurus", - "643": "Reshiram", - "644": "Zekrom", - "645": "Landorus", - "646": "Kyurem", - "647": "Keldeo", - "648": "Meloetta", - "649": "Genesect", - "650": "Chespin", - "651": "Quilladin", - "652": "Chesnaught", - "653": "Fennekin", - "654": "Braixen", - "655": "Delphox", - "656": "Froakie", - "657": "Frogadier", - "658": "Greninja", - "659": "Bunnelby", - "660": "Diggersby", - "661": "Fletchling", - "662": "Fletchinder", - "663": "Talonflame", - "664": "Scatterbug", - "665": "Spewpa", - "666": "Vivillon", - "667": "Litleo", - "668": "Pyroar", - "669": "Flab\u00E9b\u00E9", - "670": "Floette", - "671": "Florges", - "672": "Skiddo", - "673": "Gogoat", - "674": "Pancham", - "675": "Pangoro", - "676": "Furfrou", - "677": "Espurr", - "678": "Meowstic", - "679": "Honedge", - "680": "Doublade", - "681": "Aegislash", - "682": "Spritzee", - "683": "Aromatisse", - "684": "Swirlix", - "685": "Slurpuff", - "686": "Inkay", - "687": "Malamar", - "688": "Binacle", - "689": "Barbaracle", - "690": "Skrelp", - "691": "Dragalge", - "692": "Clauncher", - "693": "Clawitzer", - "694": "Helioptile", - "695": "Heliolisk", - "696": "Tyrunt", - "697": "Tyrantrum", - "698": "Amaura", - "699": "Aurorus", - "700": "Sylveon", - "701": "Hawlucha", - "702": "Dedenne", - "703": "Carbink", - "704": "Goomy", - "705": "Sliggoo", - "706": "Goodra", - "707": "Klefki", - "708": "Phantump", - "709": "Trevenant", - "710": "Pumpkaboo", - "711": "Gourgeist", - "712": "Bergmite", - "713": "Avalugg", - "714": "Noibat", - "715": "Noivern", - "716": "Xerneas", - "717": "Yveltal", - "718": "Zygarde", - "719": "Diancie", - "720": "Hoopa", + "001": "Bulbasaur", + "002": "Ivysaur", + "003": "Venusaur", + "004": "Charmander", + "005": "Charmeleon", + "006": "Charizard", + "007": "Squirtle", + "008": "Wartortle", + "009": "Blastoise", + "010": "Caterpie", + "011": "Metapod", + "012": "Butterfree", + "013": "Weedle", + "014": "Kakuna", + "015": "Beedrill", + "016": "Pidgey", + "017": "Pidgeotto", + "018": "Pidgeot", + "019": "Rattata", + "020": "Raticate", + "021": "Spearow", + "022": "Fearow", + "023": "Ekans", + "024": "Arbok", + "025": "Pikachu", + "026": "Raichu", + "027": "Sandshrew", + "028": "Sandslash", + "029": "Nidoran\u2640", + "030": "Nidorina", + "031": "Nidoqueen", + "032": "Nidoran\u2642", + "033": "Nidorino", + "034": "Nidoking", + "035": "Clefairy", + "036": "Clefable", + "037": "Vulpix", + "038": "Ninetales", + "039": "Jigglypuff", + "040": "Wigglytuff", + "041": "Zubat", + "042": "Golbat", + "043": "Oddish", + "044": "Gloom", + "045": "Vileplume", + "046": "Paras", + "047": "Parasect", + "048": "Venonat", + "049": "Venomoth", + "050": "Diglett", + "051": "Dugtrio", + "052": "Meowth", + "053": "Persian", + "054": "Psyduck", + "055": "Golduck", + "056": "Mankey", + "057": "Primeape", + "058": "Growlithe", + "059": "Arcanine", + "060": "Poliwag", + "061": "Poliwhirl", + "062": "Poliwrath", + "063": "Abra", + "064": "Kadabra", + "065": "Alakazam", + "066": "Machop", + "067": "Machoke", + "068": "Machamp", + "069": "Bellsprout", + "070": "Weepinbell", + "071": "Victreebel", + "072": "Tentacool", + "073": "Tentacruel", + "074": "Geodude", + "075": "Graveler", + "076": "Golem", + "077": "Ponyta", + "078": "Rapidash", + "079": "Slowpoke", + "080": "Slowbro", + "081": "Magnemite", + "082": "Magneton", + "083": "Farfetch'd", + "084": "Doduo", + "085": "Dodrio", + "086": "Seel", + "087": "Dewgong", + "088": "Grimer", + "089": "Muk", + "090": "Shellder", + "091": "Cloyster", + "092": "Gastly", + "093": "Haunter", + "094": "Gengar", + "095": "Onix", + "096": "Drowzee", + "097": "Hypno", + "098": "Krabby", + "099": "Kingler", + "100": "Voltorb", + "101": "Electrode", + "102": "Exeggcute", + "103": "Exeggutor", + "104": "Cubone", + "105": "Marowak", + "106": "Hitmonlee", + "107": "Hitmonchan", + "108": "Lickitung", + "109": "Koffing", + "110": "Weezing", + "111": "Rhyhorn", + "112": "Rhydon", + "113": "Chansey", + "114": "Tangela", + "115": "Kangaskhan", + "116": "Horsea", + "117": "Seadra", + "118": "Goldeen", + "119": "Seaking", + "120": "Staryu", + "121": "Starmie", + "122": "Mr. Mime", + "123": "Scyther", + "124": "Jynx", + "125": "Electabuzz", + "126": "Magmar", + "127": "Pinsir", + "128": "Tauros", + "129": "Magikarp", + "130": "Gyarados", + "131": "Lapras", + "132": "Ditto", + "133": "Eevee", + "134": "Vaporeon", + "135": "Jolteon", + "136": "Flareon", + "137": "Porygon", + "138": "Omanyte", + "139": "Omastar", + "140": "Kabuto", + "141": "Kabutops", + "142": "Aerodactyl", + "143": "Snorlax", + "144": "Articuno", + "145": "Zapdos", + "146": "Moltres", + "147": "Dratini", + "148": "Dragonair", + "149": "Dragonite", + "150": "Mewtwo", + "151": "Mew", + "152": "Chikorita", + "153": "Bayleef", + "154": "Meganium", + "155": "Cyndaquil", + "156": "Quilava", + "157": "Typhlosion", + "158": "Totodile", + "159": "Croconaw", + "160": "Feraligatr", + "161": "Sentret", + "162": "Furret", + "163": "Hoothoot", + "164": "Noctowl", + "165": "Ledyba", + "166": "Ledian", + "167": "Spinarak", + "168": "Ariados", + "169": "Crobat", + "170": "Chinchou", + "171": "Lanturn", + "172": "Pichu", + "173": "Cleffa", + "174": "Igglybuff", + "175": "Togepi", + "176": "Togetic", + "177": "Natu", + "178": "Xatu", + "179": "Mareep", + "180": "Flaaffy", + "181": "Ampharos", + "182": "Bellossom", + "183": "Marill", + "184": "Azumarill", + "185": "Sudowoodo", + "186": "Politoed", + "187": "Hoppip", + "188": "Skiploom", + "189": "Jumpluff", + "190": "Aipom", + "191": "Sunkern", + "192": "Sunflora", + "193": "Yanma", + "194": "Wooper", + "195": "Quagsire", + "196": "Espeon", + "197": "Umbreon", + "198": "Murkrow", + "199": "Slowking", + "200": "Misdreavus", + "201": "Unown", + "202": "Wobbuffet", + "203": "Girafarig", + "204": "Pineco", + "205": "Forretress", + "206": "Dunsparce", + "207": "Gligar", + "208": "Steelix", + "209": "Snubbull", + "210": "Granbull", + "211": "Qwilfish", + "212": "Scizor", + "213": "Shuckle", + "214": "Heracross", + "215": "Sneasel", + "216": "Teddiursa", + "217": "Ursaring", + "218": "Slugma", + "219": "Magcargo", + "220": "Swinub", + "221": "Piloswine", + "222": "Corsola", + "223": "Remoraid", + "224": "Octillery", + "225": "Delibird", + "226": "Mantine", + "227": "Skarmory", + "228": "Houndour", + "229": "Houndoom", + "230": "Kingdra", + "231": "Phanpy", + "232": "Donphan", + "233": "Porygon2", + "234": "Stantler", + "235": "Smeargle", + "236": "Tyrogue", + "237": "Hitmontop", + "238": "Smoochum", + "239": "Elekid", + "240": "Magby", + "241": "Miltank", + "242": "Blissey", + "243": "Raikou", + "244": "Entei", + "245": "Suicune", + "246": "Larvitar", + "247": "Pupitar", + "248": "Tyranitar", + "249": "Lugia", + "250": "Ho-Oh", + "251": "Celebi", + "252": "Treecko", + "253": "Grovyle", + "254": "Sceptile", + "255": "Torchic", + "256": "Combusken", + "257": "Blaziken", + "258": "Mudkip", + "259": "Marshtomp", + "260": "Swampert", + "261": "Poochyena", + "262": "Mightyena", + "263": "Zigzagoon", + "264": "Linoone", + "265": "Wurmple", + "266": "Silcoon", + "267": "Beautifly", + "268": "Cascoon", + "269": "Dustox", + "270": "Lotad", + "271": "Lombre", + "272": "Ludicolo", + "273": "Seedot", + "274": "Nuzleaf", + "275": "Shiftry", + "276": "Taillow", + "277": "Swellow", + "278": "Wingull", + "279": "Pelipper", + "280": "Ralts", + "281": "Kirlia", + "282": "Gardevoir", + "283": "Surskit", + "284": "Masquerain", + "285": "Shroomish", + "286": "Breloom", + "287": "Slakoth", + "288": "Vigoroth", + "289": "Slaking", + "290": "Nincada", + "291": "Ninjask", + "292": "Shedinja", + "293": "Whismur", + "294": "Loudred", + "295": "Exploud", + "296": "Makuhita", + "297": "Hariyama", + "298": "Azurill", + "299": "Nosepass", + "300": "Skitty", + "301": "Delcatty", + "302": "Sableye", + "303": "Mawile", + "304": "Aron", + "305": "Lairon", + "306": "Aggron", + "307": "Meditite", + "308": "Medicham", + "309": "Electrike", + "310": "Manectric", + "311": "Plusle", + "312": "Minun", + "313": "Volbeat", + "314": "Illumise", + "315": "Roselia", + "316": "Gulpin", + "317": "Swalot", + "318": "Carvanha", + "319": "Sharpedo", + "320": "Wailmer", + "321": "Wailord", + "322": "Numel", + "323": "Camerupt", + "324": "Torkoal", + "325": "Spoink", + "326": "Grumpig", + "327": "Spinda", + "328": "Trapinch", + "329": "Vibrava", + "330": "Flygon", + "331": "Cacnea", + "332": "Cacturne", + "333": "Swablu", + "334": "Altaria", + "335": "Zangoose", + "336": "Seviper", + "337": "Lunatone", + "338": "Solrock", + "339": "Barboach", + "340": "Whiscash", + "341": "Corphish", + "342": "Crawdaunt", + "343": "Baltoy", + "344": "Claydol", + "345": "Lileep", + "346": "Cradily", + "347": "Anorith", + "348": "Armaldo", + "349": "Feebas", + "350": "Milotic", + "351": "Castform", + "352": "Kecleon", + "353": "Shuppet", + "354": "Banette", + "355": "Duskull", + "356": "Dusclops", + "357": "Tropius", + "358": "Chimecho", + "359": "Absol", + "360": "Wynaut", + "361": "Snorunt", + "362": "Glalie", + "363": "Spheal", + "364": "Sealeo", + "365": "Walrein", + "366": "Clamperl", + "367": "Huntail", + "368": "Gorebyss", + "369": "Relicanth", + "370": "Luvdisc", + "371": "Bagon", + "372": "Shelgon", + "373": "Salamence", + "374": "Beldum", + "375": "Metang", + "376": "Metagross", + "377": "Regirock", + "378": "Regice", + "379": "Registeel", + "380": "Latias", + "381": "Latios", + "382": "Kyogre", + "383": "Groudon", + "384": "Rayquaza", + "385": "Jirachi", + "386": "Deoxys", + "387": "Turtwig", + "388": "Grotle", + "389": "Torterra", + "390": "Chimchar", + "391": "Monferno", + "392": "Infernape", + "393": "Piplup", + "394": "Prinplup", + "395": "Empoleon", + "396": "Starly", + "397": "Staravia", + "398": "Staraptor", + "399": "Bidoof", + "400": "Bibarel", + "401": "Kricketot", + "402": "Kricketune", + "403": "Shinx", + "404": "Luxio", + "405": "Luxray", + "406": "Budew", + "407": "Roserade", + "408": "Cranidos", + "409": "Rampardos", + "410": "Shieldon", + "411": "Bastiodon", + "412": "Burmy", + "413": "Wormadam", + "414": "Mothim", + "415": "Combee", + "416": "Vespiquen", + "417": "Pachirisu", + "418": "Buizel", + "419": "Floatzel", + "420": "Cherubi", + "421": "Cherrim", + "422": "Shellos", + "423": "Gastrodon", + "424": "Ambipom", + "425": "Drifloon", + "426": "Drifblim", + "427": "Buneary", + "428": "Lopunny", + "429": "Mismagius", + "430": "Honchkrow", + "431": "Glameow", + "432": "Purugly", + "433": "Chingling", + "434": "Stunky", + "435": "Skuntank", + "436": "Bronzor", + "437": "Bronzong", + "438": "Bonsly", + "439": "Mime Jr.", + "440": "Happiny", + "441": "Chatot", + "442": "Spiritomb", + "443": "Gible", + "444": "Gabite", + "445": "Garchomp", + "446": "Munchlax", + "447": "Riolu", + "448": "Lucario", + "449": "Hippopotas", + "450": "Hippowdon", + "451": "Skorupi", + "452": "Drapion", + "453": "Croagunk", + "454": "Toxicroak", + "455": "Carnivine", + "456": "Finneon", + "457": "Lumineon", + "458": "Mantyke", + "459": "Snover", + "460": "Abomasnow", + "461": "Weavile", + "462": "Magnezone", + "463": "Lickilicky", + "464": "Rhyperior", + "465": "Tangrowth", + "466": "Electivire", + "467": "Magmortar", + "468": "Togekiss", + "469": "Yanmega", + "470": "Leafeon", + "471": "Glaceon", + "472": "Gliscor", + "473": "Mamoswine", + "474": "Porygon-Z", + "475": "Gallade", + "476": "Probopass", + "477": "Dusknoir", + "478": "Froslass", + "479": "Rotom", + "480": "Uxie", + "481": "Mesprit", + "482": "Azelf", + "483": "Dialga", + "484": "Palkia", + "485": "Heatran", + "486": "Regigigas", + "487": "Giratina", + "488": "Cresselia", + "489": "Phione", + "490": "Manaphy", + "491": "Darkrai", + "492": "Shaymin", + "493": "Arceus", + "494": "Victini", + "495": "Snivy", + "496": "Servine", + "497": "Serperior", + "498": "Tepig", + "499": "Pignite", + "500": "Emboar", + "501": "Oshawott", + "502": "Dewott", + "503": "Samurott", + "504": "Patrat", + "505": "Watchog", + "506": "Lillipup", + "507": "Herdier", + "508": "Stoutland", + "509": "Purrloin", + "510": "Liepard", + "511": "Pansage", + "512": "Simisage", + "513": "Pansear", + "514": "Simisear", + "515": "Panpour", + "516": "Simipour", + "517": "Munna", + "518": "Musharna", + "519": "Pidove", + "520": "Tranquill", + "521": "Unfezant", + "522": "Blitzle", + "523": "Zebstrika", + "524": "Roggenrola", + "525": "Boldore", + "526": "Gigalith", + "527": "Woobat", + "528": "Swoobat", + "529": "Drilbur", + "530": "Excadrill", + "531": "Audino", + "532": "Timburr", + "533": "Gurdurr", + "534": "Conkeldurr", + "535": "Tympole", + "536": "Palpitoad", + "537": "Seismitoad", + "538": "Throh", + "539": "Sawk", + "540": "Sewaddle", + "541": "Swadloon", + "542": "Leavanny", + "543": "Venipede", + "544": "Whirlipede", + "545": "Scolipede", + "546": "Cottonee", + "547": "Whimsicott", + "548": "Petilil", + "549": "Lilligant", + "550": "Basculin", + "551": "Sandile", + "552": "Krokorok", + "553": "Krookodile", + "554": "Darumaka", + "555": "Darmanitan", + "556": "Maractus", + "557": "Dwebble", + "558": "Crustle", + "559": "Scraggy", + "560": "Scrafty", + "561": "Sigilyph", + "562": "Yamask", + "563": "Cofagrigus", + "564": "Tirtouga", + "565": "Carracosta", + "566": "Archen", + "567": "Archeops", + "568": "Trubbish", + "569": "Garbodor", + "570": "Zorua", + "571": "Zoroark", + "572": "Minccino", + "573": "Cinccino", + "574": "Gothita", + "575": "Gothorita", + "576": "Gothitelle", + "577": "Solosis", + "578": "Duosion", + "579": "Reuniclus", + "580": "Ducklett", + "581": "Swanna", + "582": "Vanillite", + "583": "Vanillish", + "584": "Vanilluxe", + "585": "Deerling", + "586": "Sawsbuck", + "587": "Emolga", + "588": "Karrablast", + "589": "Escavalier", + "590": "Foongus", + "591": "Amoonguss", + "592": "Frillish", + "593": "Jellicent", + "594": "Alomomola", + "595": "Joltik", + "596": "Galvantula", + "597": "Ferroseed", + "598": "Ferrothorn", + "599": "Klink", + "600": "Klang", + "601": "Klinklang", + "602": "Tynamo", + "603": "Eelektrik", + "604": "Eelektross", + "605": "Elgyem", + "606": "Beheeyem", + "607": "Litwick", + "608": "Lampent", + "609": "Chandelure", + "610": "Axew", + "611": "Fraxure", + "612": "Haxorus", + "613": "Cubchoo", + "614": "Beartic", + "615": "Cryogonal", + "616": "Shelmet", + "617": "Accelgor", + "618": "Stunfisk", + "619": "Mienfoo", + "620": "Mienshao", + "621": "Druddigon", + "622": "Golett", + "623": "Golurk", + "624": "Pawniard", + "625": "Bisharp", + "626": "Bouffalant", + "627": "Rufflet", + "628": "Braviary", + "629": "Vullaby", + "630": "Mandibuzz", + "631": "Heatmor", + "632": "Durant", + "633": "Deino", + "634": "Zweilous", + "635": "Hydreigon", + "636": "Larvesta", + "637": "Volcarona", + "638": "Cobalion", + "639": "Terrakion", + "640": "Virizion", + "641": "Tornadus", + "642": "Thundurus", + "643": "Reshiram", + "644": "Zekrom", + "645": "Landorus", + "646": "Kyurem", + "647": "Keldeo", + "648": "Meloetta", + "649": "Genesect", + "650": "Chespin", + "651": "Quilladin", + "652": "Chesnaught", + "653": "Fennekin", + "654": "Braixen", + "655": "Delphox", + "656": "Froakie", + "657": "Frogadier", + "658": "Greninja", + "659": "Bunnelby", + "660": "Diggersby", + "661": "Fletchling", + "662": "Fletchinder", + "663": "Talonflame", + "664": "Scatterbug", + "665": "Spewpa", + "666": "Vivillon", + "667": "Litleo", + "668": "Pyroar", + "669": "Flab\u00e9b\u00e9", + "670": "Floette", + "671": "Florges", + "672": "Skiddo", + "673": "Gogoat", + "674": "Pancham", + "675": "Pangoro", + "676": "Furfrou", + "677": "Espurr", + "678": "Meowstic", + "679": "Honedge", + "680": "Doublade", + "681": "Aegislash", + "682": "Spritzee", + "683": "Aromatisse", + "684": "Swirlix", + "685": "Slurpuff", + "686": "Inkay", + "687": "Malamar", + "688": "Binacle", + "689": "Barbaracle", + "690": "Skrelp", + "691": "Dragalge", + "692": "Clauncher", + "693": "Clawitzer", + "694": "Helioptile", + "695": "Heliolisk", + "696": "Tyrunt", + "697": "Tyrantrum", + "698": "Amaura", + "699": "Aurorus", + "700": "Sylveon", + "701": "Hawlucha", + "702": "Dedenne", + "703": "Carbink", + "704": "Goomy", + "705": "Sliggoo", + "706": "Goodra", + "707": "Klefki", + "708": "Phantump", + "709": "Trevenant", + "710": "Pumpkaboo", + "711": "Gourgeist", + "712": "Bergmite", + "713": "Avalugg", + "714": "Noibat", + "715": "Noivern", + "716": "Xerneas", + "717": "Yveltal", + "718": "Zygarde", + "719": "Diancie", + "720": "Hoopa", "721": "Volcanion" - }, - "misc": { - "boosted": "boosted" + }, + "sizes": { + "001": "tiny", + "002": "small", + "003": "normal", + "004": "large", + "005": "big" + }, + "teams": { + "000": "Neutral", + "001": "Mystic", + "002": "Valor", + "003": "Instinct" + }, + "types": { + "001": "Normal", + "002": "Fighting", + "003": "Flying", + "004": "Poison", + "005": "Ground", + "006": "Rock", + "007": "Bug", + "008": "Ghost", + "009": "Steel", + "010": "Fire", + "011": "Water", + "012": "Grass", + "013": "Electric", + "014": "Psychic", + "015": "Ice", + "016": "Dragon", + "017": "Fairy", + "018": "Dark" + }, + "weather": { + "000": "None", + "001": "Clear", + "002": "Rain", + "003": "Partly Cloudy", + "004": "Cloudy", + "005": "Windy", + "006": "Snow", + "007": "Fog" } -} +} \ No newline at end of file diff --git a/locales/es.json b/locales/es.json index 86d7b583a..3ad9fdb5a 100644 --- a/locales/es.json +++ b/locales/es.json @@ -1,961 +1,981 @@ { + "costumes": { + "025": { + "001": "Gorra festiva", + "002": "Gorra de Fiesta", + "003": "Gorra de Ash", + "004": "Sombrero de Bruja" + }, + "026": { + "001": "Gorra festiva", + "002": "Gorra de Fiesta", + "003": "Gorra de Ash", + "004": "Sombrero de Bruja" + }, + "172": { + "001": "Gorra festiva", + "002": "Gorra de Fiesta", + "003": "Gorra de Ash", + "004": "Sombrero de Bruja" + } + }, "leaders": { - "0": "Profesor Willow", - "1": "Blanche", - "2": "Candela", - "3": "Spark" - }, - "sizes": { - "1": "diminuto", - "2": "peque\u00F1o", - "3": "normal", - "4": "grande", - "5": "enorme" - }, - "types": { - "1": "Normal", - "2": "Lucha", - "3": "Volador", - "4": "Veneno", - "5": "Tierra", - "6": "Roca", - "7": "Bicho", - "8": "Fantasma", - "9": "Acero", - "10": "Fuego", - "11": "Agua", - "12": "Planta", - "13": "El\u00E9ctrico", - "14": "Ps\u00EDquico", - "15": "Hielo", - "16": "Drag\u00F3n", - "17": "Hada", - "18": "Siniestro" - }, + "000": "Profesor Willow", + "001": "Blanche", + "002": "Candela", + "003": "Spark" + }, + "misc": { + "boosted": "potenciado" + }, "moves": { - "13": "Constricci\u00f3n", - "14": "Hiperrayo", - "16": "Pulso Umbr\u00edo", - "18": "Residuos", - "20": "Agarre", - "21": "Rueda Fuego", - "22": "Megacuerno", - "24": "Lanzallamas", - "26": "Excavar", - "28": "Tajo Cruzado", - "30": "Psicorrayo", - "31": "Terremoto", - "32": "Roca Afilada", - "33": "Pu\u00f1o Hielo", - "34": "Arrumaco", - "35": "Chispazo", - "36": "Foco Resplandor", - "38": "Pico Taladro", - "39": "Rayo Hielo", - "40": "Ventisca", - "42": "Onda \u00cdgnea", - "45": "Golpe A\u00e9reo", - "46": "Taladradora", - "47": "Tormenta Floral", - "48": "Megaagotar", - "49": "Zumbido", - "50": "Colmillo Veneno", - "51": "Tajo Umbr\u00edo", - "53": "Rayo Burbuja", - "54": "Sumisi\u00f3n", - "56": "Puntapi\u00e9", - "57": "Acua Jet", - "58": "Acua Cola", - "59": "Bomba Germen", - "60": "Psicocarga", - "62": "Poder Pasado", - "63": "Tumba Rocas", - "64": "Avalancha", - "65": "Joya de Luz", - "66": "Sombra Vil", - "67": "Pu\u00f1o Sombra", - "69": "Viento Aciago", - "70": "Bola Sombra", - "72": "Bomba Im\u00e1n", - "74": "Cabeza de Hierro", - "75": "Carga Par\u00e1bola", - "77": "Pu\u00f1o Trueno", - "78": "Trueno", - "79": "Rayo", - "80": "Cicl\u00f3n", - "82": "Pulso Drag\u00f3n", - "83": "Garra Drag\u00f3n", - "84": "Voz Cautivadora", - "85": "Beso Drenaje", - "86": "Brillo M\u00e1gico", - "87": "Fuerza Lunar", - "88": "Caranto\u00f1a", - "89": "Veneno X", - "90": "Bomba Lodo", - "91": "Onda T\u00f3xica", - "92": "Lanza Mugre", - "94": "Hueso Palo", - "95": "Terratemblor", - "96": "Bomba Fango", - "99": "Doble Rayo", - "100": "Tijera X", - "101": "Nitrocarga", - "102": "Pirotecnia", - "103": "Llamarada", - "104": "Salmuera", - "105": "Hidropulso", - "106": "Escaldar", - "107": "Hidrobomba", - "108": "Ps\u00edquico", - "109": "Onda Mental", - "111": "Viento Hielo", - "114": "Gigadrenado", - "115": "Pu\u00f1o Fuego", - "116": "Rayo Solar", - "117": "Hoja Aguda", - "118": "Latigazo", - "121": "Aire Afilado", - "122": "Vendaval", - "123": "Demolici\u00f3n", - "125": "Rapidez", - "126": "Cornada", - "127": "Pisot\u00f3n", - "129": "Hipercolmillo", - "131": "Golpe Cuerpo", - "132": "Descanso", - "133": "Combate", - "200": "Corte Furia", - "201": "Picadura", - "202": "Mordisco", - "203": "Golpe Bajo", - "204": "Dragoaliento", - "205": "Impactrueno", - "206": "Chispa", - "207": "Patada Baja", - "208": "Golpe K\u00e1rate", - "209": "Ascuas", - "210": "Ataque Ala", - "211": "Picotazo", - "212": "Leng\u00fcetazo", - "213": "Garra Umbr\u00eda", - "214": "L\u00e1tigo Cepa", - "215": "Hoja Afilada", - "216": "Disparo Lodo", - "217": "Canto Helado", - "218": "Vaho G\u00e9lido", - "219": "Ataque R\u00e1pido", - "220": "Ara\u00f1azo", - "221": "Placaje", - "222": "Destructor", - "223": "Corte", - "224": "Puya Nociva", - "225": "\u00c1cido", - "226": "Psicocorte", - "227": "Lanzarrocas", - "228": "Garra Metal", - "229": "Pu\u00f1o Bala", - "230": "Pistola Agua", - "231": "Salpicadura", - "233": "Bofet\u00f3n Lodo", - "234": "Cabezazo Zen", - "235": "Confusi\u00f3n", - "236": "Picotazo Veneno", - "237": "Burbuja", - "238": "Finta", - "239": "Ala de Acero", - "240": "Colmillo \u00cdgneo", - "241": "Golpe Roca", - "242": "Transformaci\u00f3n", - "243": "Contraataque", - "244": "Nieve Polvo", - "245": "A Bocajarro", - "246": "Pu\u00f1o Din\u00e1mico", - "247": "Onda Certera", - "248": "Rayo Aurora", - "249": "Rayo Carga", - "250": "Voltiocambio", - "251": "Voltio Cruel", - "252": "Electroca\u00f1\u00f3n", - "253": "Cola Drag\u00f3n", - "254": "Alud", - "255": "Tajo A\u00e9reo", - "256": "P\u00e1jaro Osado", - "257": "Ataque A\u00e9reo", - "258": "Bucle Arena", - "259": "Pedrada", - "260": "Acoso", - "261": "Estoicismo", - "262": "Viento Plata", - "263": "Impresionar", - "264": "Infortunio", - "265": "Tinieblas", - "266": "Cola F\u00e9rrea", - "267": "Giro Bola", - "268": "Cuerpo Pesado", - "269": "Giro Fuego", - "270": "Sofoco", - "271": "Recurrente", - "272": "Hierba Lazo", - "273": "Energibola", - "274": "Paranormal", - "275": "Premonici\u00f3n", - "276": "Manto Espejo", - "277": "Enfado", - "278": "Alarido", - "279": "Triturar", - "280": "Juego Sucio", - "281": "Poder Oculto", - "282": "Derribo", - "283": "Cascada", - "284": "Surf", - "285": "Cometa Draco", - "286": "Deseo Oculto", - "287": "Bostezo", - "288": "Psicoataque", - "289": "Pulso Primigenio", - "290": "Filo del Abismo", + "013": "Constricci\u00f3n", + "014": "Hiperrayo", + "016": "Pulso Umbr\u00edo", + "018": "Residuos", + "020": "Agarre", + "021": "Rueda Fuego", + "022": "Megacuerno", + "024": "Lanzallamas", + "026": "Excavar", + "028": "Tajo Cruzado", + "030": "Psicorrayo", + "031": "Terremoto", + "032": "Roca Afilada", + "033": "Pu\u00f1o Hielo", + "034": "Arrumaco", + "035": "Chispazo", + "036": "Foco Resplandor", + "038": "Pico Taladro", + "039": "Rayo Hielo", + "040": "Ventisca", + "042": "Onda \u00cdgnea", + "045": "Golpe A\u00e9reo", + "046": "Taladradora", + "047": "Tormenta Floral", + "048": "Megaagotar", + "049": "Zumbido", + "050": "Colmillo Veneno", + "051": "Tajo Umbr\u00edo", + "053": "Rayo Burbuja", + "054": "Sumisi\u00f3n", + "056": "Puntapi\u00e9", + "057": "Acua Jet", + "058": "Acua Cola", + "059": "Bomba Germen", + "060": "Psicocarga", + "062": "Poder Pasado", + "063": "Tumba Rocas", + "064": "Avalancha", + "065": "Joya de Luz", + "066": "Sombra Vil", + "067": "Pu\u00f1o Sombra", + "069": "Viento Aciago", + "070": "Bola Sombra", + "072": "Bomba Im\u00e1n", + "074": "Cabeza de Hierro", + "075": "Carga Par\u00e1bola", + "077": "Pu\u00f1o Trueno", + "078": "Trueno", + "079": "Rayo", + "080": "Cicl\u00f3n", + "082": "Pulso Drag\u00f3n", + "083": "Garra Drag\u00f3n", + "084": "Voz Cautivadora", + "085": "Beso Drenaje", + "086": "Brillo M\u00e1gico", + "087": "Fuerza Lunar", + "088": "Caranto\u00f1a", + "089": "Veneno X", + "090": "Bomba Lodo", + "091": "Onda T\u00f3xica", + "092": "Lanza Mugre", + "094": "Hueso Palo", + "095": "Terratemblor", + "096": "Bomba Fango", + "099": "Doble Rayo", + "100": "Tijera X", + "101": "Nitrocarga", + "102": "Pirotecnia", + "103": "Llamarada", + "104": "Salmuera", + "105": "Hidropulso", + "106": "Escaldar", + "107": "Hidrobomba", + "108": "Ps\u00edquico", + "109": "Onda Mental", + "111": "Viento Hielo", + "114": "Gigadrenado", + "115": "Pu\u00f1o Fuego", + "116": "Rayo Solar", + "117": "Hoja Aguda", + "118": "Latigazo", + "121": "Aire Afilado", + "122": "Vendaval", + "123": "Demolici\u00f3n", + "125": "Rapidez", + "126": "Cornada", + "127": "Pisot\u00f3n", + "129": "Hipercolmillo", + "131": "Golpe Cuerpo", + "132": "Descanso", + "133": "Combate", + "200": "Corte Furia", + "201": "Picadura", + "202": "Mordisco", + "203": "Golpe Bajo", + "204": "Dragoaliento", + "205": "Impactrueno", + "206": "Chispa", + "207": "Patada Baja", + "208": "Golpe K\u00e1rate", + "209": "Ascuas", + "210": "Ataque Ala", + "211": "Picotazo", + "212": "Leng\u00fcetazo", + "213": "Garra Umbr\u00eda", + "214": "L\u00e1tigo Cepa", + "215": "Hoja Afilada", + "216": "Disparo Lodo", + "217": "Canto Helado", + "218": "Vaho G\u00e9lido", + "219": "Ataque R\u00e1pido", + "220": "Ara\u00f1azo", + "221": "Placaje", + "222": "Destructor", + "223": "Corte", + "224": "Puya Nociva", + "225": "\u00c1cido", + "226": "Psicocorte", + "227": "Lanzarrocas", + "228": "Garra Metal", + "229": "Pu\u00f1o Bala", + "230": "Pistola Agua", + "231": "Salpicadura", + "233": "Bofet\u00f3n Lodo", + "234": "Cabezazo Zen", + "235": "Confusi\u00f3n", + "236": "Picotazo Veneno", + "237": "Burbuja", + "238": "Finta", + "239": "Ala de Acero", + "240": "Colmillo \u00cdgneo", + "241": "Golpe Roca", + "242": "Transformaci\u00f3n", + "243": "Contraataque", + "244": "Nieve Polvo", + "245": "A Bocajarro", + "246": "Pu\u00f1o Din\u00e1mico", + "247": "Onda Certera", + "248": "Rayo Aurora", + "249": "Rayo Carga", + "250": "Voltiocambio", + "251": "Voltio Cruel", + "252": "Electroca\u00f1\u00f3n", + "253": "Cola Drag\u00f3n", + "254": "Alud", + "255": "Tajo A\u00e9reo", + "256": "P\u00e1jaro Osado", + "257": "Ataque A\u00e9reo", + "258": "Bucle Arena", + "259": "Pedrada", + "260": "Acoso", + "261": "Estoicismo", + "262": "Viento Plata", + "263": "Impresionar", + "264": "Infortunio", + "265": "Tinieblas", + "266": "Cola F\u00e9rrea", + "267": "Giro Bola", + "268": "Cuerpo Pesado", + "269": "Giro Fuego", + "270": "Sofoco", + "271": "Recurrente", + "272": "Hierba Lazo", + "273": "Energibola", + "274": "Paranormal", + "275": "Premonici\u00f3n", + "276": "Manto Espejo", + "277": "Enfado", + "278": "Alarido", + "279": "Triturar", + "280": "Juego Sucio", + "281": "Poder Oculto", + "282": "Derribo", + "283": "Cascada", + "284": "Surf", + "285": "Cometa Draco", + "286": "Deseo Oculto", + "287": "Bostezo", + "288": "Psicoataque", + "289": "Pulso Primigenio", + "290": "Filo del Abismo", "291": "Presente" - }, + }, "pokemon": { - "1": "Bulbasaur", - "2": "Ivysaur", - "3": "Venusaur", - "4": "Charmander", - "5": "Charmeleon", - "6": "Charizard", - "7": "Squirtle", - "8": "Wartortle", - "9": "Blastoise", - "10": "Caterpie", - "11": "Metapod", - "12": "Butterfree", - "13": "Weedle", - "14": "Kakuna", - "15": "Beedrill", - "16": "Pidgey", - "17": "Pidgeotto", - "18": "Pidgeot", - "19": "Rattata", - "20": "Raticate", - "21": "Spearow", - "22": "Fearow", - "23": "Ekans", - "24": "Arbok", - "25": "Pikachu", - "26": "Raichu", - "27": "Sandshrew", - "28": "Sandslash", - "29": "Nidoran♀", - "30": "Nidorina", - "31": "Nidoqueen", - "32": "Nidoran♂", - "33": "Nidorino", - "34": "Nidoking", - "35": "Clefairy", - "36": "Clefable", - "37": "Vulpix", - "38": "Ninetales", - "39": "Jigglypuff", - "40": "Wigglytuff", - "41": "Zubat", - "42": "Golbat", - "43": "Oddish", - "44": "Gloom", - "45": "Vileplume", - "46": "Paras", - "47": "Parasect", - "48": "Venonat", - "49": "Venomoth", - "50": "Diglett", - "51": "Dugtrio", - "52": "Meowth", - "53": "Persian", - "54": "Psyduck", - "55": "Golduck", - "56": "Mankey", - "57": "Primeape", - "58": "Growlithe", - "59": "Arcanine", - "60": "Poliwag", - "61": "Poliwhirl", - "62": "Poliwrath", - "63": "Abra", - "64": "Kadabra", - "65": "Alakazam", - "66": "Machop", - "67": "Machoke", - "68": "Machamp", - "69": "Bellsprout", - "70": "Weepinbell", - "71": "Victreebel", - "72": "Tentacool", - "73": "Tentacruel", - "74": "Geodude", - "75": "Graveler", - "76": "Golem", - "77": "Ponyta", - "78": "Rapidash", - "79": "Slowpoke", - "80": "Slowbro", - "81": "Magnemite", - "82": "Magneton", - "83": "Farfetch'd", - "84": "Doduo", - "85": "Dodrio", - "86": "Seel", - "87": "Dewgong", - "88": "Grimer", - "89": "Muk", - "90": "Shellder", - "91": "Cloyster", - "92": "Gastly", - "93": "Haunter", - "94": "Gengar", - "95": "Onix", - "96": "Drowzee", - "97": "Hypno", - "98": "Krabby", - "99": "Kingler", - "100": "Voltorb", - "101": "Electrode", - "102": "Exeggcute", - "103": "Exeggutor", - "104": "Cubone", - "105": "Marowak", - "106": "Hitmonlee", - "107": "Hitmonchan", - "108": "Lickitung", - "109": "Koffing", - "110": "Weezing", - "111": "Rhyhorn", - "112": "Rhydon", - "113": "Chansey", - "114": "Tangela", - "115": "Kangaskhan", - "116": "Horsea", - "117": "Seadra", - "118": "Goldeen", - "119": "Seaking", - "120": "Staryu", - "121": "Starmie", - "122": "Mr. Mime", - "123": "Scyther", - "124": "Jynx", - "125": "Electabuzz", - "126": "Magmar", - "127": "Pinsir", - "128": "Tauros", - "129": "Magikarp", - "130": "Gyarados", - "131": "Lapras", - "132": "Ditto", - "133": "Eevee", - "134": "Vaporeon", - "135": "Jolteon", - "136": "Flareon", - "137": "Porygon", - "138": "Omanyte", - "139": "Omastar", - "140": "Kabuto", - "141": "Kabutops", - "142": "Aerodactyl", - "143": "Snorlax", - "144": "Articuno", - "145": "Zapdos", - "146": "Moltres", - "147": "Dratini", - "148": "Dragonair", - "149": "Dragonite", - "150": "Mewtwo", - "151": "Mew", - "152": "Chikorita", - "153": "Bayleef", - "154": "Meganium", - "155": "Cyndaquil", - "156": "Quilava", - "157": "Typhlosion", - "158": "Totodile", - "159": "Croconaw", - "160": "Feraligatr", - "161": "Sentret", - "162": "Furret", - "163": "Hoothoot", - "164": "Noctowl", - "165": "Ledyba", - "166": "Ledian", - "167": "Spinarak", - "168": "Ariados", - "169": "Crobat", - "170": "Chinchou", - "171": "Lanturn", - "172": "Pichu", - "173": "Cleffa", - "174": "Igglybuff", - "175": "Togepi", - "176": "Togetic", - "177": "Natu", - "178": "Xatu", - "179": "Mareep", - "180": "Flaaffy", - "181": "Ampharos", - "182": "Bellossom", - "183": "Marill", - "184": "Azumarill", - "185": "Sudowoodo", - "186": "Politoed", - "187": "Hoppip", - "188": "Skiploom", - "189": "Jumpluff", - "190": "Aipom", - "191": "Sunkern", - "192": "Sunflora", - "193": "Yanma", - "194": "Wooper", - "195": "Quagsire", - "196": "Espeon", - "197": "Umbreon", - "198": "Murkrow", - "199": "Slowking", - "200": "Misdreavus", - "201": "Unown", - "202": "Wobbuffet", - "203": "Girafarig", - "204": "Pineco", - "205": "Forretress", - "206": "Dunsparce", - "207": "Gligar", - "208": "Steelix", - "209": "Snubbull", - "210": "Granbull", - "211": "Qwilfish", - "212": "Scizor", - "213": "Shuckle", - "214": "Heracross", - "215": "Sneasel", - "216": "Teddiursa", - "217": "Ursaring", - "218": "Slugma", - "219": "Magcargo", - "220": "Swinub", - "221": "Piloswine", - "222": "Corsola", - "223": "Remoraid", - "224": "Octillery", - "225": "Delibird", - "226": "Mantine", - "227": "Skarmory", - "228": "Houndour", - "229": "Houndoom", - "230": "Kingdra", - "231": "Phanpy", - "232": "Donphan", - "233": "Porygon2", - "234": "Stantler", - "235": "Smeargle", - "236": "Tyrogue", - "237": "Hitmontop", - "238": "Smoochum", - "239": "Elekid", - "240": "Magby", - "241": "Miltank", - "242": "Blissey", - "243": "Raikou", - "244": "Entei", - "245": "Suicune", - "246": "Larvitar", - "247": "Pupitar", - "248": "Tyranitar", - "249": "Lugia", - "250": "Ho-Oh", - "251": "Celebi", - "252": "Treecko", - "253": "Grovyle", - "254": "Sceptile", - "255": "Torchic", - "256": "Combusken", - "257": "Blaziken", - "258": "Mudkip", - "259": "Marshtomp", - "260": "Swampert", - "261": "Poochyena", - "262": "Mightyena", - "263": "Zigzagoon", - "264": "Linoone", - "265": "Wurmple", - "266": "Silcoon", - "267": "Beautifly", - "268": "Cascoon", - "269": "Dustox", - "270": "Lotad", - "271": "Lombre", - "272": "Ludicolo", - "273": "Seedot", - "274": "Nuzleaf", - "275": "Shiftry", - "276": "Taillow", - "277": "Swellow", - "278": "Wingull", - "279": "Pelipper", - "280": "Ralts", - "281": "Kirlia", - "282": "Gardevoir", - "283": "Surskit", - "284": "Masquerain", - "285": "Shroomish", - "286": "Breloom", - "287": "Slakoth", - "288": "Vigoroth", - "289": "Slaking", - "290": "Nincada", - "291": "Ninjask", - "292": "Shedinja", - "293": "Whismur", - "294": "Loudred", - "295": "Exploud", - "296": "Makuhita", - "297": "Hariyama", - "298": "Azurill", - "299": "Nosepass", - "300": "Skitty", - "301": "Delcatty", - "302": "Sableye", - "303": "Mawile", - "304": "Aron", - "305": "Lairon", - "306": "Aggron", - "307": "Meditite", - "308": "Medicham", - "309": "Electrike", - "310": "Manectric", - "311": "Plusle", - "312": "Minun", - "313": "Volbeat", - "314": "Illumise", - "315": "Roselia", - "316": "Gulpin", - "317": "Swalot", - "318": "Carvanha", - "319": "Sharpedo", - "320": "Wailmer", - "321": "Wailord", - "322": "Numel", - "323": "Camerupt", - "324": "Torkoal", - "325": "Spoink", - "326": "Grumpig", - "327": "Spinda", - "328": "Trapinch", - "329": "Vibrava", - "330": "Flygon", - "331": "Cacnea", - "332": "Cacturne", - "333": "Swablu", - "334": "Altaria", - "335": "Zangoose", - "336": "Seviper", - "337": "Lunatone", - "338": "Solrock", - "339": "Barboach", - "340": "Whiscash", - "341": "Corphish", - "342": "Crawdaunt", - "343": "Baltoy", - "344": "Claydol", - "345": "Lileep", - "346": "Cradily", - "347": "Anorith", - "348": "Armaldo", - "349": "Feebas", - "350": "Milotic", - "351": "Castform", - "352": "Kecleon", - "353": "Shuppet", - "354": "Banette", - "355": "Duskull", - "356": "Dusclops", - "357": "Tropius", - "358": "Chimecho", - "359": "Absol", - "360": "Wynaut", - "361": "Snorunt", - "362": "Glalie", - "363": "Spheal", - "364": "Sealeo", - "365": "Walrein", - "366": "Clamperl", - "367": "Huntail", - "368": "Gorebyss", - "369": "Relicanth", - "370": "Luvdisc", - "371": "Bagon", - "372": "Shelgon", - "373": "Salamence", - "374": "Beldum", - "375": "Metang", - "376": "Metagross", - "377": "Regirock", - "378": "Regice", - "379": "Registeel", - "380": "Latias", - "381": "Latios", - "382": "Kyogre", - "383": "Groudon", - "384": "Rayquaza", - "385": "Jirachi", - "386": "Deoxys", - "387": "Turtwig", - "388": "Grotle", - "389": "Torterra", - "390": "Chimchar", - "391": "Monferno", - "392": "Infernape", - "393": "Piplup", - "394": "Prinplup", - "395": "Empoleon", - "396": "Starly", - "397": "Staravia", - "398": "Staraptor", - "399": "Bidoof", - "400": "Bibarel", - "401": "Kricketot", - "402": "Kricketune", - "403": "Shinx", - "404": "Luxio", - "405": "Luxray", - "406": "Budew", - "407": "Roserade", - "408": "Cranidos", - "409": "Rampardos", - "410": "Shieldon", - "411": "Bastiodon", - "412": "Burmy", - "413": "Wormadam", - "414": "Mothim", - "415": "Combee", - "416": "Vespiquen", - "417": "Pachirisu", - "418": "Buizel", - "419": "Floatzel", - "420": "Cherubi", - "421": "Cherrim", - "422": "Shellos", - "423": "Gastrodon", - "424": "Ambipom", - "425": "Drifloon", - "426": "Drifblim", - "427": "Buneary", - "428": "Lopunny", - "429": "Mismagius", - "430": "Honchkrow", - "431": "Glameow", - "432": "Purugly", - "433": "Chingling", - "434": "Stunky", - "435": "Skuntank", - "436": "Bronzor", - "437": "Bronzong", - "438": "Bonsly", - "439": "Mime Jr.", - "440": "Happiny", - "441": "Chatot", - "442": "Spiritomb", - "443": "Gible", - "444": "Gabite", - "445": "Garchomp", - "446": "Munchlax", - "447": "Riolu", - "448": "Lucario", - "449": "Hippopotas", - "450": "Hippowdon", - "451": "Skorupi", - "452": "Drapion", - "453": "Croagunk", - "454": "Toxicroak", - "455": "Carnivine", - "456": "Finneon", - "457": "Lumineon", - "458": "Mantyke", - "459": "Snover", - "460": "Abomasnow", - "461": "Weavile", - "462": "Magnezone", - "463": "Lickilicky", - "464": "Rhyperior", - "465": "Tangrowth", - "466": "Electivire", - "467": "Magmortar", - "468": "Togekiss", - "469": "Yanmega", - "470": "Leafeon", - "471": "Glaceon", - "472": "Gliscor", - "473": "Mamoswine", - "474": "Porygon-Z", - "475": "Gallade", - "476": "Probopass", - "477": "Dusknoir", - "478": "Froslass", - "479": "Rotom", - "480": "Uxie", - "481": "Mesprit", - "482": "Azelf", - "483": "Dialga", - "484": "Palkia", - "485": "Heatran", - "486": "Regigigas", - "487": "Giratina", - "488": "Cresselia", - "489": "Phione", - "490": "Manaphy", - "491": "Darkrai", - "492": "Shaymin", - "493": "Arceus", - "494": "Victini", - "495": "Snivy", - "496": "Servine", - "497": "Serperior", - "498": "Tepig", - "499": "Pignite", - "500": "Emboar", - "501": "Oshawott", - "502": "Dewott", - "503": "Samurott", - "504": "Patrat", - "505": "Watchog", - "506": "Lillipup", - "507": "Herdier", - "508": "Stoutland", - "509": "Purrloin", - "510": "Liepard", - "511": "Pansage", - "512": "Simisage", - "513": "Pansear", - "514": "Simisear", - "515": "Panpour", - "516": "Simipour", - "517": "Munna", - "518": "Musharna", - "519": "Pidove", - "520": "Tranquill", - "521": "Unfezant", - "522": "Blitzle", - "523": "Zebstrika", - "524": "Roggenrola", - "525": "Boldore", - "526": "Gigalith", - "527": "Woobat", - "528": "Swoobat", - "529": "Drilbur", - "530": "Excadrill", - "531": "Audino", - "532": "Timburr", - "533": "Gurdurr", - "534": "Conkeldurr", - "535": "Tympole", - "536": "Palpitoad", - "537": "Seismitoad", - "538": "Throh", - "539": "Sawk", - "540": "Sewaddle", - "541": "Swadloon", - "542": "Leavanny", - "543": "Venipede", - "544": "Whirlipede", - "545": "Scolipede", - "546": "Cottonee", - "547": "Whimsicott", - "548": "Petilil", - "549": "Lilligant", - "550": "Basculin", - "551": "Sandile", - "552": "Krokorok", - "553": "Krookodile", - "554": "Darumaka", - "555": "Darmanitan", - "556": "Maractus", - "557": "Dwebble", - "558": "Crustle", - "559": "Scraggy", - "560": "Scrafty", - "561": "Sigilyph", - "562": "Yamask", - "563": "Cofagrigus", - "564": "Tirtouga", - "565": "Carracosta", - "566": "Archen", - "567": "Archeops", - "568": "Trubbish", - "569": "Garbodor", - "570": "Zorua", - "571": "Zoroark", - "572": "Minccino", - "573": "Cinccino", - "574": "Gothita", - "575": "Gothorita", - "576": "Gothitelle", - "577": "Solosis", - "578": "Duosion", - "579": "Reuniclus", - "580": "Ducklett", - "581": "Swanna", - "582": "Vanillite", - "583": "Vanillish", - "584": "Vanilluxe", - "585": "Deerling", - "586": "Sawsbuck", - "587": "Emolga", - "588": "Karrablast", - "589": "Escavalier", - "590": "Foongus", - "591": "Amoonguss", - "592": "Frillish", - "593": "Jellicent", - "594": "Alomomola", - "595": "Joltik", - "596": "Galvantula", - "597": "Ferroseed", - "598": "Ferrothorn", - "599": "Klink", - "600": "Klang", - "601": "Klinklang", - "602": "Tynamo", - "603": "Eelektrik", - "604": "Eelektross", - "605": "Elgyem", - "606": "Beheeyem", - "607": "Litwick", - "608": "Lampent", - "609": "Chandelure", - "610": "Axew", - "611": "Fraxure", - "612": "Haxorus", - "613": "Cubchoo", - "614": "Beartic", - "615": "Cryogonal", - "616": "Shelmet", - "617": "Accelgor", - "618": "Stunfisk", - "619": "Mienfoo", - "620": "Mienshao", - "621": "Druddigon", - "622": "Golett", - "623": "Golurk", - "624": "Pawniard", - "625": "Bisharp", - "626": "Bouffalant", - "627": "Rufflet", - "628": "Braviary", - "629": "Vullaby", - "630": "Mandibuzz", - "631": "Heatmor", - "632": "Durant", - "633": "Deino", - "634": "Zweilous", - "635": "Hydreigon", - "636": "Larvesta", - "637": "Volcarona", - "638": "Cobalion", - "639": "Terrakion", - "640": "Virizion", - "641": "Tornadus", - "642": "Thundurus", - "643": "Reshiram", - "644": "Zekrom", - "645": "Landorus", - "646": "Kyurem", - "647": "Keldeo", - "648": "Meloetta", - "649": "Genesect", - "650": "Chespin", - "651": "Quilladin", - "652": "Chesnaught", - "653": "Fennekin", - "654": "Braixen", - "655": "Delphox", - "656": "Froakie", - "657": "Frogadier", - "658": "Greninja", - "659": "Bunnelby", - "660": "Diggersby", - "661": "Fletchling", - "662": "Fletchinder", - "663": "Talonflame", - "664": "Scatterbug", - "665": "Spewpa", - "666": "Vivillon", - "667": "Litleo", - "668": "Pyroar", - "669": "Flab\u00E9b\u00E9", - "670": "Floette", - "671": "Florges", - "672": "Skiddo", - "673": "Gogoat", - "674": "Pancham", - "675": "Pangoro", - "676": "Furfrou", - "677": "Espurr", - "678": "Meowstic", - "679": "Honedge", - "680": "Doublade", - "681": "Aegislash", - "682": "Spritzee", - "683": "Aromatisse", - "684": "Swirlix", - "685": "Slurpuff", - "686": "Inkay", - "687": "Malamar", - "688": "Binacle", - "689": "Barbaracle", - "690": "Skrelp", - "691": "Dragalge", - "692": "Clauncher", - "693": "Clawitzer", - "694": "Helioptile", - "695": "Heliolisk", - "696": "Tyrunt", - "697": "Tyrantrum", - "698": "Amaura", - "699": "Aurorus", - "700": "Sylveon", - "701": "Hawlucha", - "702": "Dedenne", - "703": "Carbink", - "704": "Goomy", - "705": "Sliggoo", - "706": "Goodra", - "707": "Klefki", - "708": "Phantump", - "709": "Trevenant", - "710": "Pumpkaboo", - "711": "Gourgeist", - "712": "Bergmite", - "713": "Avalugg", - "714": "Noibat", - "715": "Noivern", - "716": "Xerneas", - "717": "Yveltal", - "718": "Zygarde", - "719": "Diancie", - "720": "Hoopa", + "001": "Bulbasaur", + "002": "Ivysaur", + "003": "Venusaur", + "004": "Charmander", + "005": "Charmeleon", + "006": "Charizard", + "007": "Squirtle", + "008": "Wartortle", + "009": "Blastoise", + "010": "Caterpie", + "011": "Metapod", + "012": "Butterfree", + "013": "Weedle", + "014": "Kakuna", + "015": "Beedrill", + "016": "Pidgey", + "017": "Pidgeotto", + "018": "Pidgeot", + "019": "Rattata", + "020": "Raticate", + "021": "Spearow", + "022": "Fearow", + "023": "Ekans", + "024": "Arbok", + "025": "Pikachu", + "026": "Raichu", + "027": "Sandshrew", + "028": "Sandslash", + "029": "Nidoran\u2640", + "030": "Nidorina", + "031": "Nidoqueen", + "032": "Nidoran\u2642", + "033": "Nidorino", + "034": "Nidoking", + "035": "Clefairy", + "036": "Clefable", + "037": "Vulpix", + "038": "Ninetales", + "039": "Jigglypuff", + "040": "Wigglytuff", + "041": "Zubat", + "042": "Golbat", + "043": "Oddish", + "044": "Gloom", + "045": "Vileplume", + "046": "Paras", + "047": "Parasect", + "048": "Venonat", + "049": "Venomoth", + "050": "Diglett", + "051": "Dugtrio", + "052": "Meowth", + "053": "Persian", + "054": "Psyduck", + "055": "Golduck", + "056": "Mankey", + "057": "Primeape", + "058": "Growlithe", + "059": "Arcanine", + "060": "Poliwag", + "061": "Poliwhirl", + "062": "Poliwrath", + "063": "Abra", + "064": "Kadabra", + "065": "Alakazam", + "066": "Machop", + "067": "Machoke", + "068": "Machamp", + "069": "Bellsprout", + "070": "Weepinbell", + "071": "Victreebel", + "072": "Tentacool", + "073": "Tentacruel", + "074": "Geodude", + "075": "Graveler", + "076": "Golem", + "077": "Ponyta", + "078": "Rapidash", + "079": "Slowpoke", + "080": "Slowbro", + "081": "Magnemite", + "082": "Magneton", + "083": "Farfetch'd", + "084": "Doduo", + "085": "Dodrio", + "086": "Seel", + "087": "Dewgong", + "088": "Grimer", + "089": "Muk", + "090": "Shellder", + "091": "Cloyster", + "092": "Gastly", + "093": "Haunter", + "094": "Gengar", + "095": "Onix", + "096": "Drowzee", + "097": "Hypno", + "098": "Krabby", + "099": "Kingler", + "100": "Voltorb", + "101": "Electrode", + "102": "Exeggcute", + "103": "Exeggutor", + "104": "Cubone", + "105": "Marowak", + "106": "Hitmonlee", + "107": "Hitmonchan", + "108": "Lickitung", + "109": "Koffing", + "110": "Weezing", + "111": "Rhyhorn", + "112": "Rhydon", + "113": "Chansey", + "114": "Tangela", + "115": "Kangaskhan", + "116": "Horsea", + "117": "Seadra", + "118": "Goldeen", + "119": "Seaking", + "120": "Staryu", + "121": "Starmie", + "122": "Mr. Mime", + "123": "Scyther", + "124": "Jynx", + "125": "Electabuzz", + "126": "Magmar", + "127": "Pinsir", + "128": "Tauros", + "129": "Magikarp", + "130": "Gyarados", + "131": "Lapras", + "132": "Ditto", + "133": "Eevee", + "134": "Vaporeon", + "135": "Jolteon", + "136": "Flareon", + "137": "Porygon", + "138": "Omanyte", + "139": "Omastar", + "140": "Kabuto", + "141": "Kabutops", + "142": "Aerodactyl", + "143": "Snorlax", + "144": "Articuno", + "145": "Zapdos", + "146": "Moltres", + "147": "Dratini", + "148": "Dragonair", + "149": "Dragonite", + "150": "Mewtwo", + "151": "Mew", + "152": "Chikorita", + "153": "Bayleef", + "154": "Meganium", + "155": "Cyndaquil", + "156": "Quilava", + "157": "Typhlosion", + "158": "Totodile", + "159": "Croconaw", + "160": "Feraligatr", + "161": "Sentret", + "162": "Furret", + "163": "Hoothoot", + "164": "Noctowl", + "165": "Ledyba", + "166": "Ledian", + "167": "Spinarak", + "168": "Ariados", + "169": "Crobat", + "170": "Chinchou", + "171": "Lanturn", + "172": "Pichu", + "173": "Cleffa", + "174": "Igglybuff", + "175": "Togepi", + "176": "Togetic", + "177": "Natu", + "178": "Xatu", + "179": "Mareep", + "180": "Flaaffy", + "181": "Ampharos", + "182": "Bellossom", + "183": "Marill", + "184": "Azumarill", + "185": "Sudowoodo", + "186": "Politoed", + "187": "Hoppip", + "188": "Skiploom", + "189": "Jumpluff", + "190": "Aipom", + "191": "Sunkern", + "192": "Sunflora", + "193": "Yanma", + "194": "Wooper", + "195": "Quagsire", + "196": "Espeon", + "197": "Umbreon", + "198": "Murkrow", + "199": "Slowking", + "200": "Misdreavus", + "201": "Unown", + "202": "Wobbuffet", + "203": "Girafarig", + "204": "Pineco", + "205": "Forretress", + "206": "Dunsparce", + "207": "Gligar", + "208": "Steelix", + "209": "Snubbull", + "210": "Granbull", + "211": "Qwilfish", + "212": "Scizor", + "213": "Shuckle", + "214": "Heracross", + "215": "Sneasel", + "216": "Teddiursa", + "217": "Ursaring", + "218": "Slugma", + "219": "Magcargo", + "220": "Swinub", + "221": "Piloswine", + "222": "Corsola", + "223": "Remoraid", + "224": "Octillery", + "225": "Delibird", + "226": "Mantine", + "227": "Skarmory", + "228": "Houndour", + "229": "Houndoom", + "230": "Kingdra", + "231": "Phanpy", + "232": "Donphan", + "233": "Porygon2", + "234": "Stantler", + "235": "Smeargle", + "236": "Tyrogue", + "237": "Hitmontop", + "238": "Smoochum", + "239": "Elekid", + "240": "Magby", + "241": "Miltank", + "242": "Blissey", + "243": "Raikou", + "244": "Entei", + "245": "Suicune", + "246": "Larvitar", + "247": "Pupitar", + "248": "Tyranitar", + "249": "Lugia", + "250": "Ho-Oh", + "251": "Celebi", + "252": "Treecko", + "253": "Grovyle", + "254": "Sceptile", + "255": "Torchic", + "256": "Combusken", + "257": "Blaziken", + "258": "Mudkip", + "259": "Marshtomp", + "260": "Swampert", + "261": "Poochyena", + "262": "Mightyena", + "263": "Zigzagoon", + "264": "Linoone", + "265": "Wurmple", + "266": "Silcoon", + "267": "Beautifly", + "268": "Cascoon", + "269": "Dustox", + "270": "Lotad", + "271": "Lombre", + "272": "Ludicolo", + "273": "Seedot", + "274": "Nuzleaf", + "275": "Shiftry", + "276": "Taillow", + "277": "Swellow", + "278": "Wingull", + "279": "Pelipper", + "280": "Ralts", + "281": "Kirlia", + "282": "Gardevoir", + "283": "Surskit", + "284": "Masquerain", + "285": "Shroomish", + "286": "Breloom", + "287": "Slakoth", + "288": "Vigoroth", + "289": "Slaking", + "290": "Nincada", + "291": "Ninjask", + "292": "Shedinja", + "293": "Whismur", + "294": "Loudred", + "295": "Exploud", + "296": "Makuhita", + "297": "Hariyama", + "298": "Azurill", + "299": "Nosepass", + "300": "Skitty", + "301": "Delcatty", + "302": "Sableye", + "303": "Mawile", + "304": "Aron", + "305": "Lairon", + "306": "Aggron", + "307": "Meditite", + "308": "Medicham", + "309": "Electrike", + "310": "Manectric", + "311": "Plusle", + "312": "Minun", + "313": "Volbeat", + "314": "Illumise", + "315": "Roselia", + "316": "Gulpin", + "317": "Swalot", + "318": "Carvanha", + "319": "Sharpedo", + "320": "Wailmer", + "321": "Wailord", + "322": "Numel", + "323": "Camerupt", + "324": "Torkoal", + "325": "Spoink", + "326": "Grumpig", + "327": "Spinda", + "328": "Trapinch", + "329": "Vibrava", + "330": "Flygon", + "331": "Cacnea", + "332": "Cacturne", + "333": "Swablu", + "334": "Altaria", + "335": "Zangoose", + "336": "Seviper", + "337": "Lunatone", + "338": "Solrock", + "339": "Barboach", + "340": "Whiscash", + "341": "Corphish", + "342": "Crawdaunt", + "343": "Baltoy", + "344": "Claydol", + "345": "Lileep", + "346": "Cradily", + "347": "Anorith", + "348": "Armaldo", + "349": "Feebas", + "350": "Milotic", + "351": "Castform", + "352": "Kecleon", + "353": "Shuppet", + "354": "Banette", + "355": "Duskull", + "356": "Dusclops", + "357": "Tropius", + "358": "Chimecho", + "359": "Absol", + "360": "Wynaut", + "361": "Snorunt", + "362": "Glalie", + "363": "Spheal", + "364": "Sealeo", + "365": "Walrein", + "366": "Clamperl", + "367": "Huntail", + "368": "Gorebyss", + "369": "Relicanth", + "370": "Luvdisc", + "371": "Bagon", + "372": "Shelgon", + "373": "Salamence", + "374": "Beldum", + "375": "Metang", + "376": "Metagross", + "377": "Regirock", + "378": "Regice", + "379": "Registeel", + "380": "Latias", + "381": "Latios", + "382": "Kyogre", + "383": "Groudon", + "384": "Rayquaza", + "385": "Jirachi", + "386": "Deoxys", + "387": "Turtwig", + "388": "Grotle", + "389": "Torterra", + "390": "Chimchar", + "391": "Monferno", + "392": "Infernape", + "393": "Piplup", + "394": "Prinplup", + "395": "Empoleon", + "396": "Starly", + "397": "Staravia", + "398": "Staraptor", + "399": "Bidoof", + "400": "Bibarel", + "401": "Kricketot", + "402": "Kricketune", + "403": "Shinx", + "404": "Luxio", + "405": "Luxray", + "406": "Budew", + "407": "Roserade", + "408": "Cranidos", + "409": "Rampardos", + "410": "Shieldon", + "411": "Bastiodon", + "412": "Burmy", + "413": "Wormadam", + "414": "Mothim", + "415": "Combee", + "416": "Vespiquen", + "417": "Pachirisu", + "418": "Buizel", + "419": "Floatzel", + "420": "Cherubi", + "421": "Cherrim", + "422": "Shellos", + "423": "Gastrodon", + "424": "Ambipom", + "425": "Drifloon", + "426": "Drifblim", + "427": "Buneary", + "428": "Lopunny", + "429": "Mismagius", + "430": "Honchkrow", + "431": "Glameow", + "432": "Purugly", + "433": "Chingling", + "434": "Stunky", + "435": "Skuntank", + "436": "Bronzor", + "437": "Bronzong", + "438": "Bonsly", + "439": "Mime Jr.", + "440": "Happiny", + "441": "Chatot", + "442": "Spiritomb", + "443": "Gible", + "444": "Gabite", + "445": "Garchomp", + "446": "Munchlax", + "447": "Riolu", + "448": "Lucario", + "449": "Hippopotas", + "450": "Hippowdon", + "451": "Skorupi", + "452": "Drapion", + "453": "Croagunk", + "454": "Toxicroak", + "455": "Carnivine", + "456": "Finneon", + "457": "Lumineon", + "458": "Mantyke", + "459": "Snover", + "460": "Abomasnow", + "461": "Weavile", + "462": "Magnezone", + "463": "Lickilicky", + "464": "Rhyperior", + "465": "Tangrowth", + "466": "Electivire", + "467": "Magmortar", + "468": "Togekiss", + "469": "Yanmega", + "470": "Leafeon", + "471": "Glaceon", + "472": "Gliscor", + "473": "Mamoswine", + "474": "Porygon-Z", + "475": "Gallade", + "476": "Probopass", + "477": "Dusknoir", + "478": "Froslass", + "479": "Rotom", + "480": "Uxie", + "481": "Mesprit", + "482": "Azelf", + "483": "Dialga", + "484": "Palkia", + "485": "Heatran", + "486": "Regigigas", + "487": "Giratina", + "488": "Cresselia", + "489": "Phione", + "490": "Manaphy", + "491": "Darkrai", + "492": "Shaymin", + "493": "Arceus", + "494": "Victini", + "495": "Snivy", + "496": "Servine", + "497": "Serperior", + "498": "Tepig", + "499": "Pignite", + "500": "Emboar", + "501": "Oshawott", + "502": "Dewott", + "503": "Samurott", + "504": "Patrat", + "505": "Watchog", + "506": "Lillipup", + "507": "Herdier", + "508": "Stoutland", + "509": "Purrloin", + "510": "Liepard", + "511": "Pansage", + "512": "Simisage", + "513": "Pansear", + "514": "Simisear", + "515": "Panpour", + "516": "Simipour", + "517": "Munna", + "518": "Musharna", + "519": "Pidove", + "520": "Tranquill", + "521": "Unfezant", + "522": "Blitzle", + "523": "Zebstrika", + "524": "Roggenrola", + "525": "Boldore", + "526": "Gigalith", + "527": "Woobat", + "528": "Swoobat", + "529": "Drilbur", + "530": "Excadrill", + "531": "Audino", + "532": "Timburr", + "533": "Gurdurr", + "534": "Conkeldurr", + "535": "Tympole", + "536": "Palpitoad", + "537": "Seismitoad", + "538": "Throh", + "539": "Sawk", + "540": "Sewaddle", + "541": "Swadloon", + "542": "Leavanny", + "543": "Venipede", + "544": "Whirlipede", + "545": "Scolipede", + "546": "Cottonee", + "547": "Whimsicott", + "548": "Petilil", + "549": "Lilligant", + "550": "Basculin", + "551": "Sandile", + "552": "Krokorok", + "553": "Krookodile", + "554": "Darumaka", + "555": "Darmanitan", + "556": "Maractus", + "557": "Dwebble", + "558": "Crustle", + "559": "Scraggy", + "560": "Scrafty", + "561": "Sigilyph", + "562": "Yamask", + "563": "Cofagrigus", + "564": "Tirtouga", + "565": "Carracosta", + "566": "Archen", + "567": "Archeops", + "568": "Trubbish", + "569": "Garbodor", + "570": "Zorua", + "571": "Zoroark", + "572": "Minccino", + "573": "Cinccino", + "574": "Gothita", + "575": "Gothorita", + "576": "Gothitelle", + "577": "Solosis", + "578": "Duosion", + "579": "Reuniclus", + "580": "Ducklett", + "581": "Swanna", + "582": "Vanillite", + "583": "Vanillish", + "584": "Vanilluxe", + "585": "Deerling", + "586": "Sawsbuck", + "587": "Emolga", + "588": "Karrablast", + "589": "Escavalier", + "590": "Foongus", + "591": "Amoonguss", + "592": "Frillish", + "593": "Jellicent", + "594": "Alomomola", + "595": "Joltik", + "596": "Galvantula", + "597": "Ferroseed", + "598": "Ferrothorn", + "599": "Klink", + "600": "Klang", + "601": "Klinklang", + "602": "Tynamo", + "603": "Eelektrik", + "604": "Eelektross", + "605": "Elgyem", + "606": "Beheeyem", + "607": "Litwick", + "608": "Lampent", + "609": "Chandelure", + "610": "Axew", + "611": "Fraxure", + "612": "Haxorus", + "613": "Cubchoo", + "614": "Beartic", + "615": "Cryogonal", + "616": "Shelmet", + "617": "Accelgor", + "618": "Stunfisk", + "619": "Mienfoo", + "620": "Mienshao", + "621": "Druddigon", + "622": "Golett", + "623": "Golurk", + "624": "Pawniard", + "625": "Bisharp", + "626": "Bouffalant", + "627": "Rufflet", + "628": "Braviary", + "629": "Vullaby", + "630": "Mandibuzz", + "631": "Heatmor", + "632": "Durant", + "633": "Deino", + "634": "Zweilous", + "635": "Hydreigon", + "636": "Larvesta", + "637": "Volcarona", + "638": "Cobalion", + "639": "Terrakion", + "640": "Virizion", + "641": "Tornadus", + "642": "Thundurus", + "643": "Reshiram", + "644": "Zekrom", + "645": "Landorus", + "646": "Kyurem", + "647": "Keldeo", + "648": "Meloetta", + "649": "Genesect", + "650": "Chespin", + "651": "Quilladin", + "652": "Chesnaught", + "653": "Fennekin", + "654": "Braixen", + "655": "Delphox", + "656": "Froakie", + "657": "Frogadier", + "658": "Greninja", + "659": "Bunnelby", + "660": "Diggersby", + "661": "Fletchling", + "662": "Fletchinder", + "663": "Talonflame", + "664": "Scatterbug", + "665": "Spewpa", + "666": "Vivillon", + "667": "Litleo", + "668": "Pyroar", + "669": "Flab\u00e9b\u00e9", + "670": "Floette", + "671": "Florges", + "672": "Skiddo", + "673": "Gogoat", + "674": "Pancham", + "675": "Pangoro", + "676": "Furfrou", + "677": "Espurr", + "678": "Meowstic", + "679": "Honedge", + "680": "Doublade", + "681": "Aegislash", + "682": "Spritzee", + "683": "Aromatisse", + "684": "Swirlix", + "685": "Slurpuff", + "686": "Inkay", + "687": "Malamar", + "688": "Binacle", + "689": "Barbaracle", + "690": "Skrelp", + "691": "Dragalge", + "692": "Clauncher", + "693": "Clawitzer", + "694": "Helioptile", + "695": "Heliolisk", + "696": "Tyrunt", + "697": "Tyrantrum", + "698": "Amaura", + "699": "Aurorus", + "700": "Sylveon", + "701": "Hawlucha", + "702": "Dedenne", + "703": "Carbink", + "704": "Goomy", + "705": "Sliggoo", + "706": "Goodra", + "707": "Klefki", + "708": "Phantump", + "709": "Trevenant", + "710": "Pumpkaboo", + "711": "Gourgeist", + "712": "Bergmite", + "713": "Avalugg", + "714": "Noibat", + "715": "Noivern", + "716": "Xerneas", + "717": "Yveltal", + "718": "Zygarde", + "719": "Diancie", + "720": "Hoopa", "721": "Volcanion" - }, + }, + "sizes": { + "001": "diminuto", + "002": "peque\u00f1o", + "003": "normal", + "004": "grande", + "005": "enorme" + }, "teams": { - "0": "Neutral", - "1": "Sabidur\u00eda", - "2": "Valor", - "3": "Instinto" - }, + "000": "Neutral", + "001": "Sabidur\u00eda", + "002": "Valor", + "003": "Instinto" + }, + "types": { + "001": "Normal", + "002": "Lucha", + "003": "Volador", + "004": "Veneno", + "005": "Tierra", + "006": "Roca", + "007": "Bicho", + "008": "Fantasma", + "009": "Acero", + "010": "Fuego", + "011": "Agua", + "012": "Planta", + "013": "El\u00e9ctrico", + "014": "Ps\u00edquico", + "015": "Hielo", + "016": "Drag\u00f3n", + "017": "Hada", + "018": "Siniestro" + }, "weather": { - "0": "None", - "1": "Despejado", - "2": "Lluvioso", - "3": "Parcialmente nublado", - "4": "Cielo cubierto", - "5": "Viento", - "6": "Nieve", - "7": "Niebla" - }, - "misc": { - "boosted": "potenciado" + "000": "None", + "001": "Despejado", + "002": "Lluvioso", + "003": "Parcialmente nublado", + "004": "Cielo cubierto", + "005": "Viento", + "006": "Nieve", + "007": "Niebla" } -} +} \ No newline at end of file diff --git a/locales/fr.json b/locales/fr.json index 1f5c1b9d9..fd12f5f7d 100644 --- a/locales/fr.json +++ b/locales/fr.json @@ -1,961 +1,981 @@ { + "costumes": { + "025": { + "001": "Chapeau de Vacances", + "002": "Chapeau de F\u00eate", + "003": "Chapeau de Ash", + "004": "Chapeau de Sorci\u00e8re" + }, + "026": { + "001": "Chapeau de Vacances", + "002": "Chapeau de F\u00eate", + "003": "Chapeau de Ash", + "004": "Chapeau de Sorci\u00e8re" + }, + "172": { + "001": "Chapeau de Vacances", + "002": "Chapeau de F\u00eate", + "003": "Chapeau de Ash", + "004": "Chapeau de Sorci\u00e8re" + } + }, "leaders": { - "0": "Professeur Saule", - "1": "Blanche", - "2": "Candela", - "3": "Spark" - }, - "sizes": { - "1": "minuscule", - "2": "petite", - "3": "normale", - "4": "grand", - "5": "\u00E9norme" - }, - "types": { - "1": "Normal", - "2": "Combattre", - "3": "Voler", - "4": "Poison", - "5": "Terre", - "6": "Roche", - "7": "Insecte", - "8": "Fant\u00F4me", - "9": "Acier", - "10": "Feu", - "11": "Eau", - "12": "Herbe", - "13": "\u00E9lectrique", - "14": "Psychique", - "15": "Glace", - "16": "Dragon", - "17": "F\u00E9e", - "18": "Sombre" - }, + "000": "Professeur Saule", + "001": "Blanche", + "002": "Candela", + "003": "Spark" + }, + "misc": { + "boosted": "boost\u00e9" + }, "moves": { - "13": "Ligotage", - "14": "Ultralaser", - "16": "Vibrobscur", - "18": "D\u00e9tritus", - "20": "Force Poigne", - "21": "Roue de Feu", - "22": "M\u00e9gacorne", - "24": "Lance-Flammes", - "26": "Tunnel", - "28": "Coup-Croix", - "30": "Rafale Psy", - "31": "S\u00e9isme", - "32": "Lame de Roc", - "33": "Poing-Glace", - "34": "Cr\u00e8vec\u0153ur", - "35": "Coup d'Jus", - "36": "Luminocanon", - "38": "Bec Vrille", - "39": "LaserGlace", - "40": "Blizzard", - "42": "Canicule", - "45": "A\u00e9ropique", - "46": "Tunnelier", - "47": "Temp\u00eate Florale", - "48": "M\u00e9ga-Sangsue", - "49": "Bourdon", - "50": "Crochet Venin", - "51": "Tranche-Nuit", - "53": "Bullesd\u2019O", - "54": "Sacrifice", - "56": "Balayette", - "57": "Aqua-Jet", - "58": "Hydroqueue", - "59": "Canon Graine", - "60": "Choc Psy", - "62": "Pouvoir Antique", - "63": "Tomberoche", - "64": "\u00c9boulement", - "65": "Rayon Gemme", - "66": "Ombre Port\u00e9e", - "67": "Poing Ombre", - "69": "Vent Mauvais", - "70": "Ball'Ombre", - "72": "Bombaimant", - "74": "T\u00eatedeFer", - "75": "Parabocharge", - "77": "Poing-\u00c9clair", - "78": "Fatal-Foudre", - "79": "Tonnerre", - "80": "Ouragan", - "82": "Dracochoc", - "83": "Dracogriffe", - "84": "Voix Enj\u00f4leuse", - "85": "Vampibaiser", - "86": "\u00c9clat Magique", - "87": "Pouvoir Lunaire", - "88": "C\u00e2linerie", - "89": "Poison-Croix", - "90": "Bomb-Beurk", - "91": "Cradovague", - "92": "D\u00e9tricanon", - "94": "Massd'Os", - "95": "Pi\u00e9tisol", - "96": "Boue-Bombe", - "99": "Rayon Signal", - "100": "Plaie-Croix", - "101": "Nitrocharge", - "102": "Rebondifeu", - "103": "D\u00e9flagration", - "104": "Saumure", - "105": "Vibraqua", - "106": "\u00c9bullition", - "107": "Hydrocanon", - "108": "Psyko", - "109": "Frappe Psy", - "111": "Vent Glace", - "114": "Giga-Sangsue", - "115": "Poing de Feu", - "116": "Lance-Soleil", - "117": "Lame-Feuille", - "118": "M\u00e9gafouet", - "121": "Tranch'Air", - "122": "Vent Violent", - "123": "Casse-Brique", - "125": "M\u00e9t\u00e9ores", - "126": "Koud'Korne", - "127": "\u00c9crasement", - "129": "Croc de Mort", - "131": "Plaquage", - "132": "Repos", - "133": "Lutte", - "200": "Taillade", - "201": "Piq\u00fbre", - "202": "Morsure", - "203": "Coup Bas", - "204": "Dracosouffle", - "205": "\u00c9clair", - "206": "\u00c9tincelle", - "207": "Balayage", - "208": "Poing-Karat\u00e9", - "209": "Flamm\u00e8che", - "210": "Cru-Aile", - "211": "Picpic", - "212": "L\u00e9chouille", - "213": "Griffe Ombre", - "214": "Fouet Lianes", - "215": "Tranch'Herbe", - "216": "Tir de Boue", - "217": "\u00c9clats Glace", - "218": "Souffle Glac\u00e9", - "219": "Vive-Attaque", - "220": "Griffe", - "221": "Charge", - "222": "\u00c9cras'Face", - "223": "Coupe", - "224": "Direct Toxik", - "225": "Acide", - "226": "Coupe Psycho", - "227": "Jet-Pierres", - "228": "Griffe Acier", - "229": "Pisto-Poing", - "230": "Pistolet \u00e0 O", - "231": "Trempette", - "233": "Coud'Boue", - "234": "Psykoud'Boul", - "235": "Choc Mental", - "236": "Dard-Venin", - "237": "\u00c9cume", - "238": "Feinte", - "239": "Aile d'Acier", - "240": "Crocs Feu", - "241": "\u00c9clate-Roc", - "242": "Morphing", - "243": "Riposte", - "244": "Poudreuse", - "245": "Close Combat", - "246": "Dynamopoing", - "247": "Exploforce", - "248": "Onde Bor\u00e9ale", - "249": "Rayon Charg\u00e9", - "250": "Change \u00c9clair", - "251": "\u00c9clair Fou", - "252": "\u00c9lecanon", - "253": "Draco-Queue", - "254": "Avalanche", - "255": "Lame d'Air", - "256": "Rapace", - "257": "Pique", - "258": "Tourbi-Sable", - "259": "Boule Roc", - "260": "Harc\u00e8lement", - "261": "Survinsecte", - "262": "Vent Argent\u00e9", - "263": "Etonnement", - "264": "Ch\u00e2timent", - "265": "T\u00e9n\u00e8bres", - "266": "Queue De Fer", - "267": "Gyroballe", - "268": "Tacle Lourd", - "269": "Danse Flamme", - "270": "Surchauffe", - "271": "Balle Graine", - "272": "Noeud Herbe", - "273": "Eco-Sph\u00e8re", - "274": "Extrasenseur", - "275": "Prescience", - "276": "Voile Miroir", - "277": "Col\u00e8re", - "278": "Aboiement", - "279": "Machouille", - "280": "Tricherie", - "281": "Puissance Cach\u00e9e", - "282": "B\u0351lier", - "283": "Cascade", - "284": "Surf", - "285": "Draco M\u0351t\u0351ore", - "286": "Carnareket", - "287": "B\u0342illement", - "288": "Psycho Boost", - "289": "Onde Originelle", - "290": "Lame Pang\u0351enne", + "013": "Ligotage", + "014": "Ultralaser", + "016": "Vibrobscur", + "018": "D\u00e9tritus", + "020": "Force Poigne", + "021": "Roue de Feu", + "022": "M\u00e9gacorne", + "024": "Lance-Flammes", + "026": "Tunnel", + "028": "Coup-Croix", + "030": "Rafale Psy", + "031": "S\u00e9isme", + "032": "Lame de Roc", + "033": "Poing-Glace", + "034": "Cr\u00e8vec\u0153ur", + "035": "Coup d'Jus", + "036": "Luminocanon", + "038": "Bec Vrille", + "039": "LaserGlace", + "040": "Blizzard", + "042": "Canicule", + "045": "A\u00e9ropique", + "046": "Tunnelier", + "047": "Temp\u00eate Florale", + "048": "M\u00e9ga-Sangsue", + "049": "Bourdon", + "050": "Crochet Venin", + "051": "Tranche-Nuit", + "053": "Bullesd\u2019O", + "054": "Sacrifice", + "056": "Balayette", + "057": "Aqua-Jet", + "058": "Hydroqueue", + "059": "Canon Graine", + "060": "Choc Psy", + "062": "Pouvoir Antique", + "063": "Tomberoche", + "064": "\u00c9boulement", + "065": "Rayon Gemme", + "066": "Ombre Port\u00e9e", + "067": "Poing Ombre", + "069": "Vent Mauvais", + "070": "Ball'Ombre", + "072": "Bombaimant", + "074": "T\u00eatedeFer", + "075": "Parabocharge", + "077": "Poing-\u00c9clair", + "078": "Fatal-Foudre", + "079": "Tonnerre", + "080": "Ouragan", + "082": "Dracochoc", + "083": "Dracogriffe", + "084": "Voix Enj\u00f4leuse", + "085": "Vampibaiser", + "086": "\u00c9clat Magique", + "087": "Pouvoir Lunaire", + "088": "C\u00e2linerie", + "089": "Poison-Croix", + "090": "Bomb-Beurk", + "091": "Cradovague", + "092": "D\u00e9tricanon", + "094": "Massd'Os", + "095": "Pi\u00e9tisol", + "096": "Boue-Bombe", + "099": "Rayon Signal", + "100": "Plaie-Croix", + "101": "Nitrocharge", + "102": "Rebondifeu", + "103": "D\u00e9flagration", + "104": "Saumure", + "105": "Vibraqua", + "106": "\u00c9bullition", + "107": "Hydrocanon", + "108": "Psyko", + "109": "Frappe Psy", + "111": "Vent Glace", + "114": "Giga-Sangsue", + "115": "Poing de Feu", + "116": "Lance-Soleil", + "117": "Lame-Feuille", + "118": "M\u00e9gafouet", + "121": "Tranch'Air", + "122": "Vent Violent", + "123": "Casse-Brique", + "125": "M\u00e9t\u00e9ores", + "126": "Koud'Korne", + "127": "\u00c9crasement", + "129": "Croc de Mort", + "131": "Plaquage", + "132": "Repos", + "133": "Lutte", + "200": "Taillade", + "201": "Piq\u00fbre", + "202": "Morsure", + "203": "Coup Bas", + "204": "Dracosouffle", + "205": "\u00c9clair", + "206": "\u00c9tincelle", + "207": "Balayage", + "208": "Poing-Karat\u00e9", + "209": "Flamm\u00e8che", + "210": "Cru-Aile", + "211": "Picpic", + "212": "L\u00e9chouille", + "213": "Griffe Ombre", + "214": "Fouet Lianes", + "215": "Tranch'Herbe", + "216": "Tir de Boue", + "217": "\u00c9clats Glace", + "218": "Souffle Glac\u00e9", + "219": "Vive-Attaque", + "220": "Griffe", + "221": "Charge", + "222": "\u00c9cras'Face", + "223": "Coupe", + "224": "Direct Toxik", + "225": "Acide", + "226": "Coupe Psycho", + "227": "Jet-Pierres", + "228": "Griffe Acier", + "229": "Pisto-Poing", + "230": "Pistolet \u00e0 O", + "231": "Trempette", + "233": "Coud'Boue", + "234": "Psykoud'Boul", + "235": "Choc Mental", + "236": "Dard-Venin", + "237": "\u00c9cume", + "238": "Feinte", + "239": "Aile d'Acier", + "240": "Crocs Feu", + "241": "\u00c9clate-Roc", + "242": "Morphing", + "243": "Riposte", + "244": "Poudreuse", + "245": "Close Combat", + "246": "Dynamopoing", + "247": "Exploforce", + "248": "Onde Bor\u00e9ale", + "249": "Rayon Charg\u00e9", + "250": "Change \u00c9clair", + "251": "\u00c9clair Fou", + "252": "\u00c9lecanon", + "253": "Draco-Queue", + "254": "Avalanche", + "255": "Lame d'Air", + "256": "Rapace", + "257": "Pique", + "258": "Tourbi-Sable", + "259": "Boule Roc", + "260": "Harc\u00e8lement", + "261": "Survinsecte", + "262": "Vent Argent\u00e9", + "263": "Etonnement", + "264": "Ch\u00e2timent", + "265": "T\u00e9n\u00e8bres", + "266": "Queue De Fer", + "267": "Gyroballe", + "268": "Tacle Lourd", + "269": "Danse Flamme", + "270": "Surchauffe", + "271": "Balle Graine", + "272": "Noeud Herbe", + "273": "Eco-Sph\u00e8re", + "274": "Extrasenseur", + "275": "Prescience", + "276": "Voile Miroir", + "277": "Col\u00e8re", + "278": "Aboiement", + "279": "Machouille", + "280": "Tricherie", + "281": "Puissance Cach\u00e9e", + "282": "B\u0351lier", + "283": "Cascade", + "284": "Surf", + "285": "Draco M\u0351t\u0351ore", + "286": "Carnareket", + "287": "B\u0342illement", + "288": "Psycho Boost", + "289": "Onde Originelle", + "290": "Lame Pang\u0351enne", "291": "Cadeau" - }, + }, "pokemon": { - "1": "Bulbizarre", - "2": "Herbizarre", - "3": "Florizarre", - "4": "Salam\u00e8che", - "5": "Reptincel", - "6": "Dracaufeu", - "7": "Carapuce", - "8": "Carabaffe", - "9": "Tortank", - "10": "Chenipan", - "11": "Chrysacier", - "12": "Papilusion", - "13": "Aspicot", - "14": "Coconfort", - "15": "Dardargnan", - "16": "Roucool", - "17": "Roucoups", - "18": "Roucarnage", - "19": "Rattata", - "20": "Rattatac", - "21": "Piafabec", - "22": "Rapasdepic", - "23": "Abo", - "24": "Arbok", - "25": "Pikachu", - "26": "Raichu", - "27": "Sabelette", - "28": "Sablaireau", - "29": "Nidoran\u2640", - "30": "Nidorina", - "31": "Nidoqueen", - "32": "Nidoran\u2642", - "33": "Nidorino", - "34": "Nidoking", - "35": "M\u00e9lof\u00e9e", - "36": "M\u00e9lodelfe", - "37": "Goupix", - "38": "Feunard", - "39": "Rondoudou", - "40": "Grodoudou", - "41": "Nosferapti", - "42": "Nosferalto", - "43": "Mystherbe", - "44": "Ortide", - "45": "Rafflesia", - "46": "Paras", - "47": "Parasect", - "48": "Mimitoss", - "49": "A\u00e9romite", - "50": "Taupiqueur", - "51": "Triopikeur", - "52": "Miaouss", - "53": "Persian", - "54": "Psykokwak", - "55": "Akwakwak", - "56": "F\u00e9rosinge", - "57": "Colossinge", - "58": "Caninos", - "59": "Arcanin", - "60": "Ptitard", - "61": "T\u00eatarte", - "62": "Tartard", - "63": "Abra", - "64": "Kadabra", - "65": "Alakazam", - "66": "Machoc", - "67": "Machopeur", - "68": "Mackogneur", - "69": "Ch\u00e9tiflor", - "70": "Boustiflor", - "71": "Empiflor", - "72": "Tentacool", - "73": "Tentacruel", - "74": "Racaillou", - "75": "Gravalanch", - "76": "Grolem", - "77": "Ponyta", - "78": "Galopa", - "79": "Ramoloss", - "80": "Flagadoss", - "81": "Magn\u00e9ti", - "82": "Magn\u00e9ton", - "83": "Canarticho", - "84": "Doduo", - "85": "Dodrio", - "86": "Otaria", - "87": "Lamantine", - "88": "Tadmorv", - "89": "Grotadmorv", - "90": "Kokiyas", - "91": "Crustabri", - "92": "Fantominus", - "93": "Spectrum", - "94": "Ectoplasma", - "95": "Onix", - "96": "Soporifik", - "97": "Hypnomade", - "98": "Krabby", - "99": "Krabboss", - "100": "Voltorbe", - "101": "\u00c9lectrode", - "102": "N\u0153un\u0153uf", - "103": "Noadkoko", - "104": "Osselait", - "105": "Ossatueur", - "106": "Kicklee", - "107": "Tygnon", - "108": "Excelangue", - "109": "Smogo", - "110": "Smogogo", - "111": "Rhinocorne", - "112": "Rhinof\u00e9ros", - "113": "Leveinard", - "114": "Saquedeneu", - "115": "Kangourex", - "116": "Hypotrempe", - "117": "Hypoc\u00e9an", - "118": "Poissir\u00e8ne", - "119": "Poissoroy", - "120": "Stari", - "121": "Staross", - "122": "M.Mime", - "123": "Ins\u00e9cateur", - "124": "Lippoutou", - "125": "\u00c9lektek", - "126": "Magmar", - "127": "Scarabrute", - "128": "Tauros", - "129": "Magicarpe", - "130": "L\u00e9viator", - "131": "Lokhlass", - "132": "M\u00e9tamorph", - "133": "\u00c9voli", - "134": "Aquali", - "135": "Voltali", - "136": "Pyroli", - "137": "Porygon", - "138": "Amonita", - "139": "Amonistar", - "140": "Kabuto", - "141": "Kabutops", - "142": "Pt\u00e9ra", - "143": "Ronflex", - "144": "Artikodin", - "145": "\u00c9lecthor", - "146": "Sulfura", - "147": "Minidraco", - "148": "Draco", - "149": "Dracolosse", - "150": "Mewtwo", - "151": "Mew", - "152": "Germignon", - "153": "Macronium", - "154": "M\u00e9ganium", - "155": "H\u00e9ricendre", - "156": "Feurisson", - "157": "Typhlosion", - "158": "Kaiminus", - "159": "Crocrodil", - "160": "Aligatueur", - "161": "Fouinette", - "162": "Fouinar", - "163": "Hoothoot", - "164": "Noarfang", - "165": "Coxy", - "166": "Coxyclaque", - "167": "Mimigal", - "168": "Migalos", - "169": "Nostenfer", - "170": "Loupio", - "171": "Lanturn", - "172": "Pichu", - "173": "M\u00e9lo", - "174": "Toudoudou", - "175": "Togepi", - "176": "Togetic", - "177": "Natu", - "178": "Xatu", - "179": "Wattouat", - "180": "Lainergie", - "181": "Pharamp", - "182": "Joliflor", - "183": "Marill", - "184": "Azumarill", - "185": "Simularbre", - "186": "Tarpaud", - "187": "Granivol", - "188": "Floravol", - "189": "Cotovol", - "190": "Capumain", - "191": "Tournegrin", - "192": "H\u00e9liatronc", - "193": "Yanma", - "194": "Axoloto", - "195": "Maraiste", - "196": "Mentali", - "197": "Noctali", - "198": "Corn\u00e8bre", - "199": "Roigada", - "200": "Feufor\u00eave", - "201": "Zarbi", - "202": "Qulbutok\u00e9", - "203": "Girafarig", - "204": "Pomdepik", - "205": "Foretress", - "206": "Insolourdo", - "207": "Scorplane", - "208": "Steelix", - "209": "Snubbull", - "210": "Granbull", - "211": "Qwilfish", - "212": "Cizayox", - "213": "Caratroc", - "214": "Scarhino", - "215": "Farfuret", - "216": "Teddiursa", - "217": "Ursaring", - "218": "Limagma", - "219": "Volcaropod", - "220": "Marcacrin", - "221": "Cochignon", - "222": "Corayon", - "223": "R\u00e9moraid", - "224": "Octillery", - "225": "Cadoizo", - "226": "D\u00e9manta", - "227": "Airmure", - "228": "Malosse", - "229": "D\u00e9molosse", - "230": "Hyporoi", - "231": "Phanpy", - "232": "Donphan", - "233": "Porygon2", - "234": "Cerfrousse", - "235": "Queulorior", - "236": "Debugant", - "237": "Kapoera", - "238": "Lippouti", - "239": "\u00c9lekid", - "240": "Magby", - "241": "\u00c9cr\u00e9meuh", - "242": "Leuphorie", - "243": "Raikou", - "244": "Entei", - "245": "Suicune", - "246": "Embrylex", - "247": "Ymphect", - "248": "Tyranocif", - "249": "Lugia", - "250": "Ho-Oh", - "251": "Celebi", - "252": "Arcko", - "253": "Massko", - "254": "Jungko", - "255": "Poussifeu", - "256": "Galifeu", - "257": "Bras\u00e9gali", - "258": "Gobou", - "259": "Flobio", - "260": "Laggron", - "261": "Medhy\u00e8na", - "262": "Grahy\u00e8na", - "263": "Zigzaton", - "264": "Lin\u00e9on", - "265": "Chenipotte", - "266": "Armulys", - "267": "Charmillon", - "268": "Blindalys", - "269": "Papinox", - "270": "N\u00e9nupiot", - "271": "Lombre", - "272": "Ludicolo", - "273": "Grainipiot", - "274": "Pifeuil", - "275": "Tengalice", - "276": "Nirondelle", - "277": "H\u00e9l\u00e9delle", - "278": "Go\u00e9lise", - "279": "Bekipan", - "280": "Tarsal", - "281": "Kirlia", - "282": "Gardevoir", - "283": "Arakdo", - "284": "Maskadra", - "285": "Balignon", - "286": "Chapignon", - "287": "Parecool", - "288": "Vigoroth", - "289": "Monafl\u00e8mit", - "290": "Ningale", - "291": "Ninjask", - "292": "Munja", - "293": "Chuchmur", - "294": "Ramboum", - "295": "Brouhabam", - "296": "Makuhita", - "297": "Hariyama", - "298": "Azurill", - "299": "Tarinor", - "300": "Skitty", - "301": "Delcatty", - "302": "T\u00e9n\u00e9fix", - "303": "Mysdibule", - "304": "Galekid", - "305": "Galegon", - "306": "Galeking", - "307": "M\u00e9ditikka", - "308": "Charmina", - "309": "Dynavolt", - "310": "\u00c9lecsprint", - "311": "Posipi", - "312": "N\u00e9gapi", - "313": "Muciole", - "314": "Lumivole", - "315": "Ros\u00e9lia", - "316": "Gloupti", - "317": "Avaltout", - "318": "Carvanha", - "319": "Sharpedo", - "320": "Wailmer", - "321": "Wailord", - "322": "Chamallot", - "323": "Cam\u00e9rupt", - "324": "Chartor", - "325": "Spoink", - "326": "Groret", - "327": "Spinda", - "328": "Kraknoix", - "329": "Vibraninf", - "330": "Lib\u00e9gon", - "331": "Cacnea", - "332": "Cacturne", - "333": "Tylton", - "334": "Altaria", - "335": "Mangriff", - "336": "S\u00e9viper", - "337": "S\u00e9l\u00e9roc", - "338": "Solaroc", - "339": "Barloche", - "340": "Barbicha", - "341": "\u00c9crapince", - "342": "Colhomard", - "343": "Balbuto", - "344": "Kaorine", - "345": "Lilia", - "346": "Vacilys", - "347": "Anorith", - "348": "Armaldo", - "349": "Barpau", - "350": "Milobellus", - "351": "Morph\u00e9o", - "352": "Kecleon", - "353": "Polichombr", - "354": "Branette", - "355": "Skel\u00e9nox", - "356": "T\u00e9raclope", - "357": "Tropius", - "358": "\u00c9oko", - "359": "Absol", - "360": "Ok\u00e9ok\u00e9", - "361": "Stalgamin", - "362": "Oniglali", - "363": "Obalie", - "364": "Phogleur", - "365": "Kaimorse", - "366": "Coquiperl", - "367": "Serpang", - "368": "Rosabyss", - "369": "Relicanth", - "370": "Lovdisc", - "371": "Draby", - "372": "Drackhaus", - "373": "Drattak", - "374": "Terhal", - "375": "M\u00e9tang", - "376": "M\u00e9talosse", - "377": "Regirock", - "378": "Regice", - "379": "Registeel", - "380": "Latias", - "381": "Latios", - "382": "Kyogre", - "383": "Groudon", - "384": "Rayquaza", - "385": "Jirachi", - "386": "Deoxys", - "387": "Tortipouss", - "388": "Boskara", - "389": "Torterra", - "390": "Ouisticram", - "391": "Chimpenfeu", - "392": "Simiabraz", - "393": "Tiplouf", - "394": "Prinplouf", - "395": "Pingol\u00e9on", - "396": "\u00c9tourmi", - "397": "\u00c9tourvol", - "398": "\u00c9touraptor", - "399": "Keunotor", - "400": "Castorno", - "401": "Crikzik", - "402": "M\u00e9lokrik", - "403": "Lixy", - "404": "Luxio", - "405": "Luxray", - "406": "Rozbouton", - "407": "Roserade", - "408": "Kranidos", - "409": "Charkos", - "410": "Dinoclier", - "411": "Bastiodon", - "412": "Cheniti", - "413": "Cheniselle", - "414": "Papilord", - "415": "Apitrini", - "416": "Apireine", - "417": "Pachirisu", - "418": "Must\u00e9bou\u00e9e", - "419": "Must\u00e9flott", - "420": "Ceribou", - "421": "Ceriflor", - "422": "Sancoki", - "423": "Tritosor", - "424": "Capidextre", - "425": "Baudrive", - "426": "Grodrive", - "427": "Laporeille", - "428": "Lockpin", - "429": "Magir\u00eave", - "430": "Corboss", - "431": "Chaglam", - "432": "Chaffreux", - "433": "Korillon", - "434": "Moufouette", - "435": "Moufflair", - "436": "Arch\u00e9omire", - "437": "Arch\u00e9odong", - "438": "Manza\u00ef", - "439": "Mime Jr", - "440": "Ptiravi", - "441": "Pijako", - "442": "Spiritomb", - "443": "Griknot", - "444": "Carmache", - "445": "Carchacrok", - "446": "Goinfrex", - "447": "Riolu", - "448": "Lucario", - "449": "Hippopotas", - "450": "Hippodocus", - "451": "Rapion", - "452": "Drascore", - "453": "Cradopaud", - "454": "Coatox", - "455": "Vortente", - "456": "\u00c9cayon", - "457": "Lumin\u00e9on", - "458": "Babimanta", - "459": "Blizzi", - "460": "Blizzaroi", - "461": "Dimoret", - "462": "Magn\u00e9zone", - "463": "Coudlangue", - "464": "Rhinastoc", - "465": "Bouldeneu", - "466": "\u00c9lekable", - "467": "Maganon", - "468": "Togekiss", - "469": "Yanm\u00e9ga", - "470": "Phyllali", - "471": "Givrali", - "472": "Scorvol", - "473": "Mammochon", - "474": "Porygon-Z", - "475": "Gallame", - "476": "Tarinorme", - "477": "Noctunoir", - "478": "Momartik", - "479": "Motisma", - "480": "Cr\u00e9helf", - "481": "Cr\u00e9follet", - "482": "Cr\u00e9fadet", - "483": "Dialga", - "484": "Palkia", - "485": "Heatran", - "486": "Regigigas", - "487": "Giratina", - "488": "Cresselia", - "489": "Phione", - "490": "Manaphy", - "491": "Darkrai", - "492": "Shaymin", - "493": "Arceus", - "494": "Victini", - "495": "Vip\u00e9lierre", - "496": "Lianaja", - "497": "Majaspic", - "498": "Gruikui", - "499": "Grotichon", - "500": "Roitiflam", - "501": "Moustillon", - "502": "Mateloutre", - "503": "Clamiral", - "504": "Ratentif", - "505": "Miradar", - "506": "Ponchiot", - "507": "Ponchien", - "508": "Mastouffe", - "509": "Chacripan", - "510": "L\u00e9opardus", - "511": "Feuillajou", - "512": "Feuiloutan", - "513": "Flamajou", - "514": "Flamoutan", - "515": "Flotajou", - "516": "Flotoutan", - "517": "Munna", - "518": "Mushana", - "519": "Poichigeon", - "520": "Colombeau", - "521": "D\u00e9flaisan", - "522": "Z\u00e9bribon", - "523": "Z\u00e9blitz", - "524": "Nodulithe", - "525": "G\u00e9olithe", - "526": "Gigalithe", - "527": "Chovsourir", - "528": "Rhinolove", - "529": "Rototaupe", - "530": "Minotaupe", - "531": "Nanm\u00e9ou\u00efe", - "532": "Charpenti", - "533": "Ouvrifier", - "534": "B\u00e9tochef", - "535": "Tritonde", - "536": "Batracn\u00e9", - "537": "Crapustule", - "538": "Judokrak", - "539": "Karacl\u00e9e", - "540": "Larveyette", - "541": "Couverdure", - "542": "Manternel", - "543": "Venipatte", - "544": "Scobolide", - "545": "Brutapode", - "546": "Doudouvet", - "547": "Farfaduvet", - "548": "Chlorobule", - "549": "Fragilady", - "550": "Bargantua", - "551": "Masca\u00efman", - "552": "Escroco", - "553": "Crocorible", - "554": "Darumarond", - "555": "Darumacho", - "556": "Maracachi", - "557": "Crabicoque", - "558": "Crabaraque", - "559": "Baggiguane", - "560": "Bagga\u00efd", - "561": "Crypt\u00e9ro", - "562": "Tutafeh", - "563": "Tutankafer", - "564": "Carapagos", - "565": "M\u00e9gapagos", - "566": "Ark\u00e9apti", - "567": "A\u00e9ropt\u00e9ryx", - "568": "Miamiasme", - "569": "Miasmax", - "570": "Zorua", - "571": "Zoroark", - "572": "Chinchidou", - "573": "Pashmilla", - "574": "Scrutella", - "575": "Mesm\u00e9rella", - "576": "Sid\u00e9rella", - "577": "Nucl\u00e9os", - "578": "M\u00e9ios", - "579": "Symbios", - "580": "Couaneton", - "581": "Lakm\u00e9cygne", - "582": "Sorb\u00e9b\u00e9", - "583": "Sorboul", - "584": "Sorbouboul", - "585": "Vivaldaim", - "586": "Haydaim", - "587": "Emolga", - "588": "Carabing", - "589": "Lan\u00e7argot", - "590": "Trompignon", - "591": "Gaulet", - "592": "Viskuse", - "593": "Moyade", - "594": "Mamanbo", - "595": "Statitik", - "596": "Mygavolt", - "597": "Grindur", - "598": "Noacier", - "599": "Tic", - "600": "Clic", - "601": "Cliticlic", - "602": "Anchwatt", - "603": "Lamp\u00e9roie", - "604": "Ohmassacre", - "605": "Lewsor", - "606": "Neitram", - "607": "Fun\u00e9cire", - "608": "M\u00e9lancolux", - "609": "Lugulabre", - "610": "Coupenotte", - "611": "Incisache", - "612": "Tranchodon", - "613": "Polarhume", - "614": "Polagriffe", - "615": "Hexagel", - "616": "Escargaume", - "617": "Limaspeed", - "618": "Limonde", - "619": "Kungfouine", - "620": "Shaofouine", - "621": "Drakkarmin", - "622": "Gringolem", - "623": "Golemastoc", - "624": "Scalpion", - "625": "Scalproie", - "626": "Frison", - "627": "Furaiglon", - "628": "Gueriaigle", - "629": "Vostourno", - "630": "Vaututrice", - "631": "Aflamanoir", - "632": "Fermite", - "633": "Solochi", - "634": "Diamat", - "635": "Trioxhydre", - "636": "Pyronille", - "637": "Pyrax", - "638": "Cobaltium", - "639": "Terrakium", - "640": "Viridium", - "641": "Bor\u00e9as", - "642": "Fulguris", - "643": "Reshiram", - "644": "Zekrom", - "645": "D\u00e9m\u00e9t\u00e9ros", - "646": "Kyurem", - "647": "Keldeo", - "648": "Meloetta", - "649": "Genesect", - "650": "Marisson", - "651": "Bogu\u00e9risse", - "652": "Blind\u00e9pique", - "653": "Feunnec", - "654": "Roussil", - "655": "Goupelin", - "656": "Grenousse", - "657": "Cro\u00e2poral", - "658": "Amphinobi", - "659": "Sapereau", - "660": "Excavarenne", - "661": "Passerouge", - "662": "Braisillon", - "663": "Flambusard", - "664": "L\u00e9pidonille", - "665": "P\u00e9r\u00e9grain", - "666": "Prismillon", - "667": "H\u00e9lionceau", - "668": "N\u00e9m\u00e9lios", - "669": "Flab\u00e9b\u00e9", - "670": "Floette", - "671": "Florges", - "672": "Cabriolaine", - "673": "Chevroum", - "674": "Pandespi\u00e8gle", - "675": "Pandarbare", - "676": "Couafarel", - "677": "Psystigri", - "678": "Mistigrix", - "679": "Monorpale", - "680": "Dimocl\u00e8s", - "681": "Exagide", - "682": "Fluvetin", - "683": "Cocotine", - "684": "Sucroquin", - "685": "Cupcanaille", - "686": "Sepiatop", - "687": "Sepiatroce", - "688": "Opermine", - "689": "Golgopathe", - "690": "Venalgue", - "691": "Kravarech", - "692": "Flingouste", - "693": "Gamblast", - "694": "Galvaran", - "695": "Iguolta", - "696": "Ptyranidur", - "697": "Rexillius", - "698": "Amagara", - "699": "Dragmara", - "700": "Nymphali", - "701": "Brutalibr\u00e9", - "702": "Dedenne", - "703": "Strassie", - "704": "Mucuscule", - "705": "Colimucus", - "706": "Muplodocus", - "707": "Trousselin", - "708": "Broc\u00e9l\u00f4me", - "709": "Dess\u00e9liande", - "710": "Pitrouille", - "711": "Banshitrouye", - "712": "Grela\u00e7on", - "713": "S\u00e9racrawl", - "714": "Sonistrelle", - "715": "Bruyverne", - "716": "Xerneas", - "717": "Yveltal", - "718": "Zygarde", - "719": "Diancie", - "720": "Hoopa", + "001": "Bulbizarre", + "002": "Herbizarre", + "003": "Florizarre", + "004": "Salam\u00e8che", + "005": "Reptincel", + "006": "Dracaufeu", + "007": "Carapuce", + "008": "Carabaffe", + "009": "Tortank", + "010": "Chenipan", + "011": "Chrysacier", + "012": "Papilusion", + "013": "Aspicot", + "014": "Coconfort", + "015": "Dardargnan", + "016": "Roucool", + "017": "Roucoups", + "018": "Roucarnage", + "019": "Rattata", + "020": "Rattatac", + "021": "Piafabec", + "022": "Rapasdepic", + "023": "Abo", + "024": "Arbok", + "025": "Pikachu", + "026": "Raichu", + "027": "Sabelette", + "028": "Sablaireau", + "029": "Nidoran\u2640", + "030": "Nidorina", + "031": "Nidoqueen", + "032": "Nidoran\u2642", + "033": "Nidorino", + "034": "Nidoking", + "035": "M\u00e9lof\u00e9e", + "036": "M\u00e9lodelfe", + "037": "Goupix", + "038": "Feunard", + "039": "Rondoudou", + "040": "Grodoudou", + "041": "Nosferapti", + "042": "Nosferalto", + "043": "Mystherbe", + "044": "Ortide", + "045": "Rafflesia", + "046": "Paras", + "047": "Parasect", + "048": "Mimitoss", + "049": "A\u00e9romite", + "050": "Taupiqueur", + "051": "Triopikeur", + "052": "Miaouss", + "053": "Persian", + "054": "Psykokwak", + "055": "Akwakwak", + "056": "F\u00e9rosinge", + "057": "Colossinge", + "058": "Caninos", + "059": "Arcanin", + "060": "Ptitard", + "061": "T\u00eatarte", + "062": "Tartard", + "063": "Abra", + "064": "Kadabra", + "065": "Alakazam", + "066": "Machoc", + "067": "Machopeur", + "068": "Mackogneur", + "069": "Ch\u00e9tiflor", + "070": "Boustiflor", + "071": "Empiflor", + "072": "Tentacool", + "073": "Tentacruel", + "074": "Racaillou", + "075": "Gravalanch", + "076": "Grolem", + "077": "Ponyta", + "078": "Galopa", + "079": "Ramoloss", + "080": "Flagadoss", + "081": "Magn\u00e9ti", + "082": "Magn\u00e9ton", + "083": "Canarticho", + "084": "Doduo", + "085": "Dodrio", + "086": "Otaria", + "087": "Lamantine", + "088": "Tadmorv", + "089": "Grotadmorv", + "090": "Kokiyas", + "091": "Crustabri", + "092": "Fantominus", + "093": "Spectrum", + "094": "Ectoplasma", + "095": "Onix", + "096": "Soporifik", + "097": "Hypnomade", + "098": "Krabby", + "099": "Krabboss", + "100": "Voltorbe", + "101": "\u00c9lectrode", + "102": "N\u0153un\u0153uf", + "103": "Noadkoko", + "104": "Osselait", + "105": "Ossatueur", + "106": "Kicklee", + "107": "Tygnon", + "108": "Excelangue", + "109": "Smogo", + "110": "Smogogo", + "111": "Rhinocorne", + "112": "Rhinof\u00e9ros", + "113": "Leveinard", + "114": "Saquedeneu", + "115": "Kangourex", + "116": "Hypotrempe", + "117": "Hypoc\u00e9an", + "118": "Poissir\u00e8ne", + "119": "Poissoroy", + "120": "Stari", + "121": "Staross", + "122": "M.Mime", + "123": "Ins\u00e9cateur", + "124": "Lippoutou", + "125": "\u00c9lektek", + "126": "Magmar", + "127": "Scarabrute", + "128": "Tauros", + "129": "Magicarpe", + "130": "L\u00e9viator", + "131": "Lokhlass", + "132": "M\u00e9tamorph", + "133": "\u00c9voli", + "134": "Aquali", + "135": "Voltali", + "136": "Pyroli", + "137": "Porygon", + "138": "Amonita", + "139": "Amonistar", + "140": "Kabuto", + "141": "Kabutops", + "142": "Pt\u00e9ra", + "143": "Ronflex", + "144": "Artikodin", + "145": "\u00c9lecthor", + "146": "Sulfura", + "147": "Minidraco", + "148": "Draco", + "149": "Dracolosse", + "150": "Mewtwo", + "151": "Mew", + "152": "Germignon", + "153": "Macronium", + "154": "M\u00e9ganium", + "155": "H\u00e9ricendre", + "156": "Feurisson", + "157": "Typhlosion", + "158": "Kaiminus", + "159": "Crocrodil", + "160": "Aligatueur", + "161": "Fouinette", + "162": "Fouinar", + "163": "Hoothoot", + "164": "Noarfang", + "165": "Coxy", + "166": "Coxyclaque", + "167": "Mimigal", + "168": "Migalos", + "169": "Nostenfer", + "170": "Loupio", + "171": "Lanturn", + "172": "Pichu", + "173": "M\u00e9lo", + "174": "Toudoudou", + "175": "Togepi", + "176": "Togetic", + "177": "Natu", + "178": "Xatu", + "179": "Wattouat", + "180": "Lainergie", + "181": "Pharamp", + "182": "Joliflor", + "183": "Marill", + "184": "Azumarill", + "185": "Simularbre", + "186": "Tarpaud", + "187": "Granivol", + "188": "Floravol", + "189": "Cotovol", + "190": "Capumain", + "191": "Tournegrin", + "192": "H\u00e9liatronc", + "193": "Yanma", + "194": "Axoloto", + "195": "Maraiste", + "196": "Mentali", + "197": "Noctali", + "198": "Corn\u00e8bre", + "199": "Roigada", + "200": "Feufor\u00eave", + "201": "Zarbi", + "202": "Qulbutok\u00e9", + "203": "Girafarig", + "204": "Pomdepik", + "205": "Foretress", + "206": "Insolourdo", + "207": "Scorplane", + "208": "Steelix", + "209": "Snubbull", + "210": "Granbull", + "211": "Qwilfish", + "212": "Cizayox", + "213": "Caratroc", + "214": "Scarhino", + "215": "Farfuret", + "216": "Teddiursa", + "217": "Ursaring", + "218": "Limagma", + "219": "Volcaropod", + "220": "Marcacrin", + "221": "Cochignon", + "222": "Corayon", + "223": "R\u00e9moraid", + "224": "Octillery", + "225": "Cadoizo", + "226": "D\u00e9manta", + "227": "Airmure", + "228": "Malosse", + "229": "D\u00e9molosse", + "230": "Hyporoi", + "231": "Phanpy", + "232": "Donphan", + "233": "Porygon2", + "234": "Cerfrousse", + "235": "Queulorior", + "236": "Debugant", + "237": "Kapoera", + "238": "Lippouti", + "239": "\u00c9lekid", + "240": "Magby", + "241": "\u00c9cr\u00e9meuh", + "242": "Leuphorie", + "243": "Raikou", + "244": "Entei", + "245": "Suicune", + "246": "Embrylex", + "247": "Ymphect", + "248": "Tyranocif", + "249": "Lugia", + "250": "Ho-Oh", + "251": "Celebi", + "252": "Arcko", + "253": "Massko", + "254": "Jungko", + "255": "Poussifeu", + "256": "Galifeu", + "257": "Bras\u00e9gali", + "258": "Gobou", + "259": "Flobio", + "260": "Laggron", + "261": "Medhy\u00e8na", + "262": "Grahy\u00e8na", + "263": "Zigzaton", + "264": "Lin\u00e9on", + "265": "Chenipotte", + "266": "Armulys", + "267": "Charmillon", + "268": "Blindalys", + "269": "Papinox", + "270": "N\u00e9nupiot", + "271": "Lombre", + "272": "Ludicolo", + "273": "Grainipiot", + "274": "Pifeuil", + "275": "Tengalice", + "276": "Nirondelle", + "277": "H\u00e9l\u00e9delle", + "278": "Go\u00e9lise", + "279": "Bekipan", + "280": "Tarsal", + "281": "Kirlia", + "282": "Gardevoir", + "283": "Arakdo", + "284": "Maskadra", + "285": "Balignon", + "286": "Chapignon", + "287": "Parecool", + "288": "Vigoroth", + "289": "Monafl\u00e8mit", + "290": "Ningale", + "291": "Ninjask", + "292": "Munja", + "293": "Chuchmur", + "294": "Ramboum", + "295": "Brouhabam", + "296": "Makuhita", + "297": "Hariyama", + "298": "Azurill", + "299": "Tarinor", + "300": "Skitty", + "301": "Delcatty", + "302": "T\u00e9n\u00e9fix", + "303": "Mysdibule", + "304": "Galekid", + "305": "Galegon", + "306": "Galeking", + "307": "M\u00e9ditikka", + "308": "Charmina", + "309": "Dynavolt", + "310": "\u00c9lecsprint", + "311": "Posipi", + "312": "N\u00e9gapi", + "313": "Muciole", + "314": "Lumivole", + "315": "Ros\u00e9lia", + "316": "Gloupti", + "317": "Avaltout", + "318": "Carvanha", + "319": "Sharpedo", + "320": "Wailmer", + "321": "Wailord", + "322": "Chamallot", + "323": "Cam\u00e9rupt", + "324": "Chartor", + "325": "Spoink", + "326": "Groret", + "327": "Spinda", + "328": "Kraknoix", + "329": "Vibraninf", + "330": "Lib\u00e9gon", + "331": "Cacnea", + "332": "Cacturne", + "333": "Tylton", + "334": "Altaria", + "335": "Mangriff", + "336": "S\u00e9viper", + "337": "S\u00e9l\u00e9roc", + "338": "Solaroc", + "339": "Barloche", + "340": "Barbicha", + "341": "\u00c9crapince", + "342": "Colhomard", + "343": "Balbuto", + "344": "Kaorine", + "345": "Lilia", + "346": "Vacilys", + "347": "Anorith", + "348": "Armaldo", + "349": "Barpau", + "350": "Milobellus", + "351": "Morph\u00e9o", + "352": "Kecleon", + "353": "Polichombr", + "354": "Branette", + "355": "Skel\u00e9nox", + "356": "T\u00e9raclope", + "357": "Tropius", + "358": "\u00c9oko", + "359": "Absol", + "360": "Ok\u00e9ok\u00e9", + "361": "Stalgamin", + "362": "Oniglali", + "363": "Obalie", + "364": "Phogleur", + "365": "Kaimorse", + "366": "Coquiperl", + "367": "Serpang", + "368": "Rosabyss", + "369": "Relicanth", + "370": "Lovdisc", + "371": "Draby", + "372": "Drackhaus", + "373": "Drattak", + "374": "Terhal", + "375": "M\u00e9tang", + "376": "M\u00e9talosse", + "377": "Regirock", + "378": "Regice", + "379": "Registeel", + "380": "Latias", + "381": "Latios", + "382": "Kyogre", + "383": "Groudon", + "384": "Rayquaza", + "385": "Jirachi", + "386": "Deoxys", + "387": "Tortipouss", + "388": "Boskara", + "389": "Torterra", + "390": "Ouisticram", + "391": "Chimpenfeu", + "392": "Simiabraz", + "393": "Tiplouf", + "394": "Prinplouf", + "395": "Pingol\u00e9on", + "396": "\u00c9tourmi", + "397": "\u00c9tourvol", + "398": "\u00c9touraptor", + "399": "Keunotor", + "400": "Castorno", + "401": "Crikzik", + "402": "M\u00e9lokrik", + "403": "Lixy", + "404": "Luxio", + "405": "Luxray", + "406": "Rozbouton", + "407": "Roserade", + "408": "Kranidos", + "409": "Charkos", + "410": "Dinoclier", + "411": "Bastiodon", + "412": "Cheniti", + "413": "Cheniselle", + "414": "Papilord", + "415": "Apitrini", + "416": "Apireine", + "417": "Pachirisu", + "418": "Must\u00e9bou\u00e9e", + "419": "Must\u00e9flott", + "420": "Ceribou", + "421": "Ceriflor", + "422": "Sancoki", + "423": "Tritosor", + "424": "Capidextre", + "425": "Baudrive", + "426": "Grodrive", + "427": "Laporeille", + "428": "Lockpin", + "429": "Magir\u00eave", + "430": "Corboss", + "431": "Chaglam", + "432": "Chaffreux", + "433": "Korillon", + "434": "Moufouette", + "435": "Moufflair", + "436": "Arch\u00e9omire", + "437": "Arch\u00e9odong", + "438": "Manza\u00ef", + "439": "Mime Jr", + "440": "Ptiravi", + "441": "Pijako", + "442": "Spiritomb", + "443": "Griknot", + "444": "Carmache", + "445": "Carchacrok", + "446": "Goinfrex", + "447": "Riolu", + "448": "Lucario", + "449": "Hippopotas", + "450": "Hippodocus", + "451": "Rapion", + "452": "Drascore", + "453": "Cradopaud", + "454": "Coatox", + "455": "Vortente", + "456": "\u00c9cayon", + "457": "Lumin\u00e9on", + "458": "Babimanta", + "459": "Blizzi", + "460": "Blizzaroi", + "461": "Dimoret", + "462": "Magn\u00e9zone", + "463": "Coudlangue", + "464": "Rhinastoc", + "465": "Bouldeneu", + "466": "\u00c9lekable", + "467": "Maganon", + "468": "Togekiss", + "469": "Yanm\u00e9ga", + "470": "Phyllali", + "471": "Givrali", + "472": "Scorvol", + "473": "Mammochon", + "474": "Porygon-Z", + "475": "Gallame", + "476": "Tarinorme", + "477": "Noctunoir", + "478": "Momartik", + "479": "Motisma", + "480": "Cr\u00e9helf", + "481": "Cr\u00e9follet", + "482": "Cr\u00e9fadet", + "483": "Dialga", + "484": "Palkia", + "485": "Heatran", + "486": "Regigigas", + "487": "Giratina", + "488": "Cresselia", + "489": "Phione", + "490": "Manaphy", + "491": "Darkrai", + "492": "Shaymin", + "493": "Arceus", + "494": "Victini", + "495": "Vip\u00e9lierre", + "496": "Lianaja", + "497": "Majaspic", + "498": "Gruikui", + "499": "Grotichon", + "500": "Roitiflam", + "501": "Moustillon", + "502": "Mateloutre", + "503": "Clamiral", + "504": "Ratentif", + "505": "Miradar", + "506": "Ponchiot", + "507": "Ponchien", + "508": "Mastouffe", + "509": "Chacripan", + "510": "L\u00e9opardus", + "511": "Feuillajou", + "512": "Feuiloutan", + "513": "Flamajou", + "514": "Flamoutan", + "515": "Flotajou", + "516": "Flotoutan", + "517": "Munna", + "518": "Mushana", + "519": "Poichigeon", + "520": "Colombeau", + "521": "D\u00e9flaisan", + "522": "Z\u00e9bribon", + "523": "Z\u00e9blitz", + "524": "Nodulithe", + "525": "G\u00e9olithe", + "526": "Gigalithe", + "527": "Chovsourir", + "528": "Rhinolove", + "529": "Rototaupe", + "530": "Minotaupe", + "531": "Nanm\u00e9ou\u00efe", + "532": "Charpenti", + "533": "Ouvrifier", + "534": "B\u00e9tochef", + "535": "Tritonde", + "536": "Batracn\u00e9", + "537": "Crapustule", + "538": "Judokrak", + "539": "Karacl\u00e9e", + "540": "Larveyette", + "541": "Couverdure", + "542": "Manternel", + "543": "Venipatte", + "544": "Scobolide", + "545": "Brutapode", + "546": "Doudouvet", + "547": "Farfaduvet", + "548": "Chlorobule", + "549": "Fragilady", + "550": "Bargantua", + "551": "Masca\u00efman", + "552": "Escroco", + "553": "Crocorible", + "554": "Darumarond", + "555": "Darumacho", + "556": "Maracachi", + "557": "Crabicoque", + "558": "Crabaraque", + "559": "Baggiguane", + "560": "Bagga\u00efd", + "561": "Crypt\u00e9ro", + "562": "Tutafeh", + "563": "Tutankafer", + "564": "Carapagos", + "565": "M\u00e9gapagos", + "566": "Ark\u00e9apti", + "567": "A\u00e9ropt\u00e9ryx", + "568": "Miamiasme", + "569": "Miasmax", + "570": "Zorua", + "571": "Zoroark", + "572": "Chinchidou", + "573": "Pashmilla", + "574": "Scrutella", + "575": "Mesm\u00e9rella", + "576": "Sid\u00e9rella", + "577": "Nucl\u00e9os", + "578": "M\u00e9ios", + "579": "Symbios", + "580": "Couaneton", + "581": "Lakm\u00e9cygne", + "582": "Sorb\u00e9b\u00e9", + "583": "Sorboul", + "584": "Sorbouboul", + "585": "Vivaldaim", + "586": "Haydaim", + "587": "Emolga", + "588": "Carabing", + "589": "Lan\u00e7argot", + "590": "Trompignon", + "591": "Gaulet", + "592": "Viskuse", + "593": "Moyade", + "594": "Mamanbo", + "595": "Statitik", + "596": "Mygavolt", + "597": "Grindur", + "598": "Noacier", + "599": "Tic", + "600": "Clic", + "601": "Cliticlic", + "602": "Anchwatt", + "603": "Lamp\u00e9roie", + "604": "Ohmassacre", + "605": "Lewsor", + "606": "Neitram", + "607": "Fun\u00e9cire", + "608": "M\u00e9lancolux", + "609": "Lugulabre", + "610": "Coupenotte", + "611": "Incisache", + "612": "Tranchodon", + "613": "Polarhume", + "614": "Polagriffe", + "615": "Hexagel", + "616": "Escargaume", + "617": "Limaspeed", + "618": "Limonde", + "619": "Kungfouine", + "620": "Shaofouine", + "621": "Drakkarmin", + "622": "Gringolem", + "623": "Golemastoc", + "624": "Scalpion", + "625": "Scalproie", + "626": "Frison", + "627": "Furaiglon", + "628": "Gueriaigle", + "629": "Vostourno", + "630": "Vaututrice", + "631": "Aflamanoir", + "632": "Fermite", + "633": "Solochi", + "634": "Diamat", + "635": "Trioxhydre", + "636": "Pyronille", + "637": "Pyrax", + "638": "Cobaltium", + "639": "Terrakium", + "640": "Viridium", + "641": "Bor\u00e9as", + "642": "Fulguris", + "643": "Reshiram", + "644": "Zekrom", + "645": "D\u00e9m\u00e9t\u00e9ros", + "646": "Kyurem", + "647": "Keldeo", + "648": "Meloetta", + "649": "Genesect", + "650": "Marisson", + "651": "Bogu\u00e9risse", + "652": "Blind\u00e9pique", + "653": "Feunnec", + "654": "Roussil", + "655": "Goupelin", + "656": "Grenousse", + "657": "Cro\u00e2poral", + "658": "Amphinobi", + "659": "Sapereau", + "660": "Excavarenne", + "661": "Passerouge", + "662": "Braisillon", + "663": "Flambusard", + "664": "L\u00e9pidonille", + "665": "P\u00e9r\u00e9grain", + "666": "Prismillon", + "667": "H\u00e9lionceau", + "668": "N\u00e9m\u00e9lios", + "669": "Flab\u00e9b\u00e9", + "670": "Floette", + "671": "Florges", + "672": "Cabriolaine", + "673": "Chevroum", + "674": "Pandespi\u00e8gle", + "675": "Pandarbare", + "676": "Couafarel", + "677": "Psystigri", + "678": "Mistigrix", + "679": "Monorpale", + "680": "Dimocl\u00e8s", + "681": "Exagide", + "682": "Fluvetin", + "683": "Cocotine", + "684": "Sucroquin", + "685": "Cupcanaille", + "686": "Sepiatop", + "687": "Sepiatroce", + "688": "Opermine", + "689": "Golgopathe", + "690": "Venalgue", + "691": "Kravarech", + "692": "Flingouste", + "693": "Gamblast", + "694": "Galvaran", + "695": "Iguolta", + "696": "Ptyranidur", + "697": "Rexillius", + "698": "Amagara", + "699": "Dragmara", + "700": "Nymphali", + "701": "Brutalibr\u00e9", + "702": "Dedenne", + "703": "Strassie", + "704": "Mucuscule", + "705": "Colimucus", + "706": "Muplodocus", + "707": "Trousselin", + "708": "Broc\u00e9l\u00f4me", + "709": "Dess\u00e9liande", + "710": "Pitrouille", + "711": "Banshitrouye", + "712": "Grela\u00e7on", + "713": "S\u00e9racrawl", + "714": "Sonistrelle", + "715": "Bruyverne", + "716": "Xerneas", + "717": "Yveltal", + "718": "Zygarde", + "719": "Diancie", + "720": "Hoopa", "721": "Volcanion" - }, + }, + "sizes": { + "001": "minuscule", + "002": "petite", + "003": "normale", + "004": "grand", + "005": "\u00e9norme" + }, "teams": { - "0": "Neutre", - "1": "Sagesse", - "2": "Bravoure", - "3": "Intuition" - }, + "000": "Neutre", + "001": "Sagesse", + "002": "Bravoure", + "003": "Intuition" + }, + "types": { + "001": "Normal", + "002": "Combattre", + "003": "Voler", + "004": "Poison", + "005": "Terre", + "006": "Roche", + "007": "Insecte", + "008": "Fant\u00f4me", + "009": "Acier", + "010": "Feu", + "011": "Eau", + "012": "Herbe", + "013": "\u00e9lectrique", + "014": "Psychique", + "015": "Glace", + "016": "Dragon", + "017": "F\u00e9e", + "018": "Sombre" + }, "weather": { - "0": "Aucun", - "1": "Clair", - "2": "Pluie", - "3": "Partiellement nuageux", - "4": "Nuageux", - "5": "Venteux", - "6": "Neige", - "7": "Brouillard" - }, - "misc": { - "boosted": "boosté" + "000": "Aucun", + "001": "Clair", + "002": "Pluie", + "003": "Partiellement nuageux", + "004": "Nuageux", + "005": "Venteux", + "006": "Neige", + "007": "Brouillard" } -} +} \ No newline at end of file diff --git a/locales/it.json b/locales/it.json index 0dc2ddd43..99bccb689 100644 --- a/locales/it.json +++ b/locales/it.json @@ -1,38 +1,99 @@ { + "costumes": { + "025": { + "001": "Cappello Festiva", + "002": "Cappello da Festa", + "003": "Cappello di Ash", + "004": "Cappello da Strega" + }, + "026": { + "001": "Cappello Festiva", + "002": "Cappello da Festa", + "003": "Cappello di Ash", + "004": "Cappello da Strega" + }, + "172": { + "001": "Cappello Festiva", + "002": "Cappello da Festa", + "003": "Cappello di Ash", + "004": "Cappello da Strega" + } + }, "leaders": { - "0": "Professor Willow", - "1": "Blanche", - "2": "Candela", - "3": "Spark" - }, - "sizes": { - "1": "minuscolo", - "2": "piccolo", - "3": "normale", - "4": "grande", - "5": "enorme" - }, - "types": { - "1": "Normale", - "2": "Combattimento", - "3": "Volare", - "4": "Veleno", - "5": "Terra", - "6": "Rock", - "7": "Roccia", - "8": "Fantasma", - "9": "Acciaio", - "10": "Fuoco", - "11": "Acqua", - "12": "Erba", - "13": "Elettrico", - "14": "Psichico", - "15": "Ghiaccio", - "16": "Drago", - "17": "Fata", - "18": "Scuro" - }, + "000": "Professor Willow", + "001": "Blanche", + "002": "Candela", + "003": "Spark" + }, + "misc": { + "boosted": "potenziato" + }, "moves": { + "013": "Avvolgibotta", + "014": "Iper Raggio", + "016": "Neropulsar", + "018": "Fango", + "020": "Presa", + "021": "Ruotafuoco", + "022": "Megacorno", + "024": "Lanciafiamme", + "026": "Fossa", + "028": "Incrocolpo", + "030": "Psicoraggio", + "031": "Terremoto", + "032": "Pietrataglio", + "033": "Gelopugno", + "034": "Cuorestampo", + "035": "Scarica", + "036": "Cannonflash", + "038": "Perforbecco", + "039": "Geloraggio", + "040": "Bora", + "042": "Ondacalda", + "045": "Aeroassalto", + "046": "Giravvita", + "047": "Fiortempesta", + "048": "Megassorbimento", + "049": "Ronzio", + "050": "Velenodenti", + "051": "Nottesferza", + "053": "Bollaraggio", + "054": "Sottomissione", + "056": "Calciobasso", + "057": "Acquagetto", + "058": "Idrondata", + "059": "Semebomba", + "060": "Psicoshock", + "062": "Forzantica", + "063": "Rocciotomba", + "064": "Frana", + "065": "Gemmoforza", + "066": "Furtivombra", + "067": "Pugnodombra", + "069": "Funestovento", + "070": "Palla Ombra", + "072": "Bombagnete", + "074": "Metaltestata", + "075": "Caricaparabola", + "077": "Tuonopugno", + "078": "Tuono", + "079": "Fulmine", + "080": "Tornado", + "082": "Dragopulsar", + "083": "Dragartigli", + "084": "Incantavoce", + "085": "Assorbibacio", + "086": "Magibrillio", + "087": "Forza Lunare", + "088": "Carineria", + "089": "Velenocroce", + "090": "Fangobomba", + "091": "Fangonda", + "092": "Sporcolancio", + "094": "Ossoclava", + "095": "Battiterra", + "096": "Pantanobomba", + "099": "Segnoraggio", "100": "Forbice X", "101": "Nitrocarica", "102": "Pirolancio", @@ -56,7 +117,6 @@ "126": "Incornata", "127": "Pestone", "129": "Iperzanna", - "13": "Avvolgibotta", "131": "Corposcontro", "132": "Riposo", "133": "Scontro", @@ -64,10 +124,6 @@ "135": "Idropompa (Blastoise)", "136": "Avvolgibotta (Green)", "137": "Avvolgibotta (Pink)", - "14": "Iper Raggio", - "16": "Neropulsar", - "18": "Fango", - "20": "Presa", "200": "Tagliofuria", "201": "Coleomorso", "202": "Morso", @@ -78,7 +134,6 @@ "207": "Colpo Basso", "208": "Colpokarate", "209": "Braciere", - "21": "Ruotafuoco", "210": "Attacco d'Ala", "211": "Beccata", "212": "Leccata", @@ -89,7 +144,6 @@ "217": "Geloscheggia", "218": "Alitogelido", "219": "Attacco Rapido", - "22": "Megacorno", "220": "Graffio", "221": "Azione", "222": "Botta", @@ -109,7 +163,6 @@ "237": "Bolla", "238": "Finta", "239": "Alacciaio", - "24": "Lanciafiamme", "240": "Rogodenti", "241": "Spaccaroccia", "242": "Trasformazione", @@ -130,7 +183,6 @@ "257": "Aeroattacco", "258": "Sabbiotomba", "259": "Cadutamassi", - "26": "Fossa", "260": "Infestatione", "261": "Entomoblocco", "262": "Ventargenteo", @@ -151,79 +203,119 @@ "277": "Oltraggio", "278": "Urlorabbia", "279": "Sgranocchio", - "28": "Incrocolpo", "280": "Ripicca", "281": "Introforza", - "30": "Psicoraggio", - "31": "Terremoto", - "32": "Pietrataglio", - "33": "Gelopugno", - "34": "Cuorestampo", - "35": "Scarica", - "36": "Cannonflash", - "38": "Perforbecco", - "39": "Geloraggio", - "40": "Bora", - "42": "Ondacalda", - "45": "Aeroassalto", - "46": "Giravvita", - "47": "Fiortempesta", - "48": "Megassorbimento", - "49": "Ronzio", - "50": "Velenodenti", - "51": "Nottesferza", - "53": "Bollaraggio", - "54": "Sottomissione", - "56": "Calciobasso", - "57": "Acquagetto", - "58": "Idrondata", - "59": "Semebomba", - "60": "Psicoshock", - "62": "Forzantica", - "63": "Rocciotomba", - "64": "Frana", - "65": "Gemmoforza", - "66": "Furtivombra", - "67": "Pugnodombra", - "69": "Funestovento", - "70": "Palla Ombra", - "72": "Bombagnete", - "74": "Metaltestata", - "75": "Caricaparabola", - "77": "Tuonopugno", - "78": "Tuono", - "79": "Fulmine", - "80": "Tornado", - "82": "Dragopulsar", - "83": "Dragartigli", - "84": "Incantavoce", - "85": "Assorbibacio", - "86": "Magibrillio", - "87": "Forza Lunare", - "88": "Carineria", - "89": "Velenocroce", - "90": "Fangobomba", - "91": "Fangonda", - "92": "Sporcolancio", - "94": "Ossoclava", - "95": "Battiterra", - "96": "Pantanobomba", - "99": "Segnoraggio", - "281": "Introforza", - "282": "Riduttore", - "283": "Cascata", - "284": "Surf", - "285": "Dragobolide", - "286": "Obbliderio", - "287": "Sbadiglio", - "288": "Psicoslancio", - "289": "Primopulsar", - "290": "Spade Telluriche", + "282": "Riduttore", + "283": "Cascata", + "284": "Surf", + "285": "Dragobolide", + "286": "Obbliderio", + "287": "Sbadiglio", + "288": "Psicoslancio", + "289": "Primopulsar", + "290": "Spade Telluriche", "291": "Regalino" }, "pokemon": { - "1": "Bulbasaur", - "10": "Caterpie", + "001": "Bulbasaur", + "002": "Ivysaur", + "003": "Venusaur", + "004": "Charmander", + "005": "Charmeleon", + "006": "Charizard", + "007": "Squirtle", + "008": "Wartortle", + "009": "Blastoise", + "010": "Caterpie", + "011": "Metapod", + "012": "Butterfree", + "013": "Weedle", + "014": "Kakuna", + "015": "Beedrill", + "016": "Pidgey", + "017": "Pidgeotto", + "018": "Pidgeot", + "019": "Rattata", + "020": "Raticate", + "021": "Spearow", + "022": "Fearow", + "023": "Ekans", + "024": "Arbok", + "025": "Pikachu", + "026": "Raichu", + "027": "Sandshrew", + "028": "Sandslash", + "029": "Nidoran\u2640", + "030": "Nidorina", + "031": "Nidoqueen", + "032": "Nidoran\u2642", + "033": "Nidorino", + "034": "Nidoking", + "035": "Clefairy", + "036": "Clefable", + "037": "Vulpix", + "038": "Ninetales", + "039": "Jigglypuff", + "040": "Wigglytuff", + "041": "Zubat", + "042": "Golbat", + "043": "Oddish", + "044": "Gloom", + "045": "Vileplume", + "046": "Paras", + "047": "Parasect", + "048": "Venonat", + "049": "Venomoth", + "050": "Diglett", + "051": "Dugtrio", + "052": "Meowth", + "053": "Persian", + "054": "Psyduck", + "055": "Golduck", + "056": "Mankey", + "057": "Primeape", + "058": "Growlithe", + "059": "Arcanine", + "060": "Poliwag", + "061": "Poliwhirl", + "062": "Poliwrath", + "063": "Abra", + "064": "Kadabra", + "065": "Alakazam", + "066": "Machop", + "067": "Machoke", + "068": "Machamp", + "069": "Bellsprout", + "070": "Weepinbell", + "071": "Victreebel", + "072": "Tentacool", + "073": "Tentacruel", + "074": "Geodude", + "075": "Graveler", + "076": "Golem", + "077": "Ponyta", + "078": "Rapidash", + "079": "Slowpoke", + "080": "Slowbro", + "081": "Magnemite", + "082": "Magneton", + "083": "Farfetch'd", + "084": "Doduo", + "085": "Dodrio", + "086": "Seel", + "087": "Dewgong", + "088": "Grimer", + "089": "Muk", + "090": "Shellder", + "091": "Cloyster", + "092": "Gastly", + "093": "Haunter", + "094": "Gengar", + "095": "Onix", + "096": "Drowzee", + "097": "Hypno", + "098": "Krabby", + "099": "Kingler", "100": "Voltorb", "101": "Electrode", "102": "Exeggcute", @@ -234,7 +326,6 @@ "107": "Hitmonchan", "108": "Lickitung", "109": "Koffing", - "11": "Metapod", "110": "Weezing", "111": "Rhyhorn", "112": "Rhydon", @@ -245,7 +336,6 @@ "117": "Seadra", "118": "Goldeen", "119": "Seaking", - "12": "Butterfree", "120": "Staryu", "121": "Starmie", "122": "Mr. Mime", @@ -256,7 +346,6 @@ "127": "Pinsir", "128": "Tauros", "129": "Magikarp", - "13": "Weedle", "130": "Gyarados", "131": "Lapras", "132": "Ditto", @@ -267,7 +356,6 @@ "137": "Porygon", "138": "Omanyte", "139": "Omastar", - "14": "Kakuna", "140": "Kabuto", "141": "Kabutops", "142": "Aerodactyl", @@ -278,7 +366,6 @@ "147": "Dratini", "148": "Dragonair", "149": "Dragonite", - "15": "Beedrill", "150": "Mewtwo", "151": "Mew", "152": "Chikorita", @@ -289,7 +376,6 @@ "157": "Typhlosion", "158": "Totodile", "159": "Croconaw", - "16": "Pidgey", "160": "Feraligatr", "161": "Sentret", "162": "Furret", @@ -300,7 +386,6 @@ "167": "Spinarak", "168": "Ariados", "169": "Crobat", - "17": "Pidgeotto", "170": "Chinchou", "171": "Lanturn", "172": "Pichu", @@ -311,7 +396,6 @@ "177": "Natu", "178": "Xatu", "179": "Mareep", - "18": "Pidgeot", "180": "Flaaffy", "181": "Ampharos", "182": "Bellossom", @@ -322,7 +406,6 @@ "187": "Hoppip", "188": "Skiploom", "189": "Jumpluff", - "19": "Rattata", "190": "Aipom", "191": "Sunkern", "192": "Sunflora", @@ -333,8 +416,6 @@ "197": "Umbreon", "198": "Murkrow", "199": "Slowking", - "2": "Ivysaur", - "20": "Raticate", "200": "Misdreavus", "201": "Unown", "202": "Wobbuffet", @@ -345,7 +426,6 @@ "207": "Gligar", "208": "Steelix", "209": "Snubbull", - "21": "Spearow", "210": "Granbull", "211": "Qwilfish", "212": "Scizor", @@ -356,7 +436,6 @@ "217": "Ursaring", "218": "Slugma", "219": "Magcargo", - "22": "Fearow", "220": "Swinub", "221": "Piloswine", "222": "Corsola", @@ -367,7 +446,6 @@ "227": "Skarmory", "228": "Houndour", "229": "Houndoom", - "23": "Ekans", "230": "Kingdra", "231": "Phanpy", "232": "Donphan", @@ -378,7 +456,6 @@ "237": "Hitmontop", "238": "Smoochum", "239": "Elekid", - "24": "Arbok", "240": "Magby", "241": "Miltank", "242": "Blissey", @@ -389,7 +466,6 @@ "247": "Pupitar", "248": "Tyranitar", "249": "Lugia", - "25": "Pikachu", "250": "Ho-Oh", "251": "Celebi", "252": "Treecko", @@ -400,7 +476,6 @@ "257": "Blaziken", "258": "Mudkip", "259": "Marshtomp", - "26": "Raichu", "260": "Swampert", "261": "Poochyena", "262": "Mightyena", @@ -411,7 +486,6 @@ "267": "Beautifly", "268": "Cascoon", "269": "Dustox", - "27": "Sandshrew", "270": "Lotad", "271": "Lombre", "272": "Ludicolo", @@ -422,7 +496,6 @@ "277": "Swellow", "278": "Wingull", "279": "Pelipper", - "28": "Sandslash", "280": "Ralts", "281": "Kirlia", "282": "Gardevoir", @@ -433,7 +506,6 @@ "287": "Slakoth", "288": "Vigoroth", "289": "Slaking", - "29": "Nidoran\u2640", "290": "Nincada", "291": "Ninjask", "292": "Shedinja", @@ -444,8 +516,6 @@ "297": "Hariyama", "298": "Azurill", "299": "Nosepass", - "3": "Venusaur", - "30": "Nidorina", "300": "Skitty", "301": "Delcatty", "302": "Sableye", @@ -456,7 +526,6 @@ "307": "Meditite", "308": "Medicham", "309": "Electrike", - "31": "Nidoqueen", "310": "Manectric", "311": "Plusle", "312": "Minun", @@ -467,7 +536,6 @@ "317": "Swalot", "318": "Carvanha", "319": "Sharpedo", - "32": "Nidoran\u2642", "320": "Wailmer", "321": "Wailord", "322": "Numel", @@ -478,7 +546,6 @@ "327": "Spinda", "328": "Trapinch", "329": "Vibrava", - "33": "Nidorino", "330": "Flygon", "331": "Cacnea", "332": "Cacturne", @@ -489,7 +556,6 @@ "337": "Lunatone", "338": "Solrock", "339": "Barboach", - "34": "Nidoking", "340": "Whiscash", "341": "Corphish", "342": "Crawdaunt", @@ -500,7 +566,6 @@ "347": "Anorith", "348": "Armaldo", "349": "Feebas", - "35": "Clefairy", "350": "Milotic", "351": "Castform", "352": "Kecleon", @@ -511,7 +576,6 @@ "357": "Tropius", "358": "Chimecho", "359": "Absol", - "36": "Clefable", "360": "Wynaut", "361": "Snorunt", "362": "Glalie", @@ -522,7 +586,6 @@ "367": "Huntail", "368": "Gorebyss", "369": "Relicanth", - "37": "Vulpix", "370": "Luvdisc", "371": "Bagon", "372": "Shelgon", @@ -533,7 +596,6 @@ "377": "Regirock", "378": "Regice", "379": "Registeel", - "38": "Ninetales", "380": "Latias", "381": "Latios", "382": "Kyogre", @@ -544,7 +606,6 @@ "387": "Turtwig", "388": "Grotle", "389": "Torterra", - "39": "Jigglypuff", "390": "Chimchar", "391": "Monferno", "392": "Infernape", @@ -555,8 +616,6 @@ "397": "Staravia", "398": "Staraptor", "399": "Bidoof", - "4": "Charmander", - "40": "Wigglytuff", "400": "Bibarel", "401": "Kricketot", "402": "Kricketune", @@ -567,7 +626,6 @@ "407": "Roserade", "408": "Cranidos", "409": "Rampardos", - "41": "Zubat", "410": "Shieldon", "411": "Bastiodon", "412": "Burmy", @@ -578,7 +636,6 @@ "417": "Pachirisu", "418": "Buizel", "419": "Floatzel", - "42": "Golbat", "420": "Cherubi", "421": "Cherrim", "422": "Shellos", @@ -589,7 +646,6 @@ "427": "Buneary", "428": "Lopunny", "429": "Mismagius", - "43": "Oddish", "430": "Honchkrow", "431": "Glameow", "432": "Purugly", @@ -600,7 +656,6 @@ "437": "Bronzong", "438": "Bonsly", "439": "Mime Jr.", - "44": "Gloom", "440": "Happiny", "441": "Chatot", "442": "Spiritomb", @@ -611,7 +666,6 @@ "447": "Riolu", "448": "Lucario", "449": "Hippopotas", - "45": "Vileplume", "450": "Hippowdon", "451": "Skorupi", "452": "Drapion", @@ -622,7 +676,6 @@ "457": "Lumineon", "458": "Mantyke", "459": "Snover", - "46": "Paras", "460": "Abomasnow", "461": "Weavile", "462": "Magnezone", @@ -633,7 +686,6 @@ "467": "Magmortar", "468": "Togekiss", "469": "Yanmega", - "47": "Parasect", "470": "Leafeon", "471": "Glaceon", "472": "Gliscor", @@ -644,7 +696,6 @@ "477": "Dusknoir", "478": "Froslass", "479": "Rotom", - "48": "Venonat", "480": "Uxie", "481": "Mesprit", "482": "Azelf", @@ -655,7 +706,6 @@ "487": "Giratina", "488": "Cresselia", "489": "Phione", - "49": "Venomoth", "490": "Manaphy", "491": "Darkrai", "492": "Shaymin", @@ -666,8 +716,6 @@ "497": "Serperior", "498": "Tepig", "499": "Pignite", - "5": "Charmeleon", - "50": "Diglett", "500": "Emboar", "501": "Oshawott", "502": "Dewott", @@ -678,7 +726,6 @@ "507": "Herdier", "508": "Stoutland", "509": "Purrloin", - "51": "Dugtrio", "510": "Liepard", "511": "Pansage", "512": "Simisage", @@ -689,7 +736,6 @@ "517": "Munna", "518": "Musharna", "519": "Pidove", - "52": "Meowth", "520": "Tranquill", "521": "Unfezant", "522": "Blitzle", @@ -700,7 +746,6 @@ "527": "Woobat", "528": "Swoobat", "529": "Drilbur", - "53": "Persian", "530": "Excadrill", "531": "Audino", "532": "Timburr", @@ -711,7 +756,6 @@ "537": "Seismitoad", "538": "Throh", "539": "Sawk", - "54": "Psyduck", "540": "Sewaddle", "541": "Swadloon", "542": "Leavanny", @@ -722,7 +766,6 @@ "547": "Whimsicott", "548": "Petilil", "549": "Lilligant", - "55": "Golduck", "550": "Basculin", "551": "Sandile", "552": "Krokorok", @@ -733,7 +776,6 @@ "557": "Dwebble", "558": "Crustle", "559": "Scraggy", - "56": "Mankey", "560": "Scrafty", "561": "Sigilyph", "562": "Yamask", @@ -744,7 +786,6 @@ "567": "Archeops", "568": "Trubbish", "569": "Garbodor", - "57": "Primeape", "570": "Zorua", "571": "Zoroark", "572": "Minccino", @@ -755,7 +796,6 @@ "577": "Solosis", "578": "Duosion", "579": "Reuniclus", - "58": "Growlithe", "580": "Ducklett", "581": "Swanna", "582": "Vanillite", @@ -766,7 +806,6 @@ "587": "Emolga", "588": "Karrablast", "589": "Escavalier", - "59": "Arcanine", "590": "Foongus", "591": "Amoonguss", "592": "Frillish", @@ -777,8 +816,6 @@ "597": "Ferroseed", "598": "Ferrothorn", "599": "Klink", - "6": "Charizard", - "60": "Poliwag", "600": "Klang", "601": "Klinklang", "602": "Tynamo", @@ -789,7 +826,6 @@ "607": "Litwick", "608": "Lampent", "609": "Chandelure", - "61": "Poliwhirl", "610": "Axew", "611": "Fraxure", "612": "Haxorus", @@ -800,7 +836,6 @@ "617": "Accelgor", "618": "Stunfisk", "619": "Mienfoo", - "62": "Poliwrath", "620": "Mienshao", "621": "Druddigon", "622": "Golett", @@ -811,7 +846,6 @@ "627": "Rufflet", "628": "Braviary", "629": "Vullaby", - "63": "Abra", "630": "Mandibuzz", "631": "Heatmor", "632": "Durant", @@ -822,7 +856,6 @@ "637": "Volcarona", "638": "Cobalion", "639": "Terrakion", - "64": "Kadabra", "640": "Virizion", "641": "Tornadus", "642": "Thundurus", @@ -833,7 +866,6 @@ "647": "Keldeo", "648": "Meloetta", "649": "Genesect", - "65": "Alakazam", "650": "Chespin", "651": "Quilladin", "652": "Chesnaught", @@ -844,7 +876,6 @@ "657": "Frogadier", "658": "Greninja", "659": "Bunnelby", - "66": "Machop", "660": "Diggersby", "661": "Fletchling", "662": "Fletchinder", @@ -855,7 +886,6 @@ "667": "Litleo", "668": "Pyroar", "669": "Flab\u00e9b\u00e9", - "67": "Machoke", "670": "Floette", "671": "Florges", "672": "Skiddo", @@ -866,7 +896,6 @@ "677": "Espurr", "678": "Meowstic", "679": "Honedge", - "68": "Machamp", "680": "Doublade", "681": "Aegislash", "682": "Spritzee", @@ -877,7 +906,6 @@ "687": "Malamar", "688": "Binacle", "689": "Barbaracle", - "69": "Bellsprout", "690": "Skrelp", "691": "Dragalge", "692": "Clauncher", @@ -888,8 +916,6 @@ "697": "Tyrantrum", "698": "Amaura", "699": "Aurorus", - "7": "Squirtle", - "70": "Weepinbell", "700": "Sylveon", "701": "Hawlucha", "702": "Dedenne", @@ -900,7 +926,6 @@ "707": "Klefki", "708": "Phantump", "709": "Trevenant", - "71": "Victreebel", "710": "Pumpkaboo", "711": "Gourgeist", "712": "Bergmite", @@ -911,56 +936,50 @@ "717": "Yveltal", "718": "Zygarde", "719": "Diancie", - "72": "Tentacool", "720": "Hoopa", - "721": "Volcanion", - "73": "Tentacruel", - "74": "Geodude", - "75": "Graveler", - "76": "Golem", - "77": "Ponyta", - "78": "Rapidash", - "79": "Slowpoke", - "8": "Wartortle", - "80": "Slowbro", - "81": "Magnemite", - "82": "Magneton", - "83": "Farfetch'd", - "84": "Doduo", - "85": "Dodrio", - "86": "Seel", - "87": "Dewgong", - "88": "Grimer", - "89": "Muk", - "9": "Blastoise", - "90": "Shellder", - "91": "Cloyster", - "92": "Gastly", - "93": "Haunter", - "94": "Gengar", - "95": "Onix", - "96": "Drowzee", - "97": "Hypno", - "98": "Krabby", - "99": "Kingler" + "721": "Volcanion" + }, + "sizes": { + "001": "minuscolo", + "002": "piccolo", + "003": "normale", + "004": "grande", + "005": "enorme" }, "teams": { - "0": "Neutrale", - "1": "Saggezza", - "2": "Coraggio", - "3": "Istinto" - }, + "000": "Neutrale", + "001": "Saggezza", + "002": "Coraggio", + "003": "Istinto" + }, + "types": { + "001": "Normale", + "002": "Combattimento", + "003": "Volare", + "004": "Veleno", + "005": "Terra", + "006": "Rock", + "007": "Roccia", + "008": "Fantasma", + "009": "Acciaio", + "010": "Fuoco", + "011": "Acqua", + "012": "Erba", + "013": "Elettrico", + "014": "Psichico", + "015": "Ghiaccio", + "016": "Drago", + "017": "Fata", + "018": "Scuro" + }, "weather": { - "0": "Nessuna", - "1": "Chiaro", - "2": "Pioggia", - "3": "Parzialmente nuvoloso", - "4": "Nuvoloso", - "5": "Ventoso", - "6": "La neve", - "7": "Nebbia" - }, - "misc": { - "boosted": "potenziato" + "000": "Nessuna", + "001": "Chiaro", + "002": "Pioggia", + "003": "Parzialmente nuvoloso", + "004": "Nuvoloso", + "005": "Ventoso", + "006": "La neve", + "007": "Nebbia" } -} +} \ No newline at end of file diff --git a/locales/ko.json b/locales/ko.json index 5008dadae..e91e75fc7 100644 --- a/locales/ko.json +++ b/locales/ko.json @@ -1,38 +1,99 @@ { + "costumes": { + "025": { + "001": "\ucd95\uc81c \ubaa8\uc790", + "002": "\ud30c\ud2f0 \ubaa8\uc790", + "003": "Ash \ubaa8\uc790", + "004": "\ub9c8\ub140 \ubaa8\uc790" + }, + "026": { + "001": "\ucd95\uc81c \ubaa8\uc790", + "002": "\ud30c\ud2f0 \ubaa8\uc790", + "003": "Ash \ubaa8\uc790", + "004": "\ub9c8\ub140 \ubaa8\uc790" + }, + "172": { + "001": "\ucd95\uc81c \ubaa8\uc790", + "002": "\ud30c\ud2f0 \ubaa8\uc790", + "003": "Ash \ubaa8\uc790", + "004": "\ub9c8\ub140 \ubaa8\uc790" + } + }, "leaders": { - "0": "\uc70c\ub85c\uc6b0\ubc15\uc0ac", - "1": "\ube14\ub791\uc26c", - "2": "\uce78\ub378\ub77c", - "3": "\uc2a4\ud30c\ud06c" - }, - "sizes": { - "1": "\uc791\uc740", - "2": "\uc791\uc740", - "3": "\ud45c\uc900", - "4": "\ud070", - "5": "\uac70\ub300\ud55c" - }, - "types": { - "1": "\ubcf4\ud1b5", - "2": "\ud30c\uc774\ud305", - "3": "\ud50c\ub77c\uc789", - "4": "\ub3c5", - "5": "\ubc14\ub2e5", - "6": "\ub85d", - "7": "\ubc84\uadf8", - "8": "\uc720\ub839", - "9": "\uc2a4\ud2f8", - "10": "\ubd88", - "11": "\ubb3c", - "12": "\uc794\ub514", - "13": "\uc804\uae30", - "14": "\uc2ec\ub839", - "15": "\uc5bc\uc74c", - "16": "\ub4dc\ub798\uace4", - "17": "\uc694\uc815", - "18": "\uc5b4\ub460" - }, + "000": "\uc70c\ub85c\uc6b0\ubc15\uc0ac", + "001": "\ube14\ub791\uc26c", + "002": "\uce78\ub378\ub77c", + "003": "\uc2a4\ud30c\ud06c" + }, + "misc": { + "boosted": "\ubd80\uc591 \ub41c" + }, "moves": { + "013": "\uae40\ubc25\ub9d0\uc774", + "014": "\ud30c\uad34\uad11\uc120", + "016": "\uc545\uc758\ud30c\ub3d9", + "018": "\uc624\ubb3c\uacf5\uaca9", + "020": "\ucc1d\uae30", + "021": "\ud654\uc5fc\uc790\ub3d9\ucc28", + "022": "\uba54\uac00\ud3f0", + "024": "\ud654\uc5fc\ubc29\uc0ac", + "026": "\uad6c\uba4d\ud30c\uae30", + "028": "\ud06c\ub85c\uc2a4\ucd19", + "030": "\ud658\uc0c1\ube54", + "031": "\uc9c0\uc9c4", + "032": "\uc2a4\ud1a4\uc5d0\uc9c0", + "033": "\ub0c9\ub3d9\ud380\uce58", + "034": "\ud558\ud2b8\uc2a4\ud0ec\ud504", + "035": "\ubc29\uc804", + "036": "\ub7ec\uc2a4\ud130\uce90\ub17c", + "038": "\ud68c\uc804\ubd80\ub9ac", + "039": "\ub0c9\ub3d9\ube54", + "040": "\ub208\ubcf4\ub77c", + "042": "\uc5f4\ud48d", + "045": "\uc81c\ube44\ubc18\ud658", + "046": "\ub4dc\ub9b4\ub77c\uc774\ub108", + "047": "\uaf43\ubcf4\ub77c", + "048": "\uba54\uac00\ub4dc\ub808\uc778", + "049": "\ubc8c\ub808\uc758\uc57c\ub2e8\ubc95\uc11d", + "050": "\ub3c5\uc5c4\ub2c8", + "051": "\uae5c\uc9dd\ubca0\uae30", + "053": "\uac70\ud488\uad11\uc120", + "054": "\uc9c0\uc625\uc758\ubc14\ud034", + "056": "\ub85c\ud0a5", + "057": "\uc544\ucfe0\uc544\uc81c\ud2b8", + "058": "\uc544\ucfe0\uc544\ud14c\uc77c", + "059": "\uc528\ud3ed\ud0c4", + "060": "\uc0ac\uc774\ucf54\uc1fc\ud06c", + "062": "\uc6d0\uc2dc\uc758\ud798", + "063": "\uc554\uc11d\ubd09\uc778", + "064": "\uc2a4\ud1a4\uc0e4\uc6cc", + "065": "\ud30c\uc6cc\uc82c", + "066": "\uc57c\uc2b5", + "067": "\uc100\ub3c4\ud380\uce58", + "069": "\uad34\uc0c1\ud55c\ubc14\ub78c", + "070": "\uc100\ub3c4\ubcfc", + "072": "\ub9c8\uadf8\ub137\ubd04", + "074": "\uc544\uc774\uc5b8\ud5e4\ub4dc", + "075": "\ud30c\ub77c\ubcfc\ub77c\ucc28\uc9c0", + "077": "\ubc88\uac1c\ud380\uce58", + "078": "\ubc88\uac1c", + "079": "10\ub9cc\ubcfc\ud2b8", + "080": "\ud68c\uc624\ub9ac", + "082": "\uc6a9\uc758\ud30c\ub3d9", + "083": "\ub4dc\ub798\uace4\ud06c\ub8e8", + "084": "\ucc28\ubc0d\ubcf4\uc774\uc2a4", + "085": "\ub4dc\ub808\uc778\ud0a4\uc2a4", + "086": "\ub9e4\uc9c0\uceec\uc0e4\uc778", + "087": "\ubb38\ud3ec\uc2a4", + "088": "\uce58\uadfc\uac70\ub9ac\uae30", + "089": "\ud06c\ub85c\uc2a4\ud3ec\uc774\uc98c", + "090": "\uc624\ubb3c\ud3ed\ud0c4", + "091": "\uc624\ubb3c\uc6e8\uc774\ube0c", + "092": "\ub354\uc2a4\ud2b8\uc288\ud2b8", + "094": "\ubf08\ub2e4\uadc0\uce58\uae30", + "095": "\ub545\uace0\ub974\uae30", + "096": "\uc9c4\ud759\ud3ed\ud0c4", + "099": "\uc2dc\uadf8\ub110\ube54", "100": "\uc2dc\uc800\ud06c\ub85c\uc2a4", "101": "\ub2c8\ud2b8\ub85c\ucc28\uc9c0", "102": "\ubd88\uaf43\ud280\uae30\uae30", @@ -56,14 +117,9 @@ "126": "\ubfd4\ucc0c\ub974\uae30", "127": "\uc9d3\ubc1f\uae30", "129": "\ud544\uc0b4\uc55e\ub2c8", - "13": "\uae40\ubc25\ub9d0\uc774", "131": "\ub204\ub974\uae30", "132": "\uc7a0\uc790\uae30", "133": "\ubc1c\ubc84\ub465", - "14": "\ud30c\uad34\uad11\uc120", - "16": "\uc545\uc758\ud30c\ub3d9", - "18": "\uc624\ubb3c\uacf5\uaca9", - "20": "\ucc1d\uae30", "200": "\uc5f0\uc18d\uc790\ub974\uae30", "201": "\ubc8c\ub808\uba39\uc74c", "202": "\ubb3c\uae30", @@ -74,7 +130,6 @@ "207": "\uc548\ub2e4\ub9ac\uac78\uae30", "208": "\ud0dc\uad8c\ub2f9\uc218", "209": "\ubd88\uaf43\uc138\ub840", - "21": "\ud654\uc5fc\uc790\ub3d9\ucc28", "210": "\ub0a0\uac1c\uce58\uae30", "211": "\ucabc\uae30", "212": "\ud565\uae30", @@ -85,7 +140,6 @@ "217": "\uc5bc\uc74c\ubb49\uce58", "218": "\uc5bc\uc74c\uc228\uacb0", "219": "\uc804\uad11\uc11d\ud654", - "22": "\uba54\uac00\ud3f0", "220": "\ud560\ud034\uae30", "221": "\ubab8\ud1b5\ubc15\uce58\uae30", "222": "\ub9c9\uce58\uae30", @@ -105,71 +159,110 @@ "237": "\uac70\ud488", "238": "\uc18d\uc5ec\ub54c\ub9ac\uae30", "239": "\uac15\ucca0\ub0a0\uac1c", - "24": "\ud654\uc5fc\ubc29\uc0ac", "240": "\ubd88\uaf43\uc5c4\ub2c8", "241": "\ubc14\uc704\uae68\uae30", - "242": "\ubcc0\uc2e0", - "26": "\uad6c\uba4d\ud30c\uae30", - "28": "\ud06c\ub85c\uc2a4\ucd19", - "30": "\ud658\uc0c1\ube54", - "31": "\uc9c0\uc9c4", - "32": "\uc2a4\ud1a4\uc5d0\uc9c0", - "33": "\ub0c9\ub3d9\ud380\uce58", - "34": "\ud558\ud2b8\uc2a4\ud0ec\ud504", - "35": "\ubc29\uc804", - "36": "\ub7ec\uc2a4\ud130\uce90\ub17c", - "38": "\ud68c\uc804\ubd80\ub9ac", - "39": "\ub0c9\ub3d9\ube54", - "40": "\ub208\ubcf4\ub77c", - "42": "\uc5f4\ud48d", - "45": "\uc81c\ube44\ubc18\ud658", - "46": "\ub4dc\ub9b4\ub77c\uc774\ub108", - "47": "\uaf43\ubcf4\ub77c", - "48": "\uba54\uac00\ub4dc\ub808\uc778", - "49": "\ubc8c\ub808\uc758\uc57c\ub2e8\ubc95\uc11d", - "50": "\ub3c5\uc5c4\ub2c8", - "51": "\uae5c\uc9dd\ubca0\uae30", - "53": "\uac70\ud488\uad11\uc120", - "54": "\uc9c0\uc625\uc758\ubc14\ud034", - "56": "\ub85c\ud0a5", - "57": "\uc544\ucfe0\uc544\uc81c\ud2b8", - "58": "\uc544\ucfe0\uc544\ud14c\uc77c", - "59": "\uc528\ud3ed\ud0c4", - "60": "\uc0ac\uc774\ucf54\uc1fc\ud06c", - "62": "\uc6d0\uc2dc\uc758\ud798", - "63": "\uc554\uc11d\ubd09\uc778", - "64": "\uc2a4\ud1a4\uc0e4\uc6cc", - "65": "\ud30c\uc6cc\uc82c", - "66": "\uc57c\uc2b5", - "67": "\uc100\ub3c4\ud380\uce58", - "69": "\uad34\uc0c1\ud55c\ubc14\ub78c", - "70": "\uc100\ub3c4\ubcfc", - "72": "\ub9c8\uadf8\ub137\ubd04", - "74": "\uc544\uc774\uc5b8\ud5e4\ub4dc", - "75": "\ud30c\ub77c\ubcfc\ub77c\ucc28\uc9c0", - "77": "\ubc88\uac1c\ud380\uce58", - "78": "\ubc88\uac1c", - "79": "10\ub9cc\ubcfc\ud2b8", - "80": "\ud68c\uc624\ub9ac", - "82": "\uc6a9\uc758\ud30c\ub3d9", - "83": "\ub4dc\ub798\uace4\ud06c\ub8e8", - "84": "\ucc28\ubc0d\ubcf4\uc774\uc2a4", - "85": "\ub4dc\ub808\uc778\ud0a4\uc2a4", - "86": "\ub9e4\uc9c0\uceec\uc0e4\uc778", - "87": "\ubb38\ud3ec\uc2a4", - "88": "\uce58\uadfc\uac70\ub9ac\uae30", - "89": "\ud06c\ub85c\uc2a4\ud3ec\uc774\uc98c", - "90": "\uc624\ubb3c\ud3ed\ud0c4", - "91": "\uc624\ubb3c\uc6e8\uc774\ube0c", - "92": "\ub354\uc2a4\ud2b8\uc288\ud2b8", - "94": "\ubf08\ub2e4\uadc0\uce58\uae30", - "95": "\ub545\uace0\ub974\uae30", - "96": "\uc9c4\ud759\ud3ed\ud0c4", - "99": "\uc2dc\uadf8\ub110\ube54" + "242": "\ubcc0\uc2e0" }, "pokemon": { - "1": "\uc774\uc0c1\ud574\uc528", - "10": "\uce90\ud130\ud53c", + "001": "\uc774\uc0c1\ud574\uc528", + "002": "\uc774\uc0c1\ud574\ud480", + "003": "\uc774\uc0c1\ud574\uaf43", + "004": "\ud30c\uc774\ub9ac", + "005": "\ub9ac\uc790\ub4dc", + "006": "\ub9ac\uc790\ubabd", + "007": "\uaf2c\ubd80\uae30", + "008": "\uc5b4\ub2c8\ubd80\uae30", + "009": "\uac70\ubd81\uc655", + "010": "\uce90\ud130\ud53c", + "011": "\ub2e8\ub370\uae30", + "012": "\ubc84\ud130\ud50c", + "013": "\ubfd4\ucda9\uc774", + "014": "\ub531\ucda9\uc774", + "015": "\ub3c5\uce68\ubd95", + "016": "\uad6c\uad6c", + "017": "\ud53c\uc8e4", + "018": "\ud53c\uc8e4\ud22c", + "019": "\uaf2c\ub81b", + "020": "\ub808\ud2b8\ub77c", + "021": "\uae68\ube44\ucc38", + "022": "\uae68\ube44\ub4dc\ub9b4\uc870", + "023": "\uc544\ubcf4", + "024": "\uc544\ubcf4\ud06c", + "025": "\ud53c\uce74\uce04", + "026": "\ub77c\uc774\uce04", + "027": "\ubaa8\ub798\ub450\uc9c0", + "028": "\uace0\uc9c0", + "029": "\ub2c8\ub4dc\ub7f0\u2640", + "030": "\ub2c8\ub4dc\ub9ac\ub098", + "031": "\ub2c8\ub4dc\ud038", + "032": "\ub2c8\ub4dc\ub7f0\u2642", + "033": "\ub2c8\ub4dc\ub9ac\ub178", + "034": "\ub2c8\ub4dc\ud0b9", + "035": "\uc090\uc090", + "036": "\ud53d\uc2dc", + "037": "\uc2dd\uc2a4\ud14c\uc77c", + "038": "\ub098\uc778\ud14c\uc77c", + "039": "\ud478\ub9b0", + "040": "\ud478\ud06c\ub9b0", + "041": "\uc8fc\ubc43", + "042": "\uace8\ubc43", + "043": "\ub69c\ubc85\ucd78", + "044": "\ub0c4\uc0c8\uaf2c", + "045": "\ub77c\ud50c\ub808\uc2dc\uc544", + "046": "\ud30c\ub77c\uc2a4", + "047": "\ud30c\ub77c\uc139\ud2b8", + "048": "\ucf58\ud321", + "049": "\ub3c4\ub098\ub9ac", + "050": "\ub514\uadf8\ub2e4", + "051": "\ub2e5\ud2b8\ub9ac\uc624", + "052": "\ub098\uc639", + "053": "\ud398\ub974\uc2dc\uc628", + "054": "\uace0\ub77c\ud30c\ub355", + "055": "\uace8\ub355", + "056": "\ub9dd\ud0a4", + "057": "\uc131\uc6d0\uc22d", + "058": "\uac00\ub514", + "059": "\uc708\ub514", + "060": "\ubc1c\ucc59\uc774", + "061": "\uc288\ub959\ucc59\uc774", + "062": "\uac15\ucc59\uc774", + "063": "\uce90\uc774\uc2dc", + "064": "\uc724\uac94\ub77c", + "065": "\ud6c4\ub518", + "066": "\uc54c\ud1b5\ubaac", + "067": "\uadfc\uc721\ubaac", + "068": "\uad34\ub825\ubaac", + "069": "\ubaa8\ub2e4\ud53c", + "070": "\uc6b0\uce20\ub3d9", + "071": "\uc6b0\uce20\ubcf4\ud2b8", + "072": "\uc655\ub208\ud574", + "073": "\ub3c5\ud30c\ub9ac", + "074": "\uaf2c\ub9c8\ub3cc", + "075": "\ub370\uad6c\ub9ac", + "076": "\ub531\uad6c\ub9ac", + "077": "\ud3ec\ub2c8\ud0c0", + "078": "\ub0a0\uc329\ub9c8", + "079": "\uc57c\ub3c8", + "080": "\uc57c\ub3c4\ub780", + "081": "\ucf54\uc77c", + "082": "\ub808\uc5b4\ucf54\uc77c", + "083": "\ud30c\uc624\ub9ac", + "084": "\ub450\ub450", + "085": "\ub450\ud2b8\ub9ac\uc624", + "086": "\uc96c\uc96c", + "087": "\uc96c\ub808\uace4", + "088": "\uc9c8\ud37d\uc774", + "089": "\uc9c8\ubed0\uae30", + "090": "\uc140\ub7ec", + "091": "\ud30c\ub974\uc140", + "092": "\uace0\uc624\uc2a4", + "093": "\uace0\uc6b0\uc2a4\ud2b8", + "094": "\ud32c\ud140", + "095": "\ub871\uc2a4\ud1a4", + "096": "\uc2ac\ub9ac\ud504", + "097": "\uc2ac\ub9ac\ud37c", + "098": "\ud06c\ub7a9", + "099": "\ud0b9\ud06c\ub7a9", "100": "\ucc0c\ub9ac\ub9ac\uacf5", "101": "\ubd90\ubcfc", "102": "\uc544\ub77c\ub9ac", @@ -180,7 +273,6 @@ "107": "\ud64d\uc218\ubaac", "108": "\ub0b4\ub8e8\ubbf8", "109": "\ub610\uac00\uc2a4", - "11": "\ub2e8\ub370\uae30", "110": "\ub610\ub3c4\uac00\uc2a4", "111": "\ubfd4\uce74\ub178", "112": "\ucf54\ubfcc\ub9ac", @@ -191,7 +283,6 @@ "117": "\uc2dc\ub4dc\ub77c", "118": "\ucf58\uce58", "119": "\uc655\ucf58\uce58", - "12": "\ubc84\ud130\ud50c", "120": "\ubcc4\uac00\uc0ac\ub9ac", "121": "\uc544\ucfe0\uc2a4\ud0c0", "122": "\ub9c8\uc784\ub9e8", @@ -202,7 +293,6 @@ "127": "\uc058\uc0ac\uc774\uc800", "128": "\ucf04\ud0c0\ub85c\uc2a4", "129": "\uc789\uc5b4\ud0b9", - "13": "\ubfd4\ucda9\uc774", "130": "\uac38\ub77c\ub3c4\uc2a4", "131": "\ub77c\ud504\ub77c\uc2a4", "132": "\uba54\ud0c0\ubabd", @@ -213,7 +303,6 @@ "137": "\ud3f4\ub9ac\uace4", "138": "\uc554\ub098\uc774\ud2b8", "139": "\uc554\uc2a4\ud0c0", - "14": "\ub531\ucda9\uc774", "140": "\ud22c\uad6c", "141": "\ud22c\uad6c\ud478\uc2a4", "142": "\ud504\ud14c\ub77c", @@ -224,7 +313,6 @@ "147": "\ubbf8\ub1fd", "148": "\uc2e0\ub1fd", "149": "\ub9dd\ub098\ub1fd", - "15": "\ub3c5\uce68\ubd95", "150": "\ubba4\uce20", "151": "\ubba4", "152": "\uce58\ucf54\ub9ac\ud0c0", @@ -235,7 +323,6 @@ "157": "\ube14\ub808\uc774\ubc94", "158": "\ub9ac\uc544\ucf54", "159": "\uc5d8\ub9ac\uac8c\uc774", - "16": "\uad6c\uad6c", "160": "\uc7a5\ud06c\ub85c\ub2e4\uc77c", "161": "\uaf2c\ub9ac\uc120", "162": "\ub2e4\uaf2c\ub9ac", @@ -246,7 +333,6 @@ "167": "\ud398\uc774\uac80", "168": "\uc544\ub9ac\uc544\ub3c4\uc2a4", "169": "\ud06c\ub85c\ubc43", - "17": "\ud53c\uc8e4", "170": "\ucd08\ub77c\uae30", "171": "\ub79c\ud134", "172": "\ud53c\uce04", @@ -257,7 +343,6 @@ "177": "\ub124\uc774\ud2f0", "178": "\ub124\uc774\ud2f0\uc624", "179": "\uba54\ub9ac\ud504", - "18": "\ud53c\uc8e4\ud22c", "180": "\ubcf4\uc1a1\uc1a1", "181": "\uc804\ub8e1", "182": "\uc544\ub974\ucf54", @@ -268,7 +353,6 @@ "187": "\ud1b5\ud1b5\ucf54", "188": "\ub450\ucf54", "189": "\uc19c\uc19c\ucf54", - "19": "\uaf2c\ub81b", "190": "\uc5d0\uc774\ud31c", "191": "\ud574\ub108\uce20", "192": "\ud574\ub8e8\ubbf8", @@ -279,8 +363,6 @@ "197": "\ube14\ub798\ud0a4", "198": "\ub2c8\ub85c\uc6b0", "199": "\uc57c\ub3c4\ud0b9", - "2": "\uc774\uc0c1\ud574\ud480", - "20": "\ub808\ud2b8\ub77c", "200": "\ubb34\uc6b0\ub9c8", "201": "\uc548\ub18d", "202": "\ub9c8\uc790\uc6a9", @@ -291,7 +373,6 @@ "207": "\uae00\ub77c\uc774\uac70", "208": "\uac15\ucca0\ud1a4", "209": "\ube14\ub8e8", - "21": "\uae68\ube44\ucc38", "210": "\uadf8\ub791\ube14\ub8e8", "211": "\uce68\ubc14\ub8e8", "212": "\ud56b\uc0bc", @@ -302,7 +383,6 @@ "217": "\ub9c1\uacf0", "218": "\ub9c8\uadf8\ub9c8\uadf8", "219": "\ub9c8\uadf8\uce74\ub974\uace0", - "22": "\uae68\ube44\ub4dc\ub9b4\uc870", "220": "\uafb8\uafb8\ub9ac", "221": "\uba54\uafb8\ub9ac", "222": "\ucf54\uc0b0\ud638", @@ -313,7 +393,6 @@ "227": "\ubb34\uc7a5\uc870", "228": "\ub378\ube4c", "229": "\ud5ec\uac00", - "23": "\uc544\ubcf4", "230": "\ud0b9\ub4dc\ub77c", "231": "\ucf54\ucf54\ub9ac", "232": "\ucf54\ub9ac\uac11", @@ -324,7 +403,6 @@ "237": "\uce74\ud3ec\uc5d0\ub77c", "238": "\ubf40\ubf40\ub77c", "239": "\uc5d0\ub808\ud0a4\ub4dc", - "24": "\uc544\ubcf4\ud06c", "240": "\ub9c8\uadf8\ube44", "241": "\ubc00\ud0f1\ud06c", "242": "\ud574\ud53c\ub108\uc2a4", @@ -335,7 +413,6 @@ "247": "\ub370\uae30\ub77c\uc2a4", "248": "\ub9c8\uae30\ub77c\uc2a4", "249": "\ub8e8\uae30\uc544", - "25": "\ud53c\uce74\uce04", "250": "\uce60\uc0c9\uc870", "251": "\uc138\ub808\ube44", "252": "\ub098\ubb34\uc9c0\uae30", @@ -346,7 +423,6 @@ "257": "\ubc88\uce58\ucf54", "258": "\ubb3c\uc9f1\uc774", "259": "\ub2aa\uc9f1\uc774", - "26": "\ub77c\uc774\uce04", "260": "\ub300\uc9f1\uc774", "261": "\ud3ec\ucc60\ub098", "262": "\uadf8\ub77c\uc5d0\ub098", @@ -357,7 +433,6 @@ "267": "\ubdf0\ud2f0\ud50c\ub77c\uc774", "268": "\uce74\uc2a4\ucfe4", "269": "\ub3c5\ucf00\uc77c", - "27": "\ubaa8\ub798\ub450\uc9c0", "270": "\uc5f0\uaf43\ubaac", "271": "\ub85c\ud1a0\uc2a4", "272": "\ub85c\ud30c\ud30c", @@ -368,7 +443,6 @@ "277": "\uc2a4\uc648\ub85c", "278": "\uac08\ubaa8\ub9e4", "279": "\ud328\ub9ac\ud37c", - "28": "\uace0\uc9c0", "280": "\ub784\ud1a0\uc2a4", "281": "\ud0ac\ub9ac\uc544", "282": "\uac00\ub514\uc548", @@ -379,7 +453,6 @@ "287": "\uac8c\uc744\ub85c", "288": "\ubc1c\ubc14\ub85c", "289": "\uac8c\uc744\ud0b9", - "29": "\ub2c8\ub4dc\ub7f0\u2640", "290": "\ud1a0\uc911\ubaac", "291": "\uc544\uc774\uc2a4\ud06c", "292": "\uaecd\uc9c8\ubaac", @@ -390,8 +463,6 @@ "297": "\ud558\ub9ac\ubb49", "298": "\ub8e8\ub9ac\ub9ac", "299": "\ucf54\ucf54\ud30c\uc2a4", - "3": "\uc774\uc0c1\ud574\uaf43", - "30": "\ub2c8\ub4dc\ub9ac\ub098", "300": "\uc5d0\ub098\ube44", "301": "\ub378\ucf00\ud2f0", "302": "\uae5c\uae4c\ubbf8", @@ -402,7 +473,6 @@ "307": "\uc694\uac00\ub791", "308": "\uc694\uac00\ub7a8", "309": "\uc36c\ub354\ub77c\uc774", - "31": "\ub2c8\ub4dc\ud038", "310": "\uc36c\ub354\ubcfc\ud2b8", "311": "\ud50c\ub7ec\uc2dc", "312": "\ub9c8\uc774\ub18d", @@ -413,7 +483,6 @@ "317": "\uafc0\uaebd\ubaac", "318": "\uc0e4\ud504\ub2c8\uc544", "319": "\uc0e4\ud06c\ub2c8\uc544", - "32": "\ub2c8\ub4dc\ub7f0\u2642", "320": "\uace0\ub798\uc655\uc790", "321": "\uace0\ub798\uc655", "322": "\ub454\ud0c0", @@ -424,7 +493,6 @@ "327": "\uc5bc\ub8e8\uae30", "328": "\ud1b1\uce58", "329": "\ube44\ube0c\ub77c\ubc14", - "33": "\ub2c8\ub4dc\ub9ac\ub178", "330": "\ud50c\ub77c\uc774\uace4", "331": "\uc120\uc778\uc655", "332": "\ubc24\uc120\uc778", @@ -435,7 +503,6 @@ "337": "\ub8e8\ub098\ud1a4", "338": "\uc194\ub85d", "339": "\ubbf8\uafb8\ub9ac", - "34": "\ub2c8\ub4dc\ud0b9", "340": "\uba54\uae45", "341": "\uac00\uc7ac\uad70", "342": "\uac00\uc7ac\uc7a5\uad70", @@ -446,7 +513,6 @@ "347": "\uc544\ub178\ub525\uc2a4", "348": "\uc544\ub9d0\ub3c4", "349": "\ube48\ud2f0\ub098", - "35": "\uc090\uc090", "350": "\ubc00\ub85c\ud2f1", "351": "\uce90\uc2a4\ud401", "352": "\ucf08\ub9ac\ubaac", @@ -457,7 +523,6 @@ "357": "\ud2b8\ub85c\ud53c\uc6b0\uc2a4", "358": "\uce58\ub801", "359": "\uc571\uc194", - "36": "\ud53d\uc2dc", "360": "\ub9c8\uc790", "361": "\ub208\uaf2c\ub9c8", "362": "\uc5bc\uc74c\uadc0\uc2e0", @@ -468,7 +533,6 @@ "367": "\ud5cc\ud14c\uc77c", "368": "\ubd84\ud64d\uc7a5\uc774", "369": "\uc2dc\ub77c\uce78", - "37": "\uc2dd\uc2a4\ud14c\uc77c", "370": "\uc0ac\ub791\ub3d9\uc774", "371": "\uc544\uacf5\uc774", "372": "\uc258\uace4", @@ -479,7 +543,6 @@ "377": "\ub808\uc9c0\ub77d", "378": "\ub808\uc9c0\uc544\uc774\uc2a4", "379": "\ub808\uc9c0\uc2a4\ud2f8", - "38": "\ub098\uc778\ud14c\uc77c", "380": "\ub77c\ud2f0\uc544\uc2a4", "381": "\ub77c\ud2f0\uc624\uc2a4", "382": "\uac00\uc774\uc624\uac00", @@ -490,7 +553,6 @@ "387": "\ubaa8\ubd80\uae30", "388": "\uc218\ud480\ubd80\uae30", "389": "\ud1a0\ub300\ubd80\uae30", - "39": "\ud478\ub9b0", "390": "\ubd88\uaf43\uc22d\uc774", "391": "\ud30c\uc774\uc22d\uc774", "392": "\ucd08\uc5fc\ubabd", @@ -501,8 +563,6 @@ "397": "\ucc0c\ub974\ubc84\ub4dc", "398": "\ucc0c\ub974\ud638\ud06c", "399": "\ube44\ubc84\ub2c8", - "4": "\ud30c\uc774\ub9ac", - "40": "\ud478\ud06c\ub9b0", "400": "\ube44\ubc84\ud1b5", "401": "\uadc0\ub6a4\ub69c\uae30", "402": "\uadc0\ub6a4\ud1a1\ud06c", @@ -513,7 +573,6 @@ "407": "\ub85c\uc988\ub808\uc774\ub4dc", "408": "\ub450\uac1c\ub3c4\uc2a4", "409": "\ub7a8\ud384\ub4dc", - "41": "\uc8fc\ubc43", "410": "\ubc29\ud328\ud1b1\uc2a4", "411": "\ubc14\ub9ac\ud1b1\uc2a4", "412": "\ub3c4\ub871\ucda9\uc774", @@ -524,7 +583,6 @@ "417": "\ud30c\uce58\ub9ac\uc2a4", "418": "\ube0c\uc774\uc824", "419": "\ud50c\ub85c\uc824", - "42": "\uace8\ubc43", "420": "\uccb4\ub9ac\ubc84", "421": "\uccb4\ub9ac\uaf2c", "422": "\uae5d\uc9c8\ubb34", @@ -535,7 +593,6 @@ "427": "\uc774\uc5b4\ub864", "428": "\uc774\uc5b4\ub86d", "429": "\ubb34\uc6b0\ub9c8\uc9c1", - "43": "\ub69c\ubc85\ucd78", "430": "\ub3c8\ud06c\ub85c\uc6b0", "431": "\ub098\uc639\ub9c8", "432": "\ubaac\ub0e5\uc774", @@ -546,7 +603,6 @@ "437": "\ub3d9\ud0c1\uad70", "438": "\uaf2c\uc9c0\uc9c0", "439": "\ud749\ub0b4\ub0b4", - "44": "\ub0c4\uc0c8\uaf2c", "440": "\ud551\ubcf5", "441": "\ud398\ub77c\ud398", "442": "\ud654\uac15\ub3cc", @@ -557,7 +613,6 @@ "447": "\ub9ac\uc624\ub974", "448": "\ub8e8\uce74\ub9ac\uc624", "449": "\ud788\ud3ec\ud3ec\ud0c0\uc2a4", - "45": "\ub77c\ud50c\ub808\uc2dc\uc544", "450": "\ud558\ub9c8\ub3c8", "451": "\uc2a4\ucf5c\ud53c", "452": "\ub4dc\ub798\ud53c\uc628", @@ -568,7 +623,6 @@ "457": "\ub124\uc624\ub77c\uc774\ud2b8", "458": "\ud0c0\ub9cc\ud0c0", "459": "\ub208\uc4f0\uac1c", - "46": "\ud30c\ub77c\uc2a4", "460": "\ub208\uc124\uc655", "461": "\ud3ec\ud478\ub2c8\ub77c", "462": "\uc790\ud3ec\ucf54\uc77c", @@ -579,7 +633,6 @@ "467": "\ub9c8\uadf8\ub9c8\ubc88", "468": "\ud1a0\uac8c\ud0a4\uc2a4", "469": "\uba54\uac00\uc790\ub9ac", - "47": "\ud30c\ub77c\uc139\ud2b8", "470": "\ub9ac\ud53c\uc544", "471": "\uae00\ub808\uc774\uc2dc\uc544", "472": "\uae00\ub77c\uc774\uc628", @@ -590,7 +643,6 @@ "477": "\uc57c\ub290\uc640\ub974\ubabd", "478": "\ub208\uc5ec\uc544", "479": "\ub85c\ud1a0\ubb34", - "48": "\ucf58\ud321", "480": "\uc720\ud06c\uc2dc", "481": "\uc5e0\ub77c\uc774\ud2b8", "482": "\uc544\uadf8\ub188", @@ -601,7 +653,6 @@ "487": "\uae30\ub77c\ud2f0\ub098", "488": "\ud06c\ub808\uc138\ub9ac\uc544", "489": "\ud53c\uc624\ub124", - "49": "\ub3c4\ub098\ub9ac", "490": "\ub9c8\ub098\ud53c", "491": "\ub2e4\ud06c\ub77c\uc774", "492": "\uc250\uc774\ubbf8", @@ -612,8 +663,6 @@ "497": "\uc0e4\ub85c\ub2e4", "498": "\ub69c\uafb8\ub9ac", "499": "\ucc28\uc624\uafc0", - "5": "\ub9ac\uc790\ub4dc", - "50": "\ub514\uadf8\ub2e4", "500": "\uc5fc\ubb34\uc655", "501": "\uc218\ub315\uc774", "502": "\uc30d\uac80\uc790\ube44", @@ -624,7 +673,6 @@ "507": "\ud558\ub370\ub9ac\uc5b4", "508": "\ubc14\ub79c\ub4dc", "509": "\uc314\ube44\ub0e5", - "51": "\ub2e5\ud2b8\ub9ac\uc624", "510": "\ub808\ud30c\ub974\ub2e4\uc2a4", "511": "\uc57c\ub098\ud504", "512": "\uc57c\ub098\ud0a4", @@ -635,7 +683,6 @@ "517": "\ubabd\ub098", "518": "\ubabd\uc58c\ub098", "519": "\ucf69\ub458\uae30", - "52": "\ub098\uc639", "520": "\uc720\ud1a0\ube0c", "521": "\ucf04\ud638\ub85c\uc6b0", "522": "\uc904\ubba4\ub9c8", @@ -646,7 +693,6 @@ "527": "\ub610\ub974\ubc15\uc950", "528": "\ub9d8\ubc15\uc950", "529": "\ub450\ub354\ub958", - "53": "\ud398\ub974\uc2dc\uc628", "530": "\ubab0\ub4dc\ub958", "531": "\ub2e4\ubd80\ub2c8", "532": "\uc73c\ub78f\ucc28", @@ -657,7 +703,6 @@ "537": "\ub450\ube45\uad74", "538": "\ub358\uc9c0\ubbf8", "539": "\ud0c0\uaca9\uadc0", - "54": "\uace0\ub77c\ud30c\ub355", "540": "\ub450\ub974\ubcf4", "541": "\ub450\ub974\ucfe4", "542": "\ubaa8\uc544\uba38", @@ -668,7 +713,6 @@ "547": "\uc5d8\ud48d", "548": "\uce58\ub9b4\ub9ac", "549": "\ub4dc\ub808\ub514\uc5b4", - "55": "\uace8\ub355", "550": "\ubc30\uc4f0\ub098\uc774", "551": "\uae5c\ub208\ud06c", "552": "\uc545\ube44\ub974", @@ -679,7 +723,6 @@ "557": "\ub3cc\uc0b4\uc774", "558": "\uc554\ud330\ub9ac\uc2a4", "559": "\uace4\uc728\ub7ad", - "56": "\ub9dd\ud0a4", "560": "\uace4\uc728\uac70\ub2c8", "561": "\uc2ec\ubcf4\ub7ec", "562": "\ub370\uc2a4\ub9c8\uc2a4", @@ -690,7 +733,6 @@ "567": "\uc544\ucf00\uc624\uc2a4", "568": "\uae68\ubd09\uc774", "569": "\ub354\uc2a4\ud2b8\ub098", - "57": "\uc131\uc6d0\uc22d", "570": "\uc870\ub85c\uc544", "571": "\uc870\ub85c\uc544\ud06c", "572": "\uce58\ub77c\ubbf8", @@ -701,7 +743,6 @@ "577": "\uc720\ub2c8\ub780", "578": "\ub4c0\ub780", "579": "\ub780\ucfe8\ub8e8\uc2a4", - "58": "\uac00\ub514", "580": "\uaf2c\uc9c0\ubcf4\ub9ac", "581": "\uc2a4\uc644\ub098", "582": "\ubc14\ub2d0\ud504\ud2f0", @@ -712,7 +753,6 @@ "587": "\uc5d0\ubabd\uac00", "588": "\ub531\uc815\uace4", "589": "\uc288\ubc14\ub974\uace0", - "59": "\uc708\ub514", "590": "\uae5c\ub180\ubc84\uc2ac", "591": "\ubf40\ub85d\ub098", "592": "\ud0f1\uadf8\ub9b4", @@ -723,8 +763,6 @@ "597": "\ucca0\uc2dc\ub4dc", "598": "\ub108\ud2b8\ub839", "599": "\uae30\uc5b4\ub974", - "6": "\ub9ac\uc790\ubabd", - "60": "\ubc1c\ucc59\uc774", "600": "\uae30\uae30\uc5b4\ub974", "601": "\uae30\uae30\uae30\uc5b4\ub974", "602": "\uc800\ub9ac\uc5b4", @@ -735,7 +773,6 @@ "607": "\ubd88\ucf1c\ubbf8", "608": "\ub7a8\ud504\ub77c", "609": "\uc0f9\ub378\ub77c", - "61": "\uc288\ub959\ucc59\uc774", "610": "\ud130\uac80\ub2c8", "611": "\uc561\uc2a8\ub3c4", "612": "\uc561\uc2a4\ub77c\uc774\uc988", @@ -746,7 +783,6 @@ "617": "\uc5b4\uc9c0\ub9ac\ub354", "618": "\uba54\ub354", "619": "\ube44\uc870\ud478", - "62": "\uac15\ucc59\uc774", "620": "\ube44\uc870\ub3c4", "621": "\ud06c\ub9ac\ub9cc", "622": "\uace8\ube44\ub78c", @@ -757,7 +793,6 @@ "627": "\uc218\ub9ac\ub465\ubcf4", "628": "\uc6cc\uae00", "629": "\ubc8c\ucc28\uc774", - "63": "\uce90\uc774\uc2dc", "630": "\ubc84\ub79c\uc9c0\ub098", "631": "\uc564\ud2f0\uace8", "632": "\uc544\uc774\uc564\ud2b8", @@ -768,7 +803,6 @@ "637": "\ubd88\uce74\ubaa8\uc2a4", "638": "\ucf54\ubc14\ub974\uc628", "639": "\ud14c\ub77c\ud0a4\uc628", - "64": "\uc724\uac94\ub77c", "640": "\ube44\ub9ac\ub514\uc628", "641": "\ud1a0\ub124\ub85c\uc2a4", "642": "\ubcfc\ud2b8\ub85c\uc2a4", @@ -779,7 +813,6 @@ "647": "\ucf00\ub974\ub514\uc624", "648": "\uba54\ub85c\uc5e3\ud0c0", "649": "\uac8c\ub178\uc138\ud06c\ud2b8", - "65": "\ud6c4\ub518", "650": "\ub3c4\uce58\ub9c8\ub860", "651": "\ub3c4\uce58\ubcf4\uad6c", "652": "\ube0c\ub9ac\uac00\ub860", @@ -790,7 +823,6 @@ "657": "\uac1c\uad74\ubc18\uc7a5", "658": "\uac1c\uad74\ub2cc\uc790", "659": "\ud30c\ub974\ube57", - "66": "\uc54c\ud1b5\ubaac", "660": "\ud30c\ub974\ud1a0", "661": "\ud654\uc0b4\uaf2c\ube48", "662": "\ubd88\ud654\uc0b4\ube48", @@ -801,7 +833,6 @@ "667": "\ub808\uc624\uaf2c", "668": "\ud654\uc5fc\ub808\uc624", "669": "\ud50c\ub77c\ubca0\ubca0", - "67": "\uadfc\uc721\ubaac", "670": "\ud50c\ub77c\uc5e3\ud14c", "671": "\ud50c\ub77c\uc81c\uc2a4", "672": "\uba54\uc774\ud074", @@ -812,7 +843,6 @@ "677": "\ub0d0\uc2a4\ud37c", "678": "\ub0d0\uc624\ub2c9\uc2a4", "679": "\ub2e8\uce7c\ube59", - "68": "\uad34\ub825\ubaac", "680": "\uc30d\uac80\ud0ac", "681": "\ud0ac\uac00\ub974\ub3c4", "682": "\uc288\uc058", @@ -823,7 +853,6 @@ "687": "\uce7c\ub77c\ub9c8\ub124\ub85c", "688": "\uac70\ubd81\uc190\uc190", "689": "\uac70\ubd81\uc190\ub370\uc2a4", - "69": "\ubaa8\ub2e4\ud53c", "690": "\uc218\ub808\uae30", "691": "\ub4dc\ub798\uce84", "692": "\uc644\ucca0\ud3ec", @@ -834,8 +863,6 @@ "697": "\uacac\uace0\ub77c\uc2a4", "698": "\uc544\ub9c8\ub8e8\uc2a4", "699": "\uc544\ub9c8\ub8e8\ub974\uac00", - "7": "\uaf2c\ubd80\uae30", - "70": "\uc6b0\uce20\ub3d9", "700": "\ub2d8\ud53c\uc544", "701": "\ub8e8\ucc28\ubd88", "702": "\ub370\ub374\ub124", @@ -846,7 +873,6 @@ "707": "\ud074\ub808\ud53c", "708": "\ub098\ubaa9\ub839", "709": "\ub300\ub85c\ud2b8", - "71": "\uc6b0\uce20\ubcf4\ud2b8", "710": "\ud638\ubc14\uadc0", "711": "\ud38c\ud0a8\uc778", "712": "\uaf41\uc5b4\ub984", @@ -857,56 +883,50 @@ "717": "\uc774\ubca8\ud0c0\ub974", "718": "\uc9c0\uac00\ub974\ub370", "719": "\ub514\uc548\uc2dc", - "72": "\uc655\ub208\ud574", "720": "\ud6c4\ud30c", - "721": "\ubcfc\ucf00\ub2c8\uc628", - "73": "\ub3c5\ud30c\ub9ac", - "74": "\uaf2c\ub9c8\ub3cc", - "75": "\ub370\uad6c\ub9ac", - "76": "\ub531\uad6c\ub9ac", - "77": "\ud3ec\ub2c8\ud0c0", - "78": "\ub0a0\uc329\ub9c8", - "79": "\uc57c\ub3c8", - "8": "\uc5b4\ub2c8\ubd80\uae30", - "80": "\uc57c\ub3c4\ub780", - "81": "\ucf54\uc77c", - "82": "\ub808\uc5b4\ucf54\uc77c", - "83": "\ud30c\uc624\ub9ac", - "84": "\ub450\ub450", - "85": "\ub450\ud2b8\ub9ac\uc624", - "86": "\uc96c\uc96c", - "87": "\uc96c\ub808\uace4", - "88": "\uc9c8\ud37d\uc774", - "89": "\uc9c8\ubed0\uae30", - "9": "\uac70\ubd81\uc655", - "90": "\uc140\ub7ec", - "91": "\ud30c\ub974\uc140", - "92": "\uace0\uc624\uc2a4", - "93": "\uace0\uc6b0\uc2a4\ud2b8", - "94": "\ud32c\ud140", - "95": "\ub871\uc2a4\ud1a4", - "96": "\uc2ac\ub9ac\ud504", - "97": "\uc2ac\ub9ac\ud37c", - "98": "\ud06c\ub7a9", - "99": "\ud0b9\ud06c\ub7a9" + "721": "\ubcfc\ucf00\ub2c8\uc628" + }, + "sizes": { + "001": "\uc791\uc740", + "002": "\uc791\uc740", + "003": "\ud45c\uc900", + "004": "\ud070", + "005": "\uac70\ub300\ud55c" }, "teams": { - "0": "\uc911\ub9bd(\uc18c\uc18d\uc5c6\uc74c)", - "1": "\ubbf8\uc2a4\ud2f1(\ube14\ub8e8)", - "2": "\ubc1c\ub85c(\ub808\ub4dc)", - "3": "\uc778\uc2a4\ud305\ud2b8(\uc610\ub85c\uc6b0)" - }, + "000": "\uc911\ub9bd(\uc18c\uc18d\uc5c6\uc74c)", + "001": "\ubbf8\uc2a4\ud2f1(\ube14\ub8e8)", + "002": "\ubc1c\ub85c(\ub808\ub4dc)", + "003": "\uc778\uc2a4\ud305\ud2b8(\uc610\ub85c\uc6b0)" + }, + "types": { + "001": "\ubcf4\ud1b5", + "002": "\ud30c\uc774\ud305", + "003": "\ud50c\ub77c\uc789", + "004": "\ub3c5", + "005": "\ubc14\ub2e5", + "006": "\ub85d", + "007": "\ubc84\uadf8", + "008": "\uc720\ub839", + "009": "\uc2a4\ud2f8", + "010": "\ubd88", + "011": "\ubb3c", + "012": "\uc794\ub514", + "013": "\uc804\uae30", + "014": "\uc2ec\ub839", + "015": "\uc5bc\uc74c", + "016": "\ub4dc\ub798\uace4", + "017": "\uc694\uc815", + "018": "\uc5b4\ub460" + }, "weather": { - "0": "\uc5c6\uc74c", - "1": "\uba85\ud655\ud55c", - "2": "\ube44", - "3": "\uc57d\uac04 \ud750\ub9bc", - "4": "\ud750\ub9b0", - "5": "\uae5c\uc9dd \ub180\ub780", - "6": "\ub208", - "7": "\uc548\uac1c" - }, - "misc": { - "boosted": "\uBD80\uC591 \uB41C" + "000": "\uc5c6\uc74c", + "001": "\uba85\ud655\ud55c", + "002": "\ube44", + "003": "\uc57d\uac04 \ud750\ub9bc", + "004": "\ud750\ub9b0", + "005": "\uae5c\uc9dd \ub180\ub780", + "006": "\ub208", + "007": "\uc548\uac1c" } -} +} \ No newline at end of file diff --git a/locales/pt.json b/locales/pt.json index 40956e754..77530dfa7 100644 --- a/locales/pt.json +++ b/locales/pt.json @@ -1,998 +1,1018 @@ { + "costumes": { + "025": { + "001": "Chap\u00e9u Festiva", + "002": "Chap\u00e9u de Festa", + "003": "Chap\u00e9u de Ash", + "004": "Chap\u00e9u da Bruxa" + }, + "026": { + "001": "Chap\u00e9u Festiva", + "002": "Chap\u00e9u de Festa", + "003": "Chap\u00e9u de Ash", + "004": "Chap\u00e9u da Bruxa" + }, + "172": { + "001": "Chap\u00e9u Festiva", + "002": "Chap\u00e9u de Festa", + "003": "Chap\u00e9u de Ash", + "004": "Chap\u00e9u da Bruxa" + } + }, "leaders": { - "0": "Professor Willow", - "1": "Blanche", - "2": "Candela", - "3": "Spark" - }, - "sizes": { - "1": "min\u00FAsculo", - "2": "pequeno", - "3": "normal", - "4": "grande", - "5": "enorme" - }, - "types": { - "1": "Normal", - "2": "Lutar", - "3": "Voando", - "4": "Veneno", - "5": "Terra", - "6": "Rocha", - "7": "Bicho", - "8": "Fantasma", - "9": "A\u00E7o", - "10": "Fogo", - "11": "\u00C1gua", - "12": "Grama", - "13": "El\u00E9trico", - "14": "Ps\u00EDquico", - "15": "Gelo", - "16": "Drag\u00E3o", - "17": "Fada", - "18": "Escuro" - }, + "000": "Professor Willow", + "001": "Blanche", + "002": "Candela", + "003": "Spark" + }, + "misc": { + "boosted": "impulsionado" + }, "moves": { - "1": "Trovoada de Choques", - "2": "Ataque R\u00e1pido", - "3": "Arranh\u00e3o", - "4": "Brasa", - "5": "Chicote de Vinha", - "6": "Investida", - "7": "Folha Navalha", - "8": "Desmantelar", - "9": "Rev\u00f3lver d'\u00c1gua", - "10": "Mordida", - "11": "Pancada", - "12": "Tapa Duplo", - "13": "Embrulho", - "14": "Hiper-raio", - "15": "Lambida", - "16": "Pulso Sombrio", - "17": "Nevoeiro de Fuma\u00e7a", - "18": "Lodo", - "19": "Garra de Metal", - "20": "Agarramento Viciado", - "21": "Roda de Fogo", - "22": "Megachifre", - "23": "Ataque de Asa", - "24": "Lan\u00e7a-chamas", - "25": "Soco Enganador", - "26": "Cavar", - "27": "Rasteira", - "28": "Golpe Cruzado", - "29": "Corte Ps\u00edquico", - "30": "Feixe Ps\u00edquico", - "31": "Terremoto", - "32": "Gume de Pedra", - "33": "Soco de Gelo", - "34": "Estampa de Cora\u00e7\u00e3o", - "35": "Descarga", - "36": "Canh\u00e3o de Flash", - "37": "Bicada", - "38": "Bico Broca", - "39": "Raio Congelante", - "40": "Nevasca", - "41": "Golpe de Ar", - "42": "Onda de Calor", - "43": "Agulha Dupla", - "44": "Golpe Envenenado", - "45": "\u00c1s dos Ares", - "46": "Fura\u00e7\u00e3o", - "47": "Nevasca de P\u00e9talas", - "48": "Megadreno", - "49": "Zumbido de Inseto", - "50": "Presa Venenosa", - "51": "Talho Noturno", - "52": "Talho", - "53": "Jato de Bolhas", - "54": "Submiss\u00e3o", - "55": "Golpe de Carat\u00ea", - "56": "Movimento Baixo", - "57": "Aqua Jato", - "58": "Aqua Cauda", - "59": "Bomba de Sementes", - "60": "Choque Ps\u00edquico", - "61": "Lan\u00e7amento de Rocha", - "62": "Poder Ancestral", - "63": "Tumba de Rochas", - "64": "Deslize de Pedras", - "65": "Gema Poderosa", - "66": "Furtividade nas Sombras", - "67": "Soco Sombrio", - "68": "Garra Sombria", - "69": "Vento Ominoso", - "70": "Bola Sombria", - "71": "Soco Proj\u00e9til", - "72": "Bomba \u00edm\u00e3", - "73": "Asa de A\u00e7o", - "74": "Cabe\u00e7a de Ferro", - "75": "Ataque Parab\u00f3lico", - "76": "Fa\u00edsca", - "77": "Soco Trovoada", - "78": "Trov\u00e3o", - "79": "Rel\u00e2mpago", - "80": "Twister", - "81": "Sopro do Drag\u00e3o", - "82": "Pulso do Drag\u00e3o", - "83": "Garra de Drag\u00e3o", - "84": "Voz Desarmante", - "85": "Beijo Drenante", - "86": "Clar\u00e3o Deslumbrante", - "87": "Explos\u00e3o Lunar", - "88": "Jogo Duro", - "89": "Corte-veneno", - "90": "Bomba de Lodo", - "91": "Onda de Lama", - "92": "Tiro de Sujeira", - "93": "Tiro de Lama", - "94": "Bast\u00e3o de Osso", - "95": "Tremor", - "96": "Bomba de Lama", - "97": "Cortador de Fúria", - "98": "Picada", - "99": "Feixe Sinalizador", - "100": "Tesoura X", - "101": "Ataque de Chamas", - "102": "Rajada de Chamas", - "103": "Rajada de Fogo", - "104": "Salmoura", - "105": "Pulso d'\u00c1gua", - "106": "Escaldada", - "107": "Jato d'\u00c1gua", - "108": "Ps\u00edquico", - "109": "Ataque Ps\u00edquico", - "110": "Caco de Gelo", - "111": "Vento Congelante", - "112": "Respira\u00e7\u00e3o de Gelo", - "113": "Absor\u00e7\u00e3o", - "114": "Gigadreno", - "115": "Soco de Fogo", - "116": "Raio Solar", - "117": "L\u00e2mina de Folha", - "118": "Chicote Poderoso", - "119": "Borrifada", - "120": "\u00c1cido", - "121": "Cortador de Ar", - "122": "Furac\u00e3o", - "123": "Quebra-telha", - "124": "Cortar", - "125": "Ataque Veloz", - "126": "Ataque de Chifre", - "127": "Pisotear", - "128": "Cabe\u00e7ada", - "129": "Hiperpresa", - "130": "Pancada Brusca", - "131": "Pancada Corporal", - "132": "Descansar", - "133": "Insist\u00eancia", - "134": "Escaldada", - "135": "Jato d'\u00c1gua", - "136": "Embrulho", - "137": "Embrulho", - "200": "Cortador de Fúria", - "201": "Picada", - "202": "Mordida", - "203": "Soco Enganador", - "204": "Sopro do Drag\u00e3o", - "205": "Trovoada de Choques", - "206": "Fa\u00edsca", - "207": "Rasteira", - "208": "Golpe de Carat\u00ea", - "209": "Brasa", - "210": "Ataque de Asa", - "211": "Bicada", - "212": "Lambida", - "213": "Garra Sombria", - "214": "Chicote de Vinha", - "215": "Folha Navalha", - "216": "Tiro de Lama", - "217": "Caco de Gelo", - "218": "Respira\u00e7\u00e3o de Gelo", - "219": "Ataque R\u00e1pido", - "220": "Arranh\u00e3o", - "221": "Investida", - "222": "Pancada", - "223": "Cortar", - "224": "Golpe Envenenado", - "225": "\u00c1cido", - "226": "Corte Ps\u00edquico", - "227": "Lan\u00e7amento de Rocha", - "228": "Garra de Metal", - "229": "Soco Proj\u00e9til", - "230": "Rev\u00f3lver d'\u00c1gua", - "231": "Borrifada", - "232": "Rev\u00f3lver d'\u00c1gua", - "233": "Tapa de Lama", - "234": "Cabe\u00e7ada Zen", - "235": "Confus\u00e3o", - "236": "Ferr\u00e3o Venenoso", - "237": "Bolha", - "238": "Ataque Dissimulado", - "239": "Asa de A\u00e7o", - "240": "Presas de Fogo", - "241": "Esmagamento de Pedras", - "242": "Transforma\u00e7\u00e3o", - "243": "Contra-atacar", - "244": "Neve em P\u00f3", - "245": "Corpo-a-corpo", - "246": "Soco Din\u00e2mico", - "247": "Explos\u00e3o Focalizada", - "248": "Raio Aurora", - "249": "Carga de Raio", - "250": "Troca El\u00e9trica", - "251": "Ataque Selvagem", - "252": "Canh\u00e3o Zap", - "253": "Cauda do Drag\u00e3o", - "254": "Avalanche", - "255": "Golpe de Ar", - "256": "P\u00e1ssaro Bravo", - "257": "Ataque do C\u00e9u", - "258": "Fosso de Areia", - "259": "Explos\u00e3o de Rocha", - "260": "Infesta\u00e7\u00e3o", - "261": "Ira de Inseto", - "262": "Vento Prateado", - "263": "Abismar", - "264": "Feiti\u00e7o", - "265": "Sombra Noturna", - "266": "Cauda de Ferro", - "267": "Girobola", - "268": "Golpe Pesado", - "269": "Chama Furac\u00e3o", - "270": "Superaquecimento", - "271": "Proj\u00e9til de Semente", - "272": "N\u00f3 de Grama", - "273": "Bola de Energia", - "274": "Extrassensorial", - "275": "Vis\u00e3o do Futuro", - "276": "Casaco Espelhado", - "277": "Ultraje", - "278": "Rosnado", - "279": "Mastigada", - "280": "Jogo Sujo", + "001": "Trovoada de Choques", + "002": "Ataque R\u00e1pido", + "003": "Arranh\u00e3o", + "004": "Brasa", + "005": "Chicote de Vinha", + "006": "Investida", + "007": "Folha Navalha", + "008": "Desmantelar", + "009": "Rev\u00f3lver d'\u00c1gua", + "010": "Mordida", + "011": "Pancada", + "012": "Tapa Duplo", + "013": "Embrulho", + "014": "Hiper-raio", + "015": "Lambida", + "016": "Pulso Sombrio", + "017": "Nevoeiro de Fuma\u00e7a", + "018": "Lodo", + "019": "Garra de Metal", + "020": "Agarramento Viciado", + "021": "Roda de Fogo", + "022": "Megachifre", + "023": "Ataque de Asa", + "024": "Lan\u00e7a-chamas", + "025": "Soco Enganador", + "026": "Cavar", + "027": "Rasteira", + "028": "Golpe Cruzado", + "029": "Corte Ps\u00edquico", + "030": "Feixe Ps\u00edquico", + "031": "Terremoto", + "032": "Gume de Pedra", + "033": "Soco de Gelo", + "034": "Estampa de Cora\u00e7\u00e3o", + "035": "Descarga", + "036": "Canh\u00e3o de Flash", + "037": "Bicada", + "038": "Bico Broca", + "039": "Raio Congelante", + "040": "Nevasca", + "041": "Golpe de Ar", + "042": "Onda de Calor", + "043": "Agulha Dupla", + "044": "Golpe Envenenado", + "045": "\u00c1s dos Ares", + "046": "Fura\u00e7\u00e3o", + "047": "Nevasca de P\u00e9talas", + "048": "Megadreno", + "049": "Zumbido de Inseto", + "050": "Presa Venenosa", + "051": "Talho Noturno", + "052": "Talho", + "053": "Jato de Bolhas", + "054": "Submiss\u00e3o", + "055": "Golpe de Carat\u00ea", + "056": "Movimento Baixo", + "057": "Aqua Jato", + "058": "Aqua Cauda", + "059": "Bomba de Sementes", + "060": "Choque Ps\u00edquico", + "061": "Lan\u00e7amento de Rocha", + "062": "Poder Ancestral", + "063": "Tumba de Rochas", + "064": "Deslize de Pedras", + "065": "Gema Poderosa", + "066": "Furtividade nas Sombras", + "067": "Soco Sombrio", + "068": "Garra Sombria", + "069": "Vento Ominoso", + "070": "Bola Sombria", + "071": "Soco Proj\u00e9til", + "072": "Bomba \u00edm\u00e3", + "073": "Asa de A\u00e7o", + "074": "Cabe\u00e7a de Ferro", + "075": "Ataque Parab\u00f3lico", + "076": "Fa\u00edsca", + "077": "Soco Trovoada", + "078": "Trov\u00e3o", + "079": "Rel\u00e2mpago", + "080": "Twister", + "081": "Sopro do Drag\u00e3o", + "082": "Pulso do Drag\u00e3o", + "083": "Garra de Drag\u00e3o", + "084": "Voz Desarmante", + "085": "Beijo Drenante", + "086": "Clar\u00e3o Deslumbrante", + "087": "Explos\u00e3o Lunar", + "088": "Jogo Duro", + "089": "Corte-veneno", + "090": "Bomba de Lodo", + "091": "Onda de Lama", + "092": "Tiro de Sujeira", + "093": "Tiro de Lama", + "094": "Bast\u00e3o de Osso", + "095": "Tremor", + "096": "Bomba de Lama", + "097": "Cortador de F\u00faria", + "098": "Picada", + "099": "Feixe Sinalizador", + "100": "Tesoura X", + "101": "Ataque de Chamas", + "102": "Rajada de Chamas", + "103": "Rajada de Fogo", + "104": "Salmoura", + "105": "Pulso d'\u00c1gua", + "106": "Escaldada", + "107": "Jato d'\u00c1gua", + "108": "Ps\u00edquico", + "109": "Ataque Ps\u00edquico", + "110": "Caco de Gelo", + "111": "Vento Congelante", + "112": "Respira\u00e7\u00e3o de Gelo", + "113": "Absor\u00e7\u00e3o", + "114": "Gigadreno", + "115": "Soco de Fogo", + "116": "Raio Solar", + "117": "L\u00e2mina de Folha", + "118": "Chicote Poderoso", + "119": "Borrifada", + "120": "\u00c1cido", + "121": "Cortador de Ar", + "122": "Furac\u00e3o", + "123": "Quebra-telha", + "124": "Cortar", + "125": "Ataque Veloz", + "126": "Ataque de Chifre", + "127": "Pisotear", + "128": "Cabe\u00e7ada", + "129": "Hiperpresa", + "130": "Pancada Brusca", + "131": "Pancada Corporal", + "132": "Descansar", + "133": "Insist\u00eancia", + "134": "Escaldada", + "135": "Jato d'\u00c1gua", + "136": "Embrulho", + "137": "Embrulho", + "200": "Cortador de F\u00faria", + "201": "Picada", + "202": "Mordida", + "203": "Soco Enganador", + "204": "Sopro do Drag\u00e3o", + "205": "Trovoada de Choques", + "206": "Fa\u00edsca", + "207": "Rasteira", + "208": "Golpe de Carat\u00ea", + "209": "Brasa", + "210": "Ataque de Asa", + "211": "Bicada", + "212": "Lambida", + "213": "Garra Sombria", + "214": "Chicote de Vinha", + "215": "Folha Navalha", + "216": "Tiro de Lama", + "217": "Caco de Gelo", + "218": "Respira\u00e7\u00e3o de Gelo", + "219": "Ataque R\u00e1pido", + "220": "Arranh\u00e3o", + "221": "Investida", + "222": "Pancada", + "223": "Cortar", + "224": "Golpe Envenenado", + "225": "\u00c1cido", + "226": "Corte Ps\u00edquico", + "227": "Lan\u00e7amento de Rocha", + "228": "Garra de Metal", + "229": "Soco Proj\u00e9til", + "230": "Rev\u00f3lver d'\u00c1gua", + "231": "Borrifada", + "232": "Rev\u00f3lver d'\u00c1gua", + "233": "Tapa de Lama", + "234": "Cabe\u00e7ada Zen", + "235": "Confus\u00e3o", + "236": "Ferr\u00e3o Venenoso", + "237": "Bolha", + "238": "Ataque Dissimulado", + "239": "Asa de A\u00e7o", + "240": "Presas de Fogo", + "241": "Esmagamento de Pedras", + "242": "Transforma\u00e7\u00e3o", + "243": "Contra-atacar", + "244": "Neve em P\u00f3", + "245": "Corpo-a-corpo", + "246": "Soco Din\u00e2mico", + "247": "Explos\u00e3o Focalizada", + "248": "Raio Aurora", + "249": "Carga de Raio", + "250": "Troca El\u00e9trica", + "251": "Ataque Selvagem", + "252": "Canh\u00e3o Zap", + "253": "Cauda do Drag\u00e3o", + "254": "Avalanche", + "255": "Golpe de Ar", + "256": "P\u00e1ssaro Bravo", + "257": "Ataque do C\u00e9u", + "258": "Fosso de Areia", + "259": "Explos\u00e3o de Rocha", + "260": "Infesta\u00e7\u00e3o", + "261": "Ira de Inseto", + "262": "Vento Prateado", + "263": "Abismar", + "264": "Feiti\u00e7o", + "265": "Sombra Noturna", + "266": "Cauda de Ferro", + "267": "Girobola", + "268": "Golpe Pesado", + "269": "Chama Furac\u00e3o", + "270": "Superaquecimento", + "271": "Proj\u00e9til de Semente", + "272": "N\u00f3 de Grama", + "273": "Bola de Energia", + "274": "Extrassensorial", + "275": "Vis\u00e3o do Futuro", + "276": "Casaco Espelhado", + "277": "Ultraje", + "278": "Rosnado", + "279": "Mastigada", + "280": "Jogo Sujo", "281": "Poder Oculto" }, "pokemon": { - "1": "Bulbasaur", - "2": "Ivysaur", - "3": "Venusaur", - "4": "Charmander", - "5": "Charmeleon", - "6": "Charizard", - "7": "Squirtle", - "8": "Wartortle", - "9": "Blastoise", - "10": "Caterpie", - "11": "Metapod", - "12": "Butterfree", - "13": "Weedle", - "14": "Kakuna", - "15": "Beedrill", - "16": "Pidgey", - "17": "Pidgeotto", - "18": "Pidgeot", - "19": "Rattata", - "20": "Raticate", - "21": "Spearow", - "22": "Fearow", - "23": "Ekans", - "24": "Arbok", - "25": "Pikachu", - "26": "Raichu", - "27": "Sandshrew", - "28": "Sandslash", - "29": "Nidoran♀", - "30": "Nidorina", - "31": "Nidoqueen", - "32": "Nidoran♂", - "33": "Nidorino", - "34": "Nidoking", - "35": "Clefairy", - "36": "Clefable", - "37": "Vulpix", - "38": "Ninetales", - "39": "Jigglypuff", - "40": "Wigglytuff", - "41": "Zubat", - "42": "Golbat", - "43": "Oddish", - "44": "Gloom", - "45": "Vileplume", - "46": "Paras", - "47": "Parasect", - "48": "Venonat", - "49": "Venomoth", - "50": "Diglett", - "51": "Dugtrio", - "52": "Meowth", - "53": "Persian", - "54": "Psyduck", - "55": "Golduck", - "56": "Mankey", - "57": "Primeape", - "58": "Growlithe", - "59": "Arcanine", - "60": "Poliwag", - "61": "Poliwhirl", - "62": "Poliwrath", - "63": "Abra", - "64": "Kadabra", - "65": "Alakazam", - "66": "Machop", - "67": "Machoke", - "68": "Machamp", - "69": "Bellsprout", - "70": "Weepinbell", - "71": "Victreebel", - "72": "Tentacool", - "73": "Tentacruel", - "74": "Geodude", - "75": "Graveler", - "76": "Golem", - "77": "Ponyta", - "78": "Rapidash", - "79": "Slowpoke", - "80": "Slowbro", - "81": "Magnemite", - "82": "Magneton", - "83": "Farfetch'd", - "84": "Doduo", - "85": "Dodrio", - "86": "Seel", - "87": "Dewgong", - "88": "Grimer", - "89": "Muk", - "90": "Shellder", - "91": "Cloyster", - "92": "Gastly", - "93": "Haunter", - "94": "Gengar", - "95": "Onix", - "96": "Drowzee", - "97": "Hypno", - "98": "Krabby", - "99": "Kingler", - "100": "Voltorb", - "101": "Electrode", - "102": "Exeggcute", - "103": "Exeggutor", - "104": "Cubone", - "105": "Marowak", - "106": "Hitmonlee", - "107": "Hitmonchan", - "108": "Lickitung", - "109": "Koffing", - "110": "Weezing", - "111": "Rhyhorn", - "112": "Rhydon", - "113": "Chansey", - "114": "Tangela", - "115": "Kangaskhan", - "116": "Horsea", - "117": "Seadra", - "118": "Goldeen", - "119": "Seaking", - "120": "Staryu", - "121": "Starmie", - "122": "Mr. Mime", - "123": "Scyther", - "124": "Jynx", - "125": "Electabuzz", - "126": "Magmar", - "127": "Pinsir", - "128": "Tauros", - "129": "Magikarp", - "130": "Gyarados", - "131": "Lapras", - "132": "Ditto", - "133": "Eevee", - "134": "Vaporeon", - "135": "Jolteon", - "136": "Flareon", - "137": "Porygon", - "138": "Omanyte", - "139": "Omastar", - "140": "Kabuto", - "141": "Kabutops", - "142": "Aerodactyl", - "143": "Snorlax", - "144": "Articuno", - "145": "Zapdos", - "146": "Moltres", - "147": "Dratini", - "148": "Dragonair", - "149": "Dragonite", - "150": "Mewtwo", - "151": "Mew", - "152": "Chikorita", - "153": "Bayleef", - "154": "Meganium", - "155": "Cyndaquil", - "156": "Quilava", - "157": "Typhlosion", - "158": "Totodile", - "159": "Croconaw", - "160": "Feraligatr", - "161": "Sentret", - "162": "Furret", - "163": "Hoothoot", - "164": "Noctowl", - "165": "Ledyba", - "166": "Ledian", - "167": "Spinarak", - "168": "Ariados", - "169": "Crobat", - "170": "Chinchou", - "171": "Lanturn", - "172": "Pichu", - "173": "Cleffa", - "174": "Igglybuff", - "175": "Togepi", - "176": "Togetic", - "177": "Natu", - "178": "Xatu", - "179": "Mareep", - "180": "Flaaffy", - "181": "Ampharos", - "182": "Bellossom", - "183": "Marill", - "184": "Azumarill", - "185": "Sudowoodo", - "186": "Politoed", - "187": "Hoppip", - "188": "Skiploom", - "189": "Jumpluff", - "190": "Aipom", - "191": "Sunkern", - "192": "Sunflora", - "193": "Yanma", - "194": "Wooper", - "195": "Quagsire", - "196": "Espeon", - "197": "Umbreon", - "198": "Murkrow", - "199": "Slowking", - "200": "Misdreavus", - "201": "Unown", - "202": "Wobbuffet", - "203": "Girafarig", - "204": "Pineco", - "205": "Forretress", - "206": "Dunsparce", - "207": "Gligar", - "208": "Steelix", - "209": "Snubbull", - "210": "Granbull", - "211": "Qwilfish", - "212": "Scizor", - "213": "Shuckle", - "214": "Heracross", - "215": "Sneasel", - "216": "Teddiursa", - "217": "Ursaring", - "218": "Slugma", - "219": "Magcargo", - "220": "Swinub", - "221": "Piloswine", - "222": "Corsola", - "223": "Remoraid", - "224": "Octillery", - "225": "Delibird", - "226": "Mantine", - "227": "Skarmory", - "228": "Houndour", - "229": "Houndoom", - "230": "Kingdra", - "231": "Phanpy", - "232": "Donphan", - "233": "Porygon2", - "234": "Stantler", - "235": "Smeargle", - "236": "Tyrogue", - "237": "Hitmontop", - "238": "Smoochum", - "239": "Elekid", - "240": "Magby", - "241": "Miltank", - "242": "Blissey", - "243": "Raikou", - "244": "Entei", - "245": "Suicune", - "246": "Larvitar", - "247": "Pupitar", - "248": "Tyranitar", - "249": "Lugia", - "250": "Ho-Oh", - "251": "Celebi", - "252": "Treecko", - "253": "Grovyle", - "254": "Sceptile", - "255": "Torchic", - "256": "Combusken", - "257": "Blaziken", - "258": "Mudkip", - "259": "Marshtomp", - "260": "Swampert", - "261": "Poochyena", - "262": "Mightyena", - "263": "Zigzagoon", - "264": "Linoone", - "265": "Wurmple", - "266": "Silcoon", - "267": "Beautifly", - "268": "Cascoon", - "269": "Dustox", - "270": "Lotad", - "271": "Lombre", - "272": "Ludicolo", - "273": "Seedot", - "274": "Nuzleaf", - "275": "Shiftry", - "276": "Taillow", - "277": "Swellow", - "278": "Wingull", - "279": "Pelipper", - "280": "Ralts", - "281": "Kirlia", - "282": "Gardevoir", - "283": "Surskit", - "284": "Masquerain", - "285": "Shroomish", - "286": "Breloom", - "287": "Slakoth", - "288": "Vigoroth", - "289": "Slaking", - "290": "Nincada", - "291": "Ninjask", - "292": "Shedinja", - "293": "Whismur", - "294": "Loudred", - "295": "Exploud", - "296": "Makuhita", - "297": "Hariyama", - "298": "Azurill", - "299": "Nosepass", - "300": "Skitty", - "301": "Delcatty", - "302": "Sableye", - "303": "Mawile", - "304": "Aron", - "305": "Lairon", - "306": "Aggron", - "307": "Meditite", - "308": "Medicham", - "309": "Electrike", - "310": "Manectric", - "311": "Plusle", - "312": "Minun", - "313": "Volbeat", - "314": "Illumise", - "315": "Roselia", - "316": "Gulpin", - "317": "Swalot", - "318": "Carvanha", - "319": "Sharpedo", - "320": "Wailmer", - "321": "Wailord", - "322": "Numel", - "323": "Camerupt", - "324": "Torkoal", - "325": "Spoink", - "326": "Grumpig", - "327": "Spinda", - "328": "Trapinch", - "329": "Vibrava", - "330": "Flygon", - "331": "Cacnea", - "332": "Cacturne", - "333": "Swablu", - "334": "Altaria", - "335": "Zangoose", - "336": "Seviper", - "337": "Lunatone", - "338": "Solrock", - "339": "Barboach", - "340": "Whiscash", - "341": "Corphish", - "342": "Crawdaunt", - "343": "Baltoy", - "344": "Claydol", - "345": "Lileep", - "346": "Cradily", - "347": "Anorith", - "348": "Armaldo", - "349": "Feebas", - "350": "Milotic", - "351": "Castform", - "352": "Kecleon", - "353": "Shuppet", - "354": "Banette", - "355": "Duskull", - "356": "Dusclops", - "357": "Tropius", - "358": "Chimecho", - "359": "Absol", - "360": "Wynaut", - "361": "Snorunt", - "362": "Glalie", - "363": "Spheal", - "364": "Sealeo", - "365": "Walrein", - "366": "Clamperl", - "367": "Huntail", - "368": "Gorebyss", - "369": "Relicanth", - "370": "Luvdisc", - "371": "Bagon", - "372": "Shelgon", - "373": "Salamence", - "374": "Beldum", - "375": "Metang", - "376": "Metagross", - "377": "Regirock", - "378": "Regice", - "379": "Registeel", - "380": "Latias", - "381": "Latios", - "382": "Kyogre", - "383": "Groudon", - "384": "Rayquaza", - "385": "Jirachi", - "386": "Deoxys", - "387": "Turtwig", - "388": "Grotle", - "389": "Torterra", - "390": "Chimchar", - "391": "Monferno", - "392": "Infernape", - "393": "Piplup", - "394": "Prinplup", - "395": "Empoleon", - "396": "Starly", - "397": "Staravia", - "398": "Staraptor", - "399": "Bidoof", - "400": "Bibarel", - "401": "Kricketot", - "402": "Kricketune", - "403": "Shinx", - "404": "Luxio", - "405": "Luxray", - "406": "Budew", - "407": "Roserade", - "408": "Cranidos", - "409": "Rampardos", - "410": "Shieldon", - "411": "Bastiodon", - "412": "Burmy", - "413": "Wormadam", - "414": "Mothim", - "415": "Combee", - "416": "Vespiquen", - "417": "Pachirisu", - "418": "Buizel", - "419": "Floatzel", - "420": "Cherubi", - "421": "Cherrim", - "422": "Shellos", - "423": "Gastrodon", - "424": "Ambipom", - "425": "Drifloon", - "426": "Drifblim", - "427": "Buneary", - "428": "Lopunny", - "429": "Mismagius", - "430": "Honchkrow", - "431": "Glameow", - "432": "Purugly", - "433": "Chingling", - "434": "Stunky", - "435": "Skuntank", - "436": "Bronzor", - "437": "Bronzong", - "438": "Bonsly", - "439": "Mime Jr.", - "440": "Happiny", - "441": "Chatot", - "442": "Spiritomb", - "443": "Gible", - "444": "Gabite", - "445": "Garchomp", - "446": "Munchlax", - "447": "Riolu", - "448": "Lucario", - "449": "Hippopotas", - "450": "Hippowdon", - "451": "Skorupi", - "452": "Drapion", - "453": "Croagunk", - "454": "Toxicroak", - "455": "Carnivine", - "456": "Finneon", - "457": "Lumineon", - "458": "Mantyke", - "459": "Snover", - "460": "Abomasnow", - "461": "Weavile", - "462": "Magnezone", - "463": "Lickilicky", - "464": "Rhyperior", - "465": "Tangrowth", - "466": "Electivire", - "467": "Magmortar", - "468": "Togekiss", - "469": "Yanmega", - "470": "Leafeon", - "471": "Glaceon", - "472": "Gliscor", - "473": "Mamoswine", - "474": "Porygon-Z", - "475": "Gallade", - "476": "Probopass", - "477": "Dusknoir", - "478": "Froslass", - "479": "Rotom", - "480": "Uxie", - "481": "Mesprit", - "482": "Azelf", - "483": "Dialga", - "484": "Palkia", - "485": "Heatran", - "486": "Regigigas", - "487": "Giratina", - "488": "Cresselia", - "489": "Phione", - "490": "Manaphy", - "491": "Darkrai", - "492": "Shaymin", - "493": "Arceus", - "494": "Victini", - "495": "Snivy", - "496": "Servine", - "497": "Serperior", - "498": "Tepig", - "499": "Pignite", - "500": "Emboar", - "501": "Oshawott", - "502": "Dewott", - "503": "Samurott", - "504": "Patrat", - "505": "Watchog", - "506": "Lillipup", - "507": "Herdier", - "508": "Stoutland", - "509": "Purrloin", - "510": "Liepard", - "511": "Pansage", - "512": "Simisage", - "513": "Pansear", - "514": "Simisear", - "515": "Panpour", - "516": "Simipour", - "517": "Munna", - "518": "Musharna", - "519": "Pidove", - "520": "Tranquill", - "521": "Unfezant", - "522": "Blitzle", - "523": "Zebstrika", - "524": "Roggenrola", - "525": "Boldore", - "526": "Gigalith", - "527": "Woobat", - "528": "Swoobat", - "529": "Drilbur", - "530": "Excadrill", - "531": "Audino", - "532": "Timburr", - "533": "Gurdurr", - "534": "Conkeldurr", - "535": "Tympole", - "536": "Palpitoad", - "537": "Seismitoad", - "538": "Throh", - "539": "Sawk", - "540": "Sewaddle", - "541": "Swadloon", - "542": "Leavanny", - "543": "Venipede", - "544": "Whirlipede", - "545": "Scolipede", - "546": "Cottonee", - "547": "Whimsicott", - "548": "Petilil", - "549": "Lilligant", - "550": "Basculin", - "551": "Sandile", - "552": "Krokorok", - "553": "Krookodile", - "554": "Darumaka", - "555": "Darmanitan", - "556": "Maractus", - "557": "Dwebble", - "558": "Crustle", - "559": "Scraggy", - "560": "Scrafty", - "561": "Sigilyph", - "562": "Yamask", - "563": "Cofagrigus", - "564": "Tirtouga", - "565": "Carracosta", - "566": "Archen", - "567": "Archeops", - "568": "Trubbish", - "569": "Garbodor", - "570": "Zorua", - "571": "Zoroark", - "572": "Minccino", - "573": "Cinccino", - "574": "Gothita", - "575": "Gothorita", - "576": "Gothitelle", - "577": "Solosis", - "578": "Duosion", - "579": "Reuniclus", - "580": "Ducklett", - "581": "Swanna", - "582": "Vanillite", - "583": "Vanillish", - "584": "Vanilluxe", - "585": "Deerling", - "586": "Sawsbuck", - "587": "Emolga", - "588": "Karrablast", - "589": "Escavalier", - "590": "Foongus", - "591": "Amoonguss", - "592": "Frillish", - "593": "Jellicent", - "594": "Alomomola", - "595": "Joltik", - "596": "Galvantula", - "597": "Ferroseed", - "598": "Ferrothorn", - "599": "Klink", - "600": "Klang", - "601": "Klinklang", - "602": "Tynamo", - "603": "Eelektrik", - "604": "Eelektross", - "605": "Elgyem", - "606": "Beheeyem", - "607": "Litwick", - "608": "Lampent", - "609": "Chandelure", - "610": "Axew", - "611": "Fraxure", - "612": "Haxorus", - "613": "Cubchoo", - "614": "Beartic", - "615": "Cryogonal", - "616": "Shelmet", - "617": "Accelgor", - "618": "Stunfisk", - "619": "Mienfoo", - "620": "Mienshao", - "621": "Druddigon", - "622": "Golett", - "623": "Golurk", - "624": "Pawniard", - "625": "Bisharp", - "626": "Bouffalant", - "627": "Rufflet", - "628": "Braviary", - "629": "Vullaby", - "630": "Mandibuzz", - "631": "Heatmor", - "632": "Durant", - "633": "Deino", - "634": "Zweilous", - "635": "Hydreigon", - "636": "Larvesta", - "637": "Volcarona", - "638": "Cobalion", - "639": "Terrakion", - "640": "Virizion", - "641": "Tornadus", - "642": "Thundurus", - "643": "Reshiram", - "644": "Zekrom", - "645": "Landorus", - "646": "Kyurem", - "647": "Keldeo", - "648": "Meloetta", - "649": "Genesect", - "650": "Chespin", - "651": "Quilladin", - "652": "Chesnaught", - "653": "Fennekin", - "654": "Braixen", - "655": "Delphox", - "656": "Froakie", - "657": "Frogadier", - "658": "Greninja", - "659": "Bunnelby", - "660": "Diggersby", - "661": "Fletchling", - "662": "Fletchinder", - "663": "Talonflame", - "664": "Scatterbug", - "665": "Spewpa", - "666": "Vivillon", - "667": "Litleo", - "668": "Pyroar", - "669": "Flab\u00E9b\u00E9", - "670": "Floette", - "671": "Florges", - "672": "Skiddo", - "673": "Gogoat", - "674": "Pancham", - "675": "Pangoro", - "676": "Furfrou", - "677": "Espurr", - "678": "Meowstic", - "679": "Honedge", - "680": "Doublade", - "681": "Aegislash", - "682": "Spritzee", - "683": "Aromatisse", - "684": "Swirlix", - "685": "Slurpuff", - "686": "Inkay", - "687": "Malamar", - "688": "Binacle", - "689": "Barbaracle", - "690": "Skrelp", - "691": "Dragalge", - "692": "Clauncher", - "693": "Clawitzer", - "694": "Helioptile", - "695": "Heliolisk", - "696": "Tyrunt", - "697": "Tyrantrum", - "698": "Amaura", - "699": "Aurorus", - "700": "Sylveon", - "701": "Hawlucha", - "702": "Dedenne", - "703": "Carbink", - "704": "Goomy", - "705": "Sliggoo", - "706": "Goodra", - "707": "Klefki", - "708": "Phantump", - "709": "Trevenant", - "710": "Pumpkaboo", - "711": "Gourgeist", - "712": "Bergmite", - "713": "Avalugg", - "714": "Noibat", - "715": "Noivern", - "716": "Xerneas", - "717": "Yveltal", - "718": "Zygarde", - "719": "Diancie", - "720": "Hoopa", + "001": "Bulbasaur", + "002": "Ivysaur", + "003": "Venusaur", + "004": "Charmander", + "005": "Charmeleon", + "006": "Charizard", + "007": "Squirtle", + "008": "Wartortle", + "009": "Blastoise", + "010": "Caterpie", + "011": "Metapod", + "012": "Butterfree", + "013": "Weedle", + "014": "Kakuna", + "015": "Beedrill", + "016": "Pidgey", + "017": "Pidgeotto", + "018": "Pidgeot", + "019": "Rattata", + "020": "Raticate", + "021": "Spearow", + "022": "Fearow", + "023": "Ekans", + "024": "Arbok", + "025": "Pikachu", + "026": "Raichu", + "027": "Sandshrew", + "028": "Sandslash", + "029": "Nidoran\u2640", + "030": "Nidorina", + "031": "Nidoqueen", + "032": "Nidoran\u2642", + "033": "Nidorino", + "034": "Nidoking", + "035": "Clefairy", + "036": "Clefable", + "037": "Vulpix", + "038": "Ninetales", + "039": "Jigglypuff", + "040": "Wigglytuff", + "041": "Zubat", + "042": "Golbat", + "043": "Oddish", + "044": "Gloom", + "045": "Vileplume", + "046": "Paras", + "047": "Parasect", + "048": "Venonat", + "049": "Venomoth", + "050": "Diglett", + "051": "Dugtrio", + "052": "Meowth", + "053": "Persian", + "054": "Psyduck", + "055": "Golduck", + "056": "Mankey", + "057": "Primeape", + "058": "Growlithe", + "059": "Arcanine", + "060": "Poliwag", + "061": "Poliwhirl", + "062": "Poliwrath", + "063": "Abra", + "064": "Kadabra", + "065": "Alakazam", + "066": "Machop", + "067": "Machoke", + "068": "Machamp", + "069": "Bellsprout", + "070": "Weepinbell", + "071": "Victreebel", + "072": "Tentacool", + "073": "Tentacruel", + "074": "Geodude", + "075": "Graveler", + "076": "Golem", + "077": "Ponyta", + "078": "Rapidash", + "079": "Slowpoke", + "080": "Slowbro", + "081": "Magnemite", + "082": "Magneton", + "083": "Farfetch'd", + "084": "Doduo", + "085": "Dodrio", + "086": "Seel", + "087": "Dewgong", + "088": "Grimer", + "089": "Muk", + "090": "Shellder", + "091": "Cloyster", + "092": "Gastly", + "093": "Haunter", + "094": "Gengar", + "095": "Onix", + "096": "Drowzee", + "097": "Hypno", + "098": "Krabby", + "099": "Kingler", + "100": "Voltorb", + "101": "Electrode", + "102": "Exeggcute", + "103": "Exeggutor", + "104": "Cubone", + "105": "Marowak", + "106": "Hitmonlee", + "107": "Hitmonchan", + "108": "Lickitung", + "109": "Koffing", + "110": "Weezing", + "111": "Rhyhorn", + "112": "Rhydon", + "113": "Chansey", + "114": "Tangela", + "115": "Kangaskhan", + "116": "Horsea", + "117": "Seadra", + "118": "Goldeen", + "119": "Seaking", + "120": "Staryu", + "121": "Starmie", + "122": "Mr. Mime", + "123": "Scyther", + "124": "Jynx", + "125": "Electabuzz", + "126": "Magmar", + "127": "Pinsir", + "128": "Tauros", + "129": "Magikarp", + "130": "Gyarados", + "131": "Lapras", + "132": "Ditto", + "133": "Eevee", + "134": "Vaporeon", + "135": "Jolteon", + "136": "Flareon", + "137": "Porygon", + "138": "Omanyte", + "139": "Omastar", + "140": "Kabuto", + "141": "Kabutops", + "142": "Aerodactyl", + "143": "Snorlax", + "144": "Articuno", + "145": "Zapdos", + "146": "Moltres", + "147": "Dratini", + "148": "Dragonair", + "149": "Dragonite", + "150": "Mewtwo", + "151": "Mew", + "152": "Chikorita", + "153": "Bayleef", + "154": "Meganium", + "155": "Cyndaquil", + "156": "Quilava", + "157": "Typhlosion", + "158": "Totodile", + "159": "Croconaw", + "160": "Feraligatr", + "161": "Sentret", + "162": "Furret", + "163": "Hoothoot", + "164": "Noctowl", + "165": "Ledyba", + "166": "Ledian", + "167": "Spinarak", + "168": "Ariados", + "169": "Crobat", + "170": "Chinchou", + "171": "Lanturn", + "172": "Pichu", + "173": "Cleffa", + "174": "Igglybuff", + "175": "Togepi", + "176": "Togetic", + "177": "Natu", + "178": "Xatu", + "179": "Mareep", + "180": "Flaaffy", + "181": "Ampharos", + "182": "Bellossom", + "183": "Marill", + "184": "Azumarill", + "185": "Sudowoodo", + "186": "Politoed", + "187": "Hoppip", + "188": "Skiploom", + "189": "Jumpluff", + "190": "Aipom", + "191": "Sunkern", + "192": "Sunflora", + "193": "Yanma", + "194": "Wooper", + "195": "Quagsire", + "196": "Espeon", + "197": "Umbreon", + "198": "Murkrow", + "199": "Slowking", + "200": "Misdreavus", + "201": "Unown", + "202": "Wobbuffet", + "203": "Girafarig", + "204": "Pineco", + "205": "Forretress", + "206": "Dunsparce", + "207": "Gligar", + "208": "Steelix", + "209": "Snubbull", + "210": "Granbull", + "211": "Qwilfish", + "212": "Scizor", + "213": "Shuckle", + "214": "Heracross", + "215": "Sneasel", + "216": "Teddiursa", + "217": "Ursaring", + "218": "Slugma", + "219": "Magcargo", + "220": "Swinub", + "221": "Piloswine", + "222": "Corsola", + "223": "Remoraid", + "224": "Octillery", + "225": "Delibird", + "226": "Mantine", + "227": "Skarmory", + "228": "Houndour", + "229": "Houndoom", + "230": "Kingdra", + "231": "Phanpy", + "232": "Donphan", + "233": "Porygon2", + "234": "Stantler", + "235": "Smeargle", + "236": "Tyrogue", + "237": "Hitmontop", + "238": "Smoochum", + "239": "Elekid", + "240": "Magby", + "241": "Miltank", + "242": "Blissey", + "243": "Raikou", + "244": "Entei", + "245": "Suicune", + "246": "Larvitar", + "247": "Pupitar", + "248": "Tyranitar", + "249": "Lugia", + "250": "Ho-Oh", + "251": "Celebi", + "252": "Treecko", + "253": "Grovyle", + "254": "Sceptile", + "255": "Torchic", + "256": "Combusken", + "257": "Blaziken", + "258": "Mudkip", + "259": "Marshtomp", + "260": "Swampert", + "261": "Poochyena", + "262": "Mightyena", + "263": "Zigzagoon", + "264": "Linoone", + "265": "Wurmple", + "266": "Silcoon", + "267": "Beautifly", + "268": "Cascoon", + "269": "Dustox", + "270": "Lotad", + "271": "Lombre", + "272": "Ludicolo", + "273": "Seedot", + "274": "Nuzleaf", + "275": "Shiftry", + "276": "Taillow", + "277": "Swellow", + "278": "Wingull", + "279": "Pelipper", + "280": "Ralts", + "281": "Kirlia", + "282": "Gardevoir", + "283": "Surskit", + "284": "Masquerain", + "285": "Shroomish", + "286": "Breloom", + "287": "Slakoth", + "288": "Vigoroth", + "289": "Slaking", + "290": "Nincada", + "291": "Ninjask", + "292": "Shedinja", + "293": "Whismur", + "294": "Loudred", + "295": "Exploud", + "296": "Makuhita", + "297": "Hariyama", + "298": "Azurill", + "299": "Nosepass", + "300": "Skitty", + "301": "Delcatty", + "302": "Sableye", + "303": "Mawile", + "304": "Aron", + "305": "Lairon", + "306": "Aggron", + "307": "Meditite", + "308": "Medicham", + "309": "Electrike", + "310": "Manectric", + "311": "Plusle", + "312": "Minun", + "313": "Volbeat", + "314": "Illumise", + "315": "Roselia", + "316": "Gulpin", + "317": "Swalot", + "318": "Carvanha", + "319": "Sharpedo", + "320": "Wailmer", + "321": "Wailord", + "322": "Numel", + "323": "Camerupt", + "324": "Torkoal", + "325": "Spoink", + "326": "Grumpig", + "327": "Spinda", + "328": "Trapinch", + "329": "Vibrava", + "330": "Flygon", + "331": "Cacnea", + "332": "Cacturne", + "333": "Swablu", + "334": "Altaria", + "335": "Zangoose", + "336": "Seviper", + "337": "Lunatone", + "338": "Solrock", + "339": "Barboach", + "340": "Whiscash", + "341": "Corphish", + "342": "Crawdaunt", + "343": "Baltoy", + "344": "Claydol", + "345": "Lileep", + "346": "Cradily", + "347": "Anorith", + "348": "Armaldo", + "349": "Feebas", + "350": "Milotic", + "351": "Castform", + "352": "Kecleon", + "353": "Shuppet", + "354": "Banette", + "355": "Duskull", + "356": "Dusclops", + "357": "Tropius", + "358": "Chimecho", + "359": "Absol", + "360": "Wynaut", + "361": "Snorunt", + "362": "Glalie", + "363": "Spheal", + "364": "Sealeo", + "365": "Walrein", + "366": "Clamperl", + "367": "Huntail", + "368": "Gorebyss", + "369": "Relicanth", + "370": "Luvdisc", + "371": "Bagon", + "372": "Shelgon", + "373": "Salamence", + "374": "Beldum", + "375": "Metang", + "376": "Metagross", + "377": "Regirock", + "378": "Regice", + "379": "Registeel", + "380": "Latias", + "381": "Latios", + "382": "Kyogre", + "383": "Groudon", + "384": "Rayquaza", + "385": "Jirachi", + "386": "Deoxys", + "387": "Turtwig", + "388": "Grotle", + "389": "Torterra", + "390": "Chimchar", + "391": "Monferno", + "392": "Infernape", + "393": "Piplup", + "394": "Prinplup", + "395": "Empoleon", + "396": "Starly", + "397": "Staravia", + "398": "Staraptor", + "399": "Bidoof", + "400": "Bibarel", + "401": "Kricketot", + "402": "Kricketune", + "403": "Shinx", + "404": "Luxio", + "405": "Luxray", + "406": "Budew", + "407": "Roserade", + "408": "Cranidos", + "409": "Rampardos", + "410": "Shieldon", + "411": "Bastiodon", + "412": "Burmy", + "413": "Wormadam", + "414": "Mothim", + "415": "Combee", + "416": "Vespiquen", + "417": "Pachirisu", + "418": "Buizel", + "419": "Floatzel", + "420": "Cherubi", + "421": "Cherrim", + "422": "Shellos", + "423": "Gastrodon", + "424": "Ambipom", + "425": "Drifloon", + "426": "Drifblim", + "427": "Buneary", + "428": "Lopunny", + "429": "Mismagius", + "430": "Honchkrow", + "431": "Glameow", + "432": "Purugly", + "433": "Chingling", + "434": "Stunky", + "435": "Skuntank", + "436": "Bronzor", + "437": "Bronzong", + "438": "Bonsly", + "439": "Mime Jr.", + "440": "Happiny", + "441": "Chatot", + "442": "Spiritomb", + "443": "Gible", + "444": "Gabite", + "445": "Garchomp", + "446": "Munchlax", + "447": "Riolu", + "448": "Lucario", + "449": "Hippopotas", + "450": "Hippowdon", + "451": "Skorupi", + "452": "Drapion", + "453": "Croagunk", + "454": "Toxicroak", + "455": "Carnivine", + "456": "Finneon", + "457": "Lumineon", + "458": "Mantyke", + "459": "Snover", + "460": "Abomasnow", + "461": "Weavile", + "462": "Magnezone", + "463": "Lickilicky", + "464": "Rhyperior", + "465": "Tangrowth", + "466": "Electivire", + "467": "Magmortar", + "468": "Togekiss", + "469": "Yanmega", + "470": "Leafeon", + "471": "Glaceon", + "472": "Gliscor", + "473": "Mamoswine", + "474": "Porygon-Z", + "475": "Gallade", + "476": "Probopass", + "477": "Dusknoir", + "478": "Froslass", + "479": "Rotom", + "480": "Uxie", + "481": "Mesprit", + "482": "Azelf", + "483": "Dialga", + "484": "Palkia", + "485": "Heatran", + "486": "Regigigas", + "487": "Giratina", + "488": "Cresselia", + "489": "Phione", + "490": "Manaphy", + "491": "Darkrai", + "492": "Shaymin", + "493": "Arceus", + "494": "Victini", + "495": "Snivy", + "496": "Servine", + "497": "Serperior", + "498": "Tepig", + "499": "Pignite", + "500": "Emboar", + "501": "Oshawott", + "502": "Dewott", + "503": "Samurott", + "504": "Patrat", + "505": "Watchog", + "506": "Lillipup", + "507": "Herdier", + "508": "Stoutland", + "509": "Purrloin", + "510": "Liepard", + "511": "Pansage", + "512": "Simisage", + "513": "Pansear", + "514": "Simisear", + "515": "Panpour", + "516": "Simipour", + "517": "Munna", + "518": "Musharna", + "519": "Pidove", + "520": "Tranquill", + "521": "Unfezant", + "522": "Blitzle", + "523": "Zebstrika", + "524": "Roggenrola", + "525": "Boldore", + "526": "Gigalith", + "527": "Woobat", + "528": "Swoobat", + "529": "Drilbur", + "530": "Excadrill", + "531": "Audino", + "532": "Timburr", + "533": "Gurdurr", + "534": "Conkeldurr", + "535": "Tympole", + "536": "Palpitoad", + "537": "Seismitoad", + "538": "Throh", + "539": "Sawk", + "540": "Sewaddle", + "541": "Swadloon", + "542": "Leavanny", + "543": "Venipede", + "544": "Whirlipede", + "545": "Scolipede", + "546": "Cottonee", + "547": "Whimsicott", + "548": "Petilil", + "549": "Lilligant", + "550": "Basculin", + "551": "Sandile", + "552": "Krokorok", + "553": "Krookodile", + "554": "Darumaka", + "555": "Darmanitan", + "556": "Maractus", + "557": "Dwebble", + "558": "Crustle", + "559": "Scraggy", + "560": "Scrafty", + "561": "Sigilyph", + "562": "Yamask", + "563": "Cofagrigus", + "564": "Tirtouga", + "565": "Carracosta", + "566": "Archen", + "567": "Archeops", + "568": "Trubbish", + "569": "Garbodor", + "570": "Zorua", + "571": "Zoroark", + "572": "Minccino", + "573": "Cinccino", + "574": "Gothita", + "575": "Gothorita", + "576": "Gothitelle", + "577": "Solosis", + "578": "Duosion", + "579": "Reuniclus", + "580": "Ducklett", + "581": "Swanna", + "582": "Vanillite", + "583": "Vanillish", + "584": "Vanilluxe", + "585": "Deerling", + "586": "Sawsbuck", + "587": "Emolga", + "588": "Karrablast", + "589": "Escavalier", + "590": "Foongus", + "591": "Amoonguss", + "592": "Frillish", + "593": "Jellicent", + "594": "Alomomola", + "595": "Joltik", + "596": "Galvantula", + "597": "Ferroseed", + "598": "Ferrothorn", + "599": "Klink", + "600": "Klang", + "601": "Klinklang", + "602": "Tynamo", + "603": "Eelektrik", + "604": "Eelektross", + "605": "Elgyem", + "606": "Beheeyem", + "607": "Litwick", + "608": "Lampent", + "609": "Chandelure", + "610": "Axew", + "611": "Fraxure", + "612": "Haxorus", + "613": "Cubchoo", + "614": "Beartic", + "615": "Cryogonal", + "616": "Shelmet", + "617": "Accelgor", + "618": "Stunfisk", + "619": "Mienfoo", + "620": "Mienshao", + "621": "Druddigon", + "622": "Golett", + "623": "Golurk", + "624": "Pawniard", + "625": "Bisharp", + "626": "Bouffalant", + "627": "Rufflet", + "628": "Braviary", + "629": "Vullaby", + "630": "Mandibuzz", + "631": "Heatmor", + "632": "Durant", + "633": "Deino", + "634": "Zweilous", + "635": "Hydreigon", + "636": "Larvesta", + "637": "Volcarona", + "638": "Cobalion", + "639": "Terrakion", + "640": "Virizion", + "641": "Tornadus", + "642": "Thundurus", + "643": "Reshiram", + "644": "Zekrom", + "645": "Landorus", + "646": "Kyurem", + "647": "Keldeo", + "648": "Meloetta", + "649": "Genesect", + "650": "Chespin", + "651": "Quilladin", + "652": "Chesnaught", + "653": "Fennekin", + "654": "Braixen", + "655": "Delphox", + "656": "Froakie", + "657": "Frogadier", + "658": "Greninja", + "659": "Bunnelby", + "660": "Diggersby", + "661": "Fletchling", + "662": "Fletchinder", + "663": "Talonflame", + "664": "Scatterbug", + "665": "Spewpa", + "666": "Vivillon", + "667": "Litleo", + "668": "Pyroar", + "669": "Flab\u00e9b\u00e9", + "670": "Floette", + "671": "Florges", + "672": "Skiddo", + "673": "Gogoat", + "674": "Pancham", + "675": "Pangoro", + "676": "Furfrou", + "677": "Espurr", + "678": "Meowstic", + "679": "Honedge", + "680": "Doublade", + "681": "Aegislash", + "682": "Spritzee", + "683": "Aromatisse", + "684": "Swirlix", + "685": "Slurpuff", + "686": "Inkay", + "687": "Malamar", + "688": "Binacle", + "689": "Barbaracle", + "690": "Skrelp", + "691": "Dragalge", + "692": "Clauncher", + "693": "Clawitzer", + "694": "Helioptile", + "695": "Heliolisk", + "696": "Tyrunt", + "697": "Tyrantrum", + "698": "Amaura", + "699": "Aurorus", + "700": "Sylveon", + "701": "Hawlucha", + "702": "Dedenne", + "703": "Carbink", + "704": "Goomy", + "705": "Sliggoo", + "706": "Goodra", + "707": "Klefki", + "708": "Phantump", + "709": "Trevenant", + "710": "Pumpkaboo", + "711": "Gourgeist", + "712": "Bergmite", + "713": "Avalugg", + "714": "Noibat", + "715": "Noivern", + "716": "Xerneas", + "717": "Yveltal", + "718": "Zygarde", + "719": "Diancie", + "720": "Hoopa", "721": "Volcanion" }, + "sizes": { + "001": "min\u00fasculo", + "002": "pequeno", + "003": "normal", + "004": "grande", + "005": "enorme" + }, "teams": { - "0": "Neutro", - "1": "M\u00edstico", - "2": "Valentia", - "3": "Instinto" - }, + "000": "Neutro", + "001": "M\u00edstico", + "002": "Valentia", + "003": "Instinto" + }, + "types": { + "001": "Normal", + "002": "Lutar", + "003": "Voando", + "004": "Veneno", + "005": "Terra", + "006": "Rocha", + "007": "Bicho", + "008": "Fantasma", + "009": "A\u00e7o", + "010": "Fogo", + "011": "\u00c1gua", + "012": "Grama", + "013": "El\u00e9trico", + "014": "Ps\u00edquico", + "015": "Gelo", + "016": "Drag\u00e3o", + "017": "Fada", + "018": "Escuro" + }, "weather": { - "0": "Nenhum", - "1": "Claro", - "2": "Chuva", - "3": "Parcialmente nublado", - "4": "Nublado", - "5": "Ventoso", - "6": "Neve", - "7": "Névoa" - }, - "misc": { - "boosted": "impulsionado" + "000": "Nenhum", + "001": "Claro", + "002": "Chuva", + "003": "Parcialmente nublado", + "004": "Nublado", + "005": "Ventoso", + "006": "Neve", + "007": "N\u00e9voa" } -} +} \ No newline at end of file diff --git a/locales/zh_hk.json b/locales/zh_hk.json index b5382791f..f3e54a073 100644 --- a/locales/zh_hk.json +++ b/locales/zh_hk.json @@ -1,965 +1,965 @@ { "leaders": { - "0": "Professor Willow (\u7dad\u7f85\u535a)", - "1": "Blanche (\u5e03\u862d)", - "2": "Candela (\u574e\u8fea)", - "3": "Spark (\u53f2\u5e15)" - }, - "sizes": { - "1": "\u7d30\u5c0f", - "2": "\u5c0f", - "3": "\u6b63\u5e38", - "4": "\u5927", - "5": "\u5de8\u5927" - }, - "types": { - "1": "\u4e00\u822c", - "2": "\u683c\u9b25", - "3": "\u98db\u884c", - "4": "\u6bd2", - "5": "\u5730\u9762", - "6": "\u5ca9\u77f3", - "7": "\u87f2", - "8": "\u5e7d\u9748", - "9": "\u92fc", - "10": "\u706b", - "11": "\u6c34", - "12": "\u8349", - "13": "\u96fb", - "14": "\u8d85\u80fd\u529b", - "15": "\u51b0", - "16": "\u9f8d", - "17": "\u60e1", - "18": "\u5996\u7cbe" - }, + "000": "Professor Willow (\u7dad\u7f85\u535a)", + "001": "Blanche (\u5e03\u862d)", + "002": "Candela (\u574e\u8fea)", + "003": "Spark (\u53f2\u5e15)" + }, + "misc": { + "boosted": "\u63d0\u632f" + }, "moves": { - "13": "Wrap (\u7dca\u675f)", - "14": "Hyper Beam (\u7834\u58de\u5149\u7dda)", - "16": "Dark Pulse (\u60e1\u4e4b\u6ce2\u52d5)", - "18": "Sludge (\u6c61\u6ce5\u653b\u64ca)", - "20": "Vice Grip (\u593e\u4f4f)", - "21": "Flame Wheel (\u706b\u7130\u8f2a)", - "22": "Megahorn (\u8d85\u7d1a\u89d2\u64ca)", - "24": "Flamethrower (\u5674\u5c04\u706b\u7130)", - "26": "Dig (\u6316\u6d1e)", - "28": "Cross Chop (\u5341\u5b57\u5288)", - "30": "Psybeam (\u5e7b\u8c61\u5149\u7dda)", - "31": "Earthquake (\u5730\u9707)", - "32": "Stone Edge (\u5c16\u77f3\u653b\u64ca)", - "33": "Ice Punch (\u51b0\u51cd\u62f3)", - "34": "Heart Stamp (\u611b\u5fc3\u5370\u7ae0)", - "35": "Discharge (\u653e\u96fb)", - "36": "Flash Cannon (\u52a0\u8fb2\u5149\u70ae)", - "38": "Drill Peck (\u5544\u947d)", - "39": "Ice Beam (\u51b0\u51cd\u5149\u675f)", - "40": "Blizzard (\u66b4\u98a8\u96ea)", - "42": "Heat Wave (\u71b1\u98a8)", - "45": "Aerial Ace (\u71d5\u8fd4)", - "46": "Drill Run (\u76f4\u885d\u947d)", - "47": "Petal Blizzard (\u843d\u82f1\u7e7d\u7d1b)", - "48": "Mega Drain (\u8d85\u7d1a\u5438\u53d6)", - "49": "Bug Buzz (\u87f2\u9cf4)", - "50": "Poison Fang (\u5287\u6bd2\u7259)", - "51": "Night Slash (\u6697\u8972\u8981\u5bb3)", - "53": "Bubble Beam (\u6ce1\u6cab\u5149\u7dda)", - "54": "Submission (\u5730\u7344\u7ffb\u6efe)", - "56": "Low Sweep (\u4e0b\u76e4\u8e22)", - "57": "Aqua Jet (\u6c34\u6d41\u5674\u5c04)", - "58": "Aqua Tail (\u6c34\u6d41\u5c3e)", - "59": "Seed Bomb (\u7a2e\u5b50\u70b8\u5f48)", - "60": "Psyshock (\u7cbe\u795e\u885d\u64ca)", - "62": "Ancient Power (\u539f\u59cb\u4e4b\u529b)", - "63": "Rock Tomb (\u5ca9\u77f3\u5c01\u9396)", - "64": "Rock Slide (\u5ca9\u5d29)", - "65": "Power Gem (\u529b\u91cf\u5bf6\u77f3)", - "66": "Shadow Sneak (\u5f71\u5b50\u5077\u8972)", - "67": "Shadow Punch (\u6697\u5f71\u62f3)", - "69": "Ominous Wind (\u5947\u7570\u4e4b\u98a8)", - "70": "Shadow Ball (\u6697\u5f71\u7403)", - "72": "Magnet Bomb (\u78c1\u9435\u70b8\u5f48)", - "74": "Iron Head (\u9435\u982d)", - "75": "Parabolic Charge (\u62cb\u7269\u9762\u5145\u96fb)", - "77": "Thunder Punch (\u96f7\u96fb\u62f3)", - "78": "Thunder (\u6253\u96f7)", - "79": "Thunderbolt (\u5341\u842c\u4f0f\u7279)", - "80": "Twister (\u9f8d\u6372\u98a8)", - "82": "Dragon Pulse (\u9f8d\u4e4b\u6ce2\u52d5)", - "83": "Dragon Claw (\u9f8d\u722a)", - "84": "Disarming Voice (\u9b45\u60d1\u4e4b\u8072)", - "85": "Draining Kiss (\u5438\u53d6\u4e4b\u543b)", - "86": "Dazzling Gleam (\u9b54\u6cd5\u9583\u8000)", - "87": "Moonblast (\u6708\u4eae\u4e4b\u529b)", - "88": "Play Rough (\u5b09\u9b27)", - "89": "Cross Poison (\u5341\u5b57\u6bd2\u5203)", - "90": "Sludge Bomb (\u6c61\u6ce5\u70b8\u5f48)", - "91": "Sludge Wave (\u6c61\u6ce5\u6ce2)", - "92": "Gunk Shot (\u5783\u573e\u5c04\u64ca)", - "94": "Bone Club (\u9aa8\u68d2)", - "95": "Bulldoze (\u91cd\u8e0f)", - "96": "Mud Bomb (\u6ce5\u5df4\u70b8\u5f48)", - "99": "Signal Beam (\u4fe1\u865f\u5149\u675f)", - "100": "X-Scissor (\u5341\u5b57\u526a)", - "101": "Flame Charge (\u84c4\u80fd\u7130\u8972)", - "102": "Flame Burst (\u70c8\u7130\u6ffa\u5c04)", - "103": "Fire Blast (\u5927\u5b57\u7206\u708e)", - "104": "Brine (\u9e7d\u6c34)", - "105": "Water Pulse (\u6c34\u4e4b\u6ce2\u52d5)", - "106": "Scald (\u71b1\u6c34)", - "107": "Hydro Pump (\u6c34\u70ae)", - "108": "Psychic (\u7cbe\u795e\u5f37\u5ff5)", - "109": "Psystrike (\u7cbe\u795e\u64ca\u7834)", - "111": "Icy Wind (\u51b0\u51cd\u4e4b\u98a8)", - "114": "Giga Drain (\u7d42\u6975\u5438\u53d6)", - "115": "Fire Punch (\u706b\u7130\u62f3)", - "116": "Solar Beam (\u65e5\u5149\u675f)", - "117": "Leaf Blade (\u8449\u5203)", - "118": "Power Whip (\u5f37\u529b\u97ad\u6253)", - "121": "Air Cutter (\u7a7a\u6c23\u5229\u5203)", - "122": "Hurricane (\u66b4\u98a8)", - "123": "Brick Break (\u5288\u74e6)", - "125": "Swift (\u9ad8\u901f\u661f\u661f)", - "126": "Horn Attack (\u89d2\u649e)", - "127": "Stomp (\u8e29\u8e0f)", - "129": "Hyper Fang (\u5fc5\u6bba\u9580\u7259)", - "131": "Body Slam (\u6cf0\u5c71\u58d3\u9802)", - "132": "Rest (\u7761\u89ba)", - "133": "Struggle (\u6399\u624e)", - "134": "Scald (Blastoise) (\u71b1\u6c34)", - "135": "Hydro Pump (Blastoise) (\u6c34\u70ae)", - "136": "Wrap (Green) (\u7dca\u675f)", - "137": "Wrap (Pink) (\u7dca\u675f)", - "200": "Fury Cutter (\u9023\u65ac)", - "201": "Bug Bite (\u87f2\u54ac)", - "202": "Bite (\u54ac\u4f4f)", - "203": "Sucker Punch (\u7a81\u8972)", - "204": "Dragon Breath (\u9f8d\u606f)", - "205": "Thunder Shock (\u96fb\u64ca)", - "206": "Spark (\u96fb\u5149)", - "207": "Low Kick (\u8e22\u5012)", - "208": "Karate Chop (\u7a7a\u624b\u5288)", - "209": "Ember (\u706b\u82b1)", - "210": "Wing Attack (\u7fc5\u8180\u653b\u64ca)", - "211": "Peck (\u5544)", - "212": "Lick (\u820c\u8214)", - "213": "Shadow Claw (\u6697\u5f71\u722a)", - "214": "Vine Whip (\u85e4\u97ad)", - "215": "Razor Leaf (\u98db\u8449\u5feb\u5200)", - "216": "Mud Shot (\u6ce5\u5df4\u5c04\u64ca)", - "217": "Ice Shard (\u51b0\u792b)", - "218": "Frost Breath (\u51b0\u606f)", - "219": "Quick Attack (\u96fb\u5149\u4e00\u9583)", - "220": "Scratch (\u6293)", - "221": "Tackle (\u649e\u64ca)", - "222": "Pound (\u62cd\u64ca)", - "223": "Cut (\u5c45\u5408\u65ac)", - "224": "Poison Jab (\u6bd2\u64ca)", - "225": "Acid (\u6eb6\u89e3\u6db2)", - "226": "Psycho Cut (\u7cbe\u795e\u5229\u5203)", - "227": "Rock Throw (\u843d\u77f3)", - "228": "Metal Claw (\u91d1\u5c6c\u722a)", - "229": "Bullet Punch (\u5b50\u5f48\u62f3)", - "230": "Water Gun (\u6c34\u69cd)", - "231": "Splash (\u8e8d\u8d77)", - "233": "Mud Slap (\u64f2\u6ce5)", - "234": "Zen Headbutt (\u610f\u5ff5\u982d\u9318)", - "235": "Confusion (\u5ff5\u529b)", - "236": "Poison Sting (\u6bd2\u91dd)", - "237": "Bubble (\u6ce1\u6cab)", - "238": "Feint Attack (\u51fa\u5947\u4e00\u64ca)", - "239": "Steel Wing (\u92fc\u7ffc)", - "240": "Fire Fang (\u706b\u7130\u7259)", - "241": "Rock Smash (\u788e\u5ca9)", - "242": "Transform (\u8b8a\u8eab)", - "243": "Counter (\u96d9\u500d\u5949\u9084)", - "244": "Powder Snow (\u7d30\u96ea)", - "245": "Close Combat (\u8fd1\u8eab\u6230)", - "246": "Dynamic Punch (\u7206\u88c2\u62f3)", - "247": "Focus Blast (\u771f\u6c23\u5f48)", - "248": "Aurora Beam (\u6975\u5149\u675f)", - "249": "Charge Beam (\u5145\u96fb\u5149\u675f)", - "250": "Volt Switch (\u4f0f\u7279\u66ff\u63db)", - "251": "Wild Charge (\u760b\u72c2\u4f0f\u7279)", - "252": "Zap Cannon (\u96fb\u78c1\u70ae)", - "253": "Dragon Tail (\u9f8d\u5c3e)", - "254": "Avalanche (\u96ea\u5d29)", - "255": "Air Slash (\u7a7a\u6c23\u65ac)", - "256": "Brave Bird (\u52c7\u9ce5\u731b\u653b)", - "257": "Sky Attack (\u795e\u9ce5\u731b\u64ca)", - "258": "Sand Tomb (\u6d41\u6c99\u5730\u7344)", - "259": "Rock Blast (\u5ca9\u77f3\u7206\u64ca)", - "260": "Infestation (\u6b7b\u7e8f\u721b\u6253)", - "261": "Struggle Bug (\u87f2\u4e4b\u62b5\u6297)", - "262": "Silver Wind (\u9280\u8272\u65cb\u98a8)", - "263": "Astonish (\u9a5a\u5687)", - "264": "Hex (\u798d\u4e0d\u55ae\u884c)", - "265": "Night Shade (\u9ed1\u591c\u9b54\u5f71)", - "266": "Iron Tail (\u9435\u5c3e)", - "267": "Gyro Ball (\u9640\u87ba\u7403)", - "268": "Heavy Slam (\u91cd\u78c5\u885d\u649e)", - "269": "Fire Spin (\u706b\u7130\u65cb\u6e26)", - "270": "Overheat (\u904e\u71b1)", - "271": "Bullet Seed (\u7a2e\u5b50\u6a5f\u95dc\u69cd)", - "272": "Grass Knot (\u6253\u8349\u7d50)", - "273": "Energy Ball (\u80fd\u91cf\u7403)", - "274": "Extrasensory (\u795e\u901a\u529b)", - "275": "Future Sight (\u9810\u77e5\u672a\u4f86)", - "276": "Mirror Coat (\u93e1\u9762\u53cd\u5c04)", - "277": "Outrage (\u9006\u9e9f)", - "278": "Snarl (\u5927\u8072\u5486\u54ee)", - "279": "Crunch (\u54ac\u788e)", - "280": "Foul Play (\u6b3a\u8a50)", - "281": "Hidden Power (\u89ba\u9192\u529b\u91cf)", - "282": "Take Down (\u731b\u649e)", - "283": "Waterfall (\u6500\u7011)", - "284": "Surf (\u885d\u6d6a)", - "285": "Draco Meteor (\u6d41\u661f\u7fa4)", - "286": "Doom Desire (\u7834\u6ec5\u4e4b\u9858)", - "287": "Yawn (\u54c8\u6b20)", - "288": "Psycho Boost (\u7cbe\u795e\u7a81\u9032)", - "289": "Origin Pulse (\u6839\u6e90\u6ce2\u52d5)", - "290": "Precipice Blades (\u65b7\u5d16\u4e4b\u528d)", + "013": "Wrap (\u7dca\u675f)", + "014": "Hyper Beam (\u7834\u58de\u5149\u7dda)", + "016": "Dark Pulse (\u60e1\u4e4b\u6ce2\u52d5)", + "018": "Sludge (\u6c61\u6ce5\u653b\u64ca)", + "020": "Vice Grip (\u593e\u4f4f)", + "021": "Flame Wheel (\u706b\u7130\u8f2a)", + "022": "Megahorn (\u8d85\u7d1a\u89d2\u64ca)", + "024": "Flamethrower (\u5674\u5c04\u706b\u7130)", + "026": "Dig (\u6316\u6d1e)", + "028": "Cross Chop (\u5341\u5b57\u5288)", + "030": "Psybeam (\u5e7b\u8c61\u5149\u7dda)", + "031": "Earthquake (\u5730\u9707)", + "032": "Stone Edge (\u5c16\u77f3\u653b\u64ca)", + "033": "Ice Punch (\u51b0\u51cd\u62f3)", + "034": "Heart Stamp (\u611b\u5fc3\u5370\u7ae0)", + "035": "Discharge (\u653e\u96fb)", + "036": "Flash Cannon (\u52a0\u8fb2\u5149\u70ae)", + "038": "Drill Peck (\u5544\u947d)", + "039": "Ice Beam (\u51b0\u51cd\u5149\u675f)", + "040": "Blizzard (\u66b4\u98a8\u96ea)", + "042": "Heat Wave (\u71b1\u98a8)", + "045": "Aerial Ace (\u71d5\u8fd4)", + "046": "Drill Run (\u76f4\u885d\u947d)", + "047": "Petal Blizzard (\u843d\u82f1\u7e7d\u7d1b)", + "048": "Mega Drain (\u8d85\u7d1a\u5438\u53d6)", + "049": "Bug Buzz (\u87f2\u9cf4)", + "050": "Poison Fang (\u5287\u6bd2\u7259)", + "051": "Night Slash (\u6697\u8972\u8981\u5bb3)", + "053": "Bubble Beam (\u6ce1\u6cab\u5149\u7dda)", + "054": "Submission (\u5730\u7344\u7ffb\u6efe)", + "056": "Low Sweep (\u4e0b\u76e4\u8e22)", + "057": "Aqua Jet (\u6c34\u6d41\u5674\u5c04)", + "058": "Aqua Tail (\u6c34\u6d41\u5c3e)", + "059": "Seed Bomb (\u7a2e\u5b50\u70b8\u5f48)", + "060": "Psyshock (\u7cbe\u795e\u885d\u64ca)", + "062": "Ancient Power (\u539f\u59cb\u4e4b\u529b)", + "063": "Rock Tomb (\u5ca9\u77f3\u5c01\u9396)", + "064": "Rock Slide (\u5ca9\u5d29)", + "065": "Power Gem (\u529b\u91cf\u5bf6\u77f3)", + "066": "Shadow Sneak (\u5f71\u5b50\u5077\u8972)", + "067": "Shadow Punch (\u6697\u5f71\u62f3)", + "069": "Ominous Wind (\u5947\u7570\u4e4b\u98a8)", + "070": "Shadow Ball (\u6697\u5f71\u7403)", + "072": "Magnet Bomb (\u78c1\u9435\u70b8\u5f48)", + "074": "Iron Head (\u9435\u982d)", + "075": "Parabolic Charge (\u62cb\u7269\u9762\u5145\u96fb)", + "077": "Thunder Punch (\u96f7\u96fb\u62f3)", + "078": "Thunder (\u6253\u96f7)", + "079": "Thunderbolt (\u5341\u842c\u4f0f\u7279)", + "080": "Twister (\u9f8d\u6372\u98a8)", + "082": "Dragon Pulse (\u9f8d\u4e4b\u6ce2\u52d5)", + "083": "Dragon Claw (\u9f8d\u722a)", + "084": "Disarming Voice (\u9b45\u60d1\u4e4b\u8072)", + "085": "Draining Kiss (\u5438\u53d6\u4e4b\u543b)", + "086": "Dazzling Gleam (\u9b54\u6cd5\u9583\u8000)", + "087": "Moonblast (\u6708\u4eae\u4e4b\u529b)", + "088": "Play Rough (\u5b09\u9b27)", + "089": "Cross Poison (\u5341\u5b57\u6bd2\u5203)", + "090": "Sludge Bomb (\u6c61\u6ce5\u70b8\u5f48)", + "091": "Sludge Wave (\u6c61\u6ce5\u6ce2)", + "092": "Gunk Shot (\u5783\u573e\u5c04\u64ca)", + "094": "Bone Club (\u9aa8\u68d2)", + "095": "Bulldoze (\u91cd\u8e0f)", + "096": "Mud Bomb (\u6ce5\u5df4\u70b8\u5f48)", + "099": "Signal Beam (\u4fe1\u865f\u5149\u675f)", + "100": "X-Scissor (\u5341\u5b57\u526a)", + "101": "Flame Charge (\u84c4\u80fd\u7130\u8972)", + "102": "Flame Burst (\u70c8\u7130\u6ffa\u5c04)", + "103": "Fire Blast (\u5927\u5b57\u7206\u708e)", + "104": "Brine (\u9e7d\u6c34)", + "105": "Water Pulse (\u6c34\u4e4b\u6ce2\u52d5)", + "106": "Scald (\u71b1\u6c34)", + "107": "Hydro Pump (\u6c34\u70ae)", + "108": "Psychic (\u7cbe\u795e\u5f37\u5ff5)", + "109": "Psystrike (\u7cbe\u795e\u64ca\u7834)", + "111": "Icy Wind (\u51b0\u51cd\u4e4b\u98a8)", + "114": "Giga Drain (\u7d42\u6975\u5438\u53d6)", + "115": "Fire Punch (\u706b\u7130\u62f3)", + "116": "Solar Beam (\u65e5\u5149\u675f)", + "117": "Leaf Blade (\u8449\u5203)", + "118": "Power Whip (\u5f37\u529b\u97ad\u6253)", + "121": "Air Cutter (\u7a7a\u6c23\u5229\u5203)", + "122": "Hurricane (\u66b4\u98a8)", + "123": "Brick Break (\u5288\u74e6)", + "125": "Swift (\u9ad8\u901f\u661f\u661f)", + "126": "Horn Attack (\u89d2\u649e)", + "127": "Stomp (\u8e29\u8e0f)", + "129": "Hyper Fang (\u5fc5\u6bba\u9580\u7259)", + "131": "Body Slam (\u6cf0\u5c71\u58d3\u9802)", + "132": "Rest (\u7761\u89ba)", + "133": "Struggle (\u6399\u624e)", + "134": "Scald (Blastoise) (\u71b1\u6c34)", + "135": "Hydro Pump (Blastoise) (\u6c34\u70ae)", + "136": "Wrap (Green) (\u7dca\u675f)", + "137": "Wrap (Pink) (\u7dca\u675f)", + "200": "Fury Cutter (\u9023\u65ac)", + "201": "Bug Bite (\u87f2\u54ac)", + "202": "Bite (\u54ac\u4f4f)", + "203": "Sucker Punch (\u7a81\u8972)", + "204": "Dragon Breath (\u9f8d\u606f)", + "205": "Thunder Shock (\u96fb\u64ca)", + "206": "Spark (\u96fb\u5149)", + "207": "Low Kick (\u8e22\u5012)", + "208": "Karate Chop (\u7a7a\u624b\u5288)", + "209": "Ember (\u706b\u82b1)", + "210": "Wing Attack (\u7fc5\u8180\u653b\u64ca)", + "211": "Peck (\u5544)", + "212": "Lick (\u820c\u8214)", + "213": "Shadow Claw (\u6697\u5f71\u722a)", + "214": "Vine Whip (\u85e4\u97ad)", + "215": "Razor Leaf (\u98db\u8449\u5feb\u5200)", + "216": "Mud Shot (\u6ce5\u5df4\u5c04\u64ca)", + "217": "Ice Shard (\u51b0\u792b)", + "218": "Frost Breath (\u51b0\u606f)", + "219": "Quick Attack (\u96fb\u5149\u4e00\u9583)", + "220": "Scratch (\u6293)", + "221": "Tackle (\u649e\u64ca)", + "222": "Pound (\u62cd\u64ca)", + "223": "Cut (\u5c45\u5408\u65ac)", + "224": "Poison Jab (\u6bd2\u64ca)", + "225": "Acid (\u6eb6\u89e3\u6db2)", + "226": "Psycho Cut (\u7cbe\u795e\u5229\u5203)", + "227": "Rock Throw (\u843d\u77f3)", + "228": "Metal Claw (\u91d1\u5c6c\u722a)", + "229": "Bullet Punch (\u5b50\u5f48\u62f3)", + "230": "Water Gun (\u6c34\u69cd)", + "231": "Splash (\u8e8d\u8d77)", + "233": "Mud Slap (\u64f2\u6ce5)", + "234": "Zen Headbutt (\u610f\u5ff5\u982d\u9318)", + "235": "Confusion (\u5ff5\u529b)", + "236": "Poison Sting (\u6bd2\u91dd)", + "237": "Bubble (\u6ce1\u6cab)", + "238": "Feint Attack (\u51fa\u5947\u4e00\u64ca)", + "239": "Steel Wing (\u92fc\u7ffc)", + "240": "Fire Fang (\u706b\u7130\u7259)", + "241": "Rock Smash (\u788e\u5ca9)", + "242": "Transform (\u8b8a\u8eab)", + "243": "Counter (\u96d9\u500d\u5949\u9084)", + "244": "Powder Snow (\u7d30\u96ea)", + "245": "Close Combat (\u8fd1\u8eab\u6230)", + "246": "Dynamic Punch (\u7206\u88c2\u62f3)", + "247": "Focus Blast (\u771f\u6c23\u5f48)", + "248": "Aurora Beam (\u6975\u5149\u675f)", + "249": "Charge Beam (\u5145\u96fb\u5149\u675f)", + "250": "Volt Switch (\u4f0f\u7279\u66ff\u63db)", + "251": "Wild Charge (\u760b\u72c2\u4f0f\u7279)", + "252": "Zap Cannon (\u96fb\u78c1\u70ae)", + "253": "Dragon Tail (\u9f8d\u5c3e)", + "254": "Avalanche (\u96ea\u5d29)", + "255": "Air Slash (\u7a7a\u6c23\u65ac)", + "256": "Brave Bird (\u52c7\u9ce5\u731b\u653b)", + "257": "Sky Attack (\u795e\u9ce5\u731b\u64ca)", + "258": "Sand Tomb (\u6d41\u6c99\u5730\u7344)", + "259": "Rock Blast (\u5ca9\u77f3\u7206\u64ca)", + "260": "Infestation (\u6b7b\u7e8f\u721b\u6253)", + "261": "Struggle Bug (\u87f2\u4e4b\u62b5\u6297)", + "262": "Silver Wind (\u9280\u8272\u65cb\u98a8)", + "263": "Astonish (\u9a5a\u5687)", + "264": "Hex (\u798d\u4e0d\u55ae\u884c)", + "265": "Night Shade (\u9ed1\u591c\u9b54\u5f71)", + "266": "Iron Tail (\u9435\u5c3e)", + "267": "Gyro Ball (\u9640\u87ba\u7403)", + "268": "Heavy Slam (\u91cd\u78c5\u885d\u649e)", + "269": "Fire Spin (\u706b\u7130\u65cb\u6e26)", + "270": "Overheat (\u904e\u71b1)", + "271": "Bullet Seed (\u7a2e\u5b50\u6a5f\u95dc\u69cd)", + "272": "Grass Knot (\u6253\u8349\u7d50)", + "273": "Energy Ball (\u80fd\u91cf\u7403)", + "274": "Extrasensory (\u795e\u901a\u529b)", + "275": "Future Sight (\u9810\u77e5\u672a\u4f86)", + "276": "Mirror Coat (\u93e1\u9762\u53cd\u5c04)", + "277": "Outrage (\u9006\u9e9f)", + "278": "Snarl (\u5927\u8072\u5486\u54ee)", + "279": "Crunch (\u54ac\u788e)", + "280": "Foul Play (\u6b3a\u8a50)", + "281": "Hidden Power (\u89ba\u9192\u529b\u91cf)", + "282": "Take Down (\u731b\u649e)", + "283": "Waterfall (\u6500\u7011)", + "284": "Surf (\u885d\u6d6a)", + "285": "Draco Meteor (\u6d41\u661f\u7fa4)", + "286": "Doom Desire (\u7834\u6ec5\u4e4b\u9858)", + "287": "Yawn (\u54c8\u6b20)", + "288": "Psycho Boost (\u7cbe\u795e\u7a81\u9032)", + "289": "Origin Pulse (\u6839\u6e90\u6ce2\u52d5)", + "290": "Precipice Blades (\u65b7\u5d16\u4e4b\u528d)", "291": "Present (\u79ae\u7269)" - }, + }, "pokemon": { - "1": "\u5947\u7570\u7a2e\u5b50", - "2": "\u5947\u7570\u8349", - "3": "\u5947\u7570\u82b1", - "4": "\u5c0f\u706b\u9f8d", - "5": "\u706b\u6050\u9f8d", - "6": "\u5674\u706b\u9f8d", - "7": "\u8eca\u5398\u9f9c", - "8": "\u5361\u7f8e\u9f9c", - "9": "\u6c34\u7bad\u9f9c", - "10": "\u7da0\u6bdb\u87f2", - "11": "\u9435\u7532\u87f2", - "12": "\u5df4\u4ed6\u8776", - "13": "\u7368\u89d2\u87f2", - "14": "\u9435\u6bbc\u86f9", - "15": "\u5927\u91dd\u8702", - "16": "\u6ce2\u6ce2", - "17": "\u6bd4\u6bd4\u9ce5", - "18": "\u5927\u6bd4\u9ce5", - "19": "\u5c0f\u54e5\u9054", - "20": "\u54e5\u9054", - "21": "\u9b3c\u96c0", - "22": "\u9b54\u96c0", - "23": "\u963f\u67cf\u86c7", - "24": "\u963f\u67cf\u602a", - "25": "\u6bd4\u5361\u8d85", - "26": "\u96f7\u8d85", - "27": "\u7a7f\u5c71\u9f20", - "28": "\u7a7f\u5c71\u738b", - "29": "\u5c3c\u7f8e\u862d", - "30": "\u5c3c\u7f8e\u863f", - "31": "\u5c3c\u7f8e\u540e", - "32": "\u5c3c\u591a\u90ce", - "33": "\u5c3c\u591a\u5229", - "34": "\u5c3c\u591a\u738b", - "35": "\u76ae\u76ae", - "36": "\u76ae\u53ef\u65af", - "37": "\u516d\u5c3e", - "38": "\u4e5d\u5c3e", - "39": "\u6ce2\u6ce2\u7403", - "40": "\u80a5\u6ce2\u7403", - "41": "\u6ce2\u97f3\u8760", - "42": "\u5927\u53e3\u8760", - "43": "\u884c\u8def\u8349", - "44": "\u602a\u5473\u82b1", - "45": "\u9738\u738b\u82b1", - "46": "\u8611\u83c7\u87f2", - "47": "\u5de8\u83c7\u87f2", - "48": "\u6bdb\u6bdb\u87f2", - "49": "\u9b54\u9b6f\u98a8", - "50": "\u5730\u9f20", - "51": "\u4e09\u982d\u5730\u9f20", - "52": "\u55b5\u55b5\u602a", - "53": "\u9ad8\u7ac7\u8c93", - "54": "\u50bb\u9d28", - "55": "\u9ad8\u8d85\u9d28", - "56": "\u7334\u602a", - "57": "\u706b\u7206\u7334", - "58": "\u8b77\u4e3b\u72ac", - "59": "\u5949\u795e\u72ac", - "60": "\u868a\u9999\u874c\u86aa", - "61": "\u868a\u9999\u86d9", - "62": "\u5927\u529b\u86d9", - "63": "\u5361\u65af", - "64": "\u5c24\u57fa\u7d0d", - "65": "\u5bcc\u8fea", - "66": "\u9435\u8155", - "67": "\u5927\u529b", - "68": "\u602a\u529b", - "69": "\u5587\u53ed\u82bd", - "70": "\u53e3\u5446\u82b1", - "71": "\u5927\u98df\u82b1", - "72": "\u5927\u773c\u6c34\u6bcd", - "73": "\u591a\u8173\u6c34\u6bcd", - "74": "\u5c0f\u62f3\u77f3", - "75": "\u6efe\u52d5\u77f3", - "76": "\u6efe\u52d5\u5ca9", - "77": "\u5c0f\u706b\u99ac", - "78": "\u70c8\u7130\u99ac", - "79": "\u5c0f\u5446\u7378", - "80": "\u5927\u5446\u7378", - "81": "\u5c0f\u78c1\u602a", - "82": "\u4e09\u5408\u4e00\u78c1\u602a", - "83": "\u706b\u8525\u9d28", - "84": "\u591a\u591a", - "85": "\u591a\u591a\u5229", - "86": "\u5c0f\u6d77\u7345", - "87": "\u767d\u6d77\u7345", - "88": "\u721b\u6ce5\u602a", - "89": "\u721b\u6ce5\u7378", - "90": "\u8c9d\u6bbc\u602a", - "91": "\u9435\u7532\u8c9d", - "92": "\u9b3c\u65af", - "93": "\u9b3c\u65af\u901a", - "94": "\u803f\u9b3c", - "95": "\u5927\u5ca9\u86c7", - "96": "\u98df\u5922\u7378", - "97": "\u50ac\u7720\u7378", - "98": "\u5927\u9257\u87f9", - "99": "\u5de8\u9257\u87f9", - "100": "\u9739\u9742\u86cb", - "101": "\u96f7\u9706\u86cb", - "102": "\u86cb\u86cb", - "103": "\u6930\u6a39\u7378", - "104": "\u5361\u62c9\u5361\u62c9", - "105": "\u683c\u62c9\u683c\u62c9", - "106": "\u6c99\u53e4\u62c9", - "107": "\u6bd4\u83ef\u62c9", - "108": "\u5927\u820c\u982d", - "109": "\u6bd2\u6c23\u4e38", - "110": "\u6bd2\u6c23\u96d9\u5b50", - "111": "\u9435\u7532\u7280\u725b", - "112": "\u9435\u7532\u66b4\u9f8d", - "113": "\u5409\u5229\u86cb", - "114": "\u9577\u7c50\u602a", - "115": "\u888b\u7378", - "116": "\u5674\u58a8\u6d77\u99ac", - "117": "\u98db\u523a\u6d77\u99ac", - "118": "\u7368\u89d2\u91d1\u9b5a", - "119": "\u91d1\u9b5a\u738b", - "120": "\u6d77\u661f\u661f", - "121": "\u5bf6\u77f3\u6d77\u661f", - "122": "\u5438\u76e4\u5c0f\u4e11", - "123": "\u98db\u5929\u87b3\u8782", - "124": "\u7d05\u5507\u5a03", - "125": "\u96fb\u64ca\u7378", - "126": "\u9d28\u5634\u706b\u9f8d", - "127": "\u9257\u5200\u7532\u87f2", - "128": "\u5927\u96bb\u725b", - "129": "\u9bc9\u9b5a\u738b", - "130": "\u9bc9\u9b5a\u9f8d", - "131": "\u80cc\u80cc\u9f8d", - "132": "\u767e\u8b8a\u602a", - "133": "\u4f0a\u8c9d", - "134": "\u6c34\u4f0a\u8c9d", - "135": "\u96f7\u4f0a\u8c9d", - "136": "\u706b\u4f0a\u8c9d", - "137": "\u7acb\u65b9\u7378", - "138": "\u83ca\u77f3\u7378", - "139": "\u591a\u523a\u83ca\u77f3\u7378", - "140": "\u842c\u5e74\u87f2", - "141": "\u942e\u5200\u87f2", - "142": "\u5316\u77f3\u98db\u9f8d", - "143": "\u5361\u6bd4\u7378", - "144": "\u6025\u51cd\u9ce5", - "145": "\u96f7\u9ce5", - "146": "\u706b\u9ce5", - "147": "\u8ff7\u4f60\u9f8d", - "148": "\u54c8\u53e4\u9f8d", - "149": "\u555f\u66b4\u9f8d", - "150": "\u8d85\u5922\u5922", - "151": "\u5922\u5922", - "152": "\u83ca\u8349\u8449", - "153": "\u6708\u6842\u8449", - "154": "\u5927\u83ca\u82b1", - "155": "\u706b\u7403\u9f20", - "156": "\u706b\u5ca9\u9f20", - "157": "\u706b\u66b4\u7378", - "158": "\u5c0f\u92f8\u9c77", - "159": "\u85cd\u9c77", - "160": "\u5927\u529b\u9c77", - "161": "\u5c3e\u7acb", - "162": "\u5927\u5c3e\u7acb", - "163": "\u5495\u5495", - "164": "\u8c93\u982d\u591c\u9df9", - "165": "\u82ad\u74e2\u87f2", - "166": "\u5b89\u74e2\u87f2", - "167": "\u7dda\u7403", - "168": "\u963f\u5229\u591a\u65af", - "169": "\u53c9\u5b57\u8760", - "170": "\u71c8\u7c60\u9b5a", - "171": "\u96fb\u71c8\u602a", - "172": "\u6bd4\u8d85", - "173": "\u76ae\u5bf6\u5bf6", - "174": "\u5c0f\u6ce2\u7403", - "175": "\u5c0f\u523a\u86cb", - "176": "\u6ce2\u514b\u57fa\u53e4", - "177": "\u5929\u7136\u96c0", - "178": "\u5929\u7136\u9ce5", - "179": "\u54a9\u5229\u7f8a", - "180": "\u7dbf\u7dbf", - "181": "\u96fb\u9f8d", - "182": "\u7f8e\u9e97\u82b1", - "183": "\u746a\u5229\u9732", - "184": "\u746a\u5229\u9732\u9e97", - "185": "\u80e1\u8aaa\u6a39", - "186": "\u725b\u86d9\u541b", - "187": "\u6bfd\u5b50\u8349", - "188": "\u6bfd\u5b50\u82b1", - "189": "\u6bfd\u5b50\u7dbf", - "190": "\u9577\u5c3e\u602a\u624b", - "191": "\u5411\u65e5\u7a2e\u5b50", - "192": "\u5411\u65e5\u82b1\u602a", - "193": "\u967d\u967d\u746a", - "194": "\u70cf\u6ce2", - "195": "\u6cbc\u738b", - "196": "\u592a\u967d\u4f0a\u8c9d", - "197": "\u6708\u4f0a\u8c9d", - "198": "\u9ed1\u6697\u9d09", - "199": "\u6cb3\u99ac\u738b", - "200": "\u5922\u5996", - "201": "\u672a\u77e5\u5716\u9a30", - "202": "\u679c\u7136\u7fc1", - "203": "\u9e92\u9e9f\u5947", - "204": "\u699b\u679c\u7403", - "205": "\u4f5b\u70c8\u8a17\u65af", - "206": "\u571f\u9f8d\u5f1f\u5f1f", - "207": "\u5929\u880d", - "208": "\u5927\u92fc\u86c7", - "209": "\u5e03\u9b6f", - "210": "\u5e03\u9b6f\u7687", - "211": "\u5343\u91dd\u9b5a", - "212": "\u5de8\u9257\u87b3\u8782", - "213": "\u58fa\u58fa", - "214": "\u8d6b\u62c9\u514b\u7f85\u65af", - "215": "\u72c3\u62c9", - "216": "\u718a\u5bf6\u5bf6", - "217": "\u5708\u5708\u718a", - "218": "\u7194\u5ca9\u87f2", - "219": "\u7194\u5ca9\u8778\u725b", - "220": "\u5c0f\u5c71\u8c6c", - "221": "\u9577\u6bdb\u8c6c", - "222": "\u592a\u967d\u73ca\u745a", - "223": "\u9435\u70ae\u9b5a", - "224": "\u7ae0\u9b5a\u6876", - "225": "\u4fe1\u4f7f\u9ce5", - "226": "\u5de8\u7fc5\u98db\u9b5a", - "227": "\u76d4\u7532\u9ce5", - "228": "\u6234\u9b6f\u6bd4", - "229": "\u9ed1\u9b6f\u52a0", - "230": "\u523a\u9f8d\u738b", - "231": "\u5c0f\u5c0f\u8c61", - "232": "\u51ac\u51e1", - "233": "\u7acb\u65b9\u7378\uff12", - "234": "\u9a5a\u89d2\u9e7f", - "235": "\u5716\u5716\u72ac", - "236": "\u5df4\u723e\u90ce", - "237": "\u67ef\u6ce2\u6717", - "238": "\u8ff7\u5507\u5a03", - "239": "\u96fb\u64ca\u602a", - "240": "\u5c0f\u9d28\u5634\u9f8d", - "241": "\u5927\u5976\u7f50", - "242": "\u5e78\u798f\u86cb", - "243": "\u96f7\u516c", - "244": "\u708e\u5e1d", - "245": "\u6c34\u541b", - "246": "\u7531\u57fa\u62c9", - "247": "\u6c99\u57fa\u62c9", - "248": "\u73ed\u5409\u62c9", - "249": "\u5229\u57fa\u4e9e", - "250": "\u9cf3\u51f0", - "251": "\u96ea\u62c9\u6bd4", - "252": "\u6728\u5b88\u5bae", - "253": "\u68ee\u6797\u8725\u8734", - "254": "\u8725\u8734\u738b", - "255": "\u706b\u7a1a\u96de", - "256": "\u529b\u58ef\u96de", - "257": "\u706b\u7130\u96de", - "258": "\u6c34\u8e8d\u9b5a", - "259": "\u6cbc\u8e8d\u9b5a", - "260": "\u5de8\u6cbc\u602a", - "261": "\u571f\u72fc\u72ac", - "262": "\u5927\u72fc\u72ac", - "263": "\u86c7\u7d0b\u718a", - "264": "\u76f4\u885d\u718a", - "265": "\u523a\u5c3e\u87f2", - "266": "\u7532\u6bbc\u86f9", - "267": "\u72e9\u7375\u9cf3\u8776", - "268": "\u76fe\u7532\u7e6d", - "269": "\u6bd2\u7c89\u8776", - "270": "\u84ee\u8449\u7ae5\u5b50", - "271": "\u84ee\u5e3d\u5c0f\u7ae5", - "272": "\u6a02\u5929\u6cb3\u7ae5", - "273": "\u6a61\u5be6\u679c", - "274": "\u9577\u9f3b\u8449", - "275": "\u72e1\u733e\u5929\u72d7", - "276": "\u50b2\u9aa8\u71d5", - "277": "\u5927\u738b\u71d5", - "278": "\u9577\u7fc5\u9dd7", - "279": "\u5927\u5634\u9dd7", - "280": "\u62c9\u9b6f\u62c9\u7d72", - "281": "\u5947\u9b6f\u8389\u5b89", - "282": "\u6c99\u5948\u6735", - "283": "\u6e9c\u6e9c\u7cd6\u7403", - "284": "\u96e8\u7fc5\u86fe", - "285": "\u8611\u8611\u83c7", - "286": "\u6597\u7b20\u83c7", - "287": "\u61f6\u4eba\u7fc1", - "288": "\u904e\u52d5\u733f", - "289": "\u8acb\u5047\u738b", - "290": "\u571f\u5c45\u5fcd\u58eb", - "291": "\u9435\u9762\u5fcd\u8005", - "292": "\u812b\u6bbc\u5fcd\u8005", - "293": "\u5495\u599e\u599e", - "294": "\u543c\u7206\u5f48", - "295": "\u7206\u97f3\u602a", - "296": "\u5e55\u4e0b\u529b\u58eb", - "297": "\u8d85\u529b\u738b", - "298": "\u9732\u529b\u9e97", - "299": "\u671d\u5317\u9f3b", - "300": "\u5411\u5c3e\u55b5", - "301": "\u512a\u96c5\u8c93", - "302": "\u52fe\u9b42\u773c", - "303": "\u5927\u5634\u5a03", - "304": "\u53ef\u53ef\u591a\u62c9", - "305": "\u53ef\u591a\u62c9", - "306": "\u6ce2\u58eb\u53ef\u591a\u62c9", - "307": "\u746a\u6c99\u90a3", - "308": "\u6070\u96f7\u59c6", - "309": "\u843d\u96f7\u7378", - "310": "\u96f7\u96fb\u7378", - "311": "\u6b63\u96fb\u62cd\u62cd", - "312": "\u8ca0\u96fb\u62cd\u62cd", - "313": "\u96fb\u87a2\u87f2", - "314": "\u751c\u751c\u87a2", - "315": "\u6bd2\u8594\u8587", - "316": "\u6eb6\u98df\u7378", - "317": "\u541e\u98df\u7378", - "318": "\u5229\u7259\u9b5a", - "319": "\u5de8\u7259\u9bca", - "320": "\u543c\u543c\u9be8", - "321": "\u543c\u9be8\u738b", - "322": "\u5446\u706b\u99dd", - "323": "\u5674\u706b\u99dd", - "324": "\u7164\u70ad\u9f9c", - "325": "\u8df3\u8df3\u8c6c", - "326": "\u5657\u5657\u8c6c", - "327": "\u6643\u6643\u6591", - "328": "\u5927\u984e\u87fb", - "329": "\u8d85\u97f3\u6ce2\u5e7c\u87f2", - "330": "\u6c99\u6f20\u873b\u8713", - "331": "\u6c99\u6f20\u5948\u4e9e", - "332": "\u5922\u6b4c\u5948\u4e9e", - "333": "\u9752\u7dbf\u9ce5", - "334": "\u4e03\u5915\u9752\u9ce5", - "335": "\u8c93\u9f2c\u65ac", - "336": "\u98ef\u5319\u86c7", - "337": "\u6708\u77f3", - "338": "\u592a\u967d\u5ca9", - "339": "\u6ce5\u6ce5\u9c0d", - "340": "\u9bf0\u9b5a\u738b", - "341": "\u9f8d\u8766\u5c0f\u5175", - "342": "\u9435\u87c4\u9f8d\u8766", - "343": "\u5929\u79e4\u5076", - "344": "\u5ff5\u529b\u571f\u5076", - "345": "\u89f8\u624b\u767e\u5408", - "346": "\u6416\u7c43\u767e\u5408", - "347": "\u592a\u53e4\u7fbd\u87f2", - "348": "\u592a\u53e4\u76d4\u7532", - "349": "\u7b28\u7b28\u9b5a", - "350": "\u7f8e\u7d0d\u65af", - "351": "\u6f02\u6d6e\u6ce1\u6ce1", - "352": "\u8b8a\u96b1\u9f8d", - "353": "\u6028\u5f71\u5a03\u5a03", - "354": "\u8a5b\u5492\u5a03\u5a03", - "355": "\u591c\u9ab7\u9acf", - "356": "\u591c\u5de8\u4eba", - "357": "\u71b1\u5e36\u9f8d", - "358": "\u98a8\u9234\u9234", - "359": "\u963f\u52c3\u68ad\u9b6f", - "360": "\u679c\u7136\u4ed4", - "361": "\u96ea\u7ae5\u5b50", - "362": "\u51b0\u9b3c\u8b77", - "363": "\u6d77\u8c79\u7403", - "364": "\u6d77\u9b54\u7345", - "365": "\u5e1d\u7259\u6d77\u7345", - "366": "\u73cd\u73e0\u8c9d", - "367": "\u7375\u6591\u9b5a", - "368": "\u6afb\u82b1\u9b5a", - "369": "\u53e4\u7a7a\u68d8\u9b5a", - "370": "\u611b\u5fc3\u9b5a", - "371": "\u5bf6\u8c9d\u9f8d", - "372": "\u7532\u6bbc\u9f8d", - "373": "\u66b4\u8811\u8788", - "374": "\u9435\u555e\u9234", - "375": "\u91d1\u5c6c\u602a", - "376": "\u5de8\u91d1\u602a", - "377": "\u96f7\u5409\u6d1b\u514b", - "378": "\u96f7\u5409\u827e\u65af", - "379": "\u96f7\u5409\u65af\u5947\u9b6f", - "380": "\u62c9\u5e1d\u4e9e\u65af", - "381": "\u62c9\u5e1d\u6b50\u65af", - "382": "\u84cb\u6b50\u5361", - "383": "\u56fa\u62c9\u591a", - "384": "\u70c8\u7a7a\u5750", - "385": "\u57fa\u62c9\u7948", - "386": "\u4ee3\u6b50\u5947\u5e0c\u65af", - "387": "\u8349\u82d7\u9f9c", - "388": "\u6a39\u6797\u9f9c", - "389": "\u571f\u53f0\u9f9c", - "390": "\u5c0f\u706b\u7130\u7334", - "391": "\u731b\u706b\u7334", - "392": "\u70c8\u7130\u7334", - "393": "\u6ce2\u52a0\u66fc", - "394": "\u6ce2\u7687\u5b50", - "395": "\u5e1d\u7687\u62ff\u6ce2", - "396": "\u59c6\u514b\u5152", - "397": "\u59c6\u514b\u9ce5", - "398": "\u59c6\u514b\u9df9", - "399": "\u5927\u7259\u72f8", - "400": "\u5927\u5c3e\u72f8", - "401": "\u5713\u6cd5\u5e2b", - "402": "\u97f3\u7bb1\u87c0", - "403": "\u5c0f\u8c93\u602a", - "404": "\u52d2\u514b\u8c93", - "405": "\u502b\u7434\u8c93", - "406": "\u542b\u7f9e\u82de", - "407": "\u7f85\u7d72\u96f7\u6735", - "408": "\u982d\u84cb\u9f8d", - "409": "\u6230\u69cc\u9f8d", - "410": "\u76fe\u7532\u9f8d", - "411": "\u8b77\u57ce\u9f8d", - "412": "\u7d50\u8349\u5152", - "413": "\u7d50\u8349\u8cb4\u5a66", - "414": "\u7d33\u58eb\u86fe", - "415": "\u4e09\u871c\u8702", - "416": "\u8702\u540e", - "417": "\u5e15\u5947\u5229\u8332", - "418": "\u6cf3\u6c23\u9f2c", - "419": "\u6d6e\u6f5b\u9f2c", - "420": "\u6afb\u82b1\u5bf6", - "421": "\u6afb\u82b1\u5152", - "422": "\u7121\u6bbc\u6d77\u725b", - "423": "\u6d77\u725b\u7378", - "424": "\u96d9\u5c3e\u602a\u624b", - "425": "\u98c4\u98c4\u7403", - "426": "\u9644\u548c\u6c23\u7403", - "427": "\u6372\u6372\u8033", - "428": "\u9577\u8033\u5154", - "429": "\u5922\u5996\u9b54", - "430": "\u70cf\u9d09\u982d\u982d", - "431": "\u9b45\u529b\u55b5", - "432": "\u6771\u65bd\u55b5", - "433": "\u9234\u5679\u97ff", - "434": "\u81ed\u9f2c\u5657", - "435": "\u5766\u514b\u81ed\u9f2c", - "436": "\u9285\u93e1\u602a", - "437": "\u9752\u9285\u9418", - "438": "\u611b\u54ed\u6a39", - "439": "\u9b54\u5c3c\u5c3c", - "440": "\u597d\u904b\u86cb", - "441": "\u8052\u566a\u9ce5", - "442": "\u82b1\u5ca9\u602a", - "443": "\u5713\u9678\u9bca", - "444": "\u5c16\u7259\u9678\u9bca", - "445": "\u70c8\u54ac\u9678\u9bca", - "446": "\u5c0f\u5361\u6bd4\u7378", - "447": "\u5229\u6b50\u8def", - "448": "\u8def\u5361\u5229\u5965", - "449": "\u602a\u6cb3\u99ac", - "450": "\u6cb3\u99ac\u7378", - "451": "\u7d2b\u5929\u880d", - "452": "\u9f8d\u738b\u880d", - "453": "\u4e0d\u826f\u86d9", - "454": "\u6bd2\u9ab7\u86d9", - "455": "\u5c16\u7259\u7c60", - "456": "\u87a2\u5149\u9b5a", - "457": "\u9713\u8679\u9b5a", - "458": "\u5c0f\u7403\u98db\u9b5a", - "459": "\u96ea\u7b20\u602a", - "460": "\u66b4\u96ea\u738b", - "461": "\u746a\u72c3\u62c9", - "462": "\u81ea\u7206\u78c1\u602a", - "463": "\u5927\u820c\u8214", - "464": "\u8d85\u9435\u66b4\u9f8d", - "465": "\u5de8\u8513\u85e4", - "466": "\u96fb\u64ca\u9b54\u7378", - "467": "\u9d28\u5634\u7130\u9f8d", - "468": "\u6ce2\u514b\u57fa\u65af", - "469": "\u6885\u5361\u967d\u746a", - "470": "\u8449\u4f0a\u8c9d", - "471": "\u51b0\u4f0a\u8c9d", - "472": "\u5929\u880d\u738b", - "473": "\u8c61\u7259\u8c6c", - "474": "\u7acb\u65b9\u7378Z", - "475": "\u827e\u8def\u96f7\u6735", - "476": "\u5927\u671d\u5317\u9f3b", - "477": "\u591c\u9ed1\u9b54\u4eba", - "478": "\u96ea\u5996\u5973", - "479": "\u6d1b\u6258\u59c6", - "480": "\u7531\u514b\u5e0c", - "481": "\u827e\u59c6\u5229\u591a", - "482": "\u4e9e\u514b\u8afe\u59c6", - "483": "\u5e1d\u7259\u76e7\u5361", - "484": "\u5e15\u8def\u5947\u72bd", - "485": "\u5e2d\u591a\u85cd\u6069", - "486": "\u96f7\u5409\u5947\u5361\u65af", - "487": "\u9a0e\u62c9\u5e1d\u7d0d", - "488": "\u514b\u96f7\u8272\u5229\u4e9e", - "489": "\u970f\u6b50\u7d0d", - "490": "\u746a\u7d0d\u970f", - "491": "\u9054\u514b\u840a\u4f0a", - "492": "\u6f54\u54aa", - "493": "\u963f\u723e\u5b99\u65af", - "494": "\u6bd4\u514b\u63d0\u5c3c", - "495": "\u85e4\u85e4\u86c7", - "496": "\u9752\u85e4\u86c7", - "497": "\u541b\u4e3b\u86c7", - "498": "\u6696\u6696\u8c6c", - "499": "\u7092\u7092\u8c6c", - "500": "\u708e\u6b66\u738b", - "501": "\u6c34\u6c34\u737a", - "502": "\u96d9\u5203\u4e38", - "503": "\u5927\u528d\u9b3c", - "504": "\u63a2\u63a2\u9f20", - "505": "\u6b65\u54e8\u9f20", - "506": "\u5c0f\u7d04\u514b", - "507": "\u54c8\u7d04\u514b", - "508": "\u9577\u6bdb\u72d7", - "509": "\u6252\u624b\u8c93", - "510": "\u9177\u8c79", - "511": "\u82b1\u6930\u7334", - "512": "\u82b1\u6930\u733f", - "513": "\u7206\u9999\u7334", - "514": "\u7206\u9999\u733f", - "515": "\u51b7\u6c34\u7334", - "516": "\u51b7\u6c34\u733f", - "517": "\u98df\u5922\u5922", - "518": "\u5922\u5922\u8755", - "519": "\u8c46\u8c46\u9d3f", - "520": "\u6ce2\u6ce2\u9d3f", - "521": "\u8f5f\u9686\u96c9\u96de", - "522": "\u6591\u6591\u99ac", - "523": "\u96f7\u96fb\u6591\u99ac", - "524": "\u77f3\u4e38\u5b50", - "525": "\u5730\u5e54\u5ca9", - "526": "\u9f90\u5ca9\u602a", - "527": "\u6efe\u6efe\u8759\u8760", - "528": "\u5fc3\u8759\u8760", - "529": "\u87ba\u91d8\u5730\u9f20", - "530": "\u9f8d\u982d\u5730\u9f20", - "531": "\u5dee\u4e0d\u591a\u5a03\u5a03", - "532": "\u642c\u904b\u5c0f\u5320", - "533": "\u9435\u9aa8\u571f\u4eba", - "534": "\u4fee\u7e55\u8001\u982d", - "535": "\u5713\u874c\u86aa", - "536": "\u85cd\u87fe\u870d", - "537": "\u87fe\u870d\u738b", - "538": "\u6295\u5c04\u9b3c", - "539": "\u6253\u64ca\u9b3c", - "540": "\u87f2\u5bf6\u5305", - "541": "\u5bf6\u5305\u7e6d", - "542": "\u4fdd\u6bcd\u87f2", - "543": "\u767e\u8db3\u8708\u86a3", - "544": "\u8eca\u8f2a\u6bec", - "545": "\u8708\u86a3\u738b", - "546": "\u6728\u68c9\u7403", - "547": "\u98a8\u5996\u7cbe", - "548": "\u767e\u5408\u6839\u5a03\u5a03", - "549": "\u88d9\u5152\u5c0f\u59d0", - "550": "\u52c7\u58eb\u9c78\u9b5a", - "551": "\u9ed1\u773c\u9c77", - "552": "\u6df7\u6df7\u9c77", - "553": "\u6d41\u6c13\u9c77", - "554": "\u706b\u7d05\u4e0d\u5012\u7fc1", - "555": "\u9054\u6469\u72d2\u72d2", - "556": "\u8857\u982d\u6c99\u9234", - "557": "\u77f3\u5c45\u87f9", - "558": "\u5ca9\u6bbf\u5c45\u87f9", - "559": "\u6ed1\u982d\u5c0f\u5b50", - "560": "\u982d\u5dfe\u6df7\u6df7", - "561": "\u8c61\u5fb5\u9ce5", - "562": "\u54ed\u54ed\u9762\u5177", - "563": "\u6b7b\u795e\u68fa", - "564": "\u539f\u84cb\u6d77\u9f9c", - "565": "\u808b\u9aa8\u6d77\u9f9c", - "566": "\u59cb\u7956\u5c0f\u9ce5", - "567": "\u59cb\u7956\u5927\u9ce5", - "568": "\u7834\u7834\u888b", - "569": "\u7070\u5875\u5c71", - "570": "\u7d22\u7f85\u4e9e", - "571": "\u7d22\u7f85\u4e9e\u514b", - "572": "\u6ce1\u6cab\u6817\u9f20", - "573": "\u5947\u8afe\u6817\u9f20", - "574": "\u54e5\u5fb7\u5bf6\u5bf6", - "575": "\u54e5\u5fb7\u5c0f\u7ae5", - "576": "\u54e5\u5fb7\u5c0f\u59d0", - "577": "\u55ae\u5375\u7d30\u80de\u7403", - "578": "\u96d9\u5375\u7d30\u80de\u7403", - "579": "\u4eba\u9020\u7d30\u80de\u5375", - "580": "\u9d28\u5bf6\u5bf6", - "581": "\u9996\u5e2d\u5929\u9d5d", - "582": "\u8ff7\u4f60\u51b0", - "583": "\u591a\u591a\u51b0", - "584": "\u96d9\u500d\u591a\u591a\u51b0", - "585": "\u56db\u5b63\u9e7f", - "586": "\u82bd\u5439\u9e7f", - "587": "\u5c0e\u96fb\u98db\u9f20", - "588": "\u84cb\u84cb\u87f2", - "589": "\u9a0e\u58eb\u8778\u725b", - "590": "\u7cbe\u9748\u7403\u83c7", - "591": "\u66b4\u9732\u83c7", - "592": "\u8f15\u98c4\u98c4", - "593": "\u80d6\u561f\u561f", - "594": "\u4fdd\u6bcd\u66fc\u6ce2", - "595": "\u96fb\u96fb\u87f2", - "596": "\u96fb\u8718\u86db", - "597": "\u7a2e\u5b50\u9435\u7403", - "598": "\u5805\u679c\u555e\u9234", - "599": "\u9f52\u8f2a\u5152", - "600": "\u9f52\u8f2a\u7d44", - "601": "\u9f52\u8f2a\u602a", - "602": "\u9ebb\u9ebb\u5c0f\u9b5a", - "603": "\u9ebb\u9ebb\u9c3b", - "604": "\u9ebb\u9ebb\u9c3b\u9b5a\u738b", - "605": "\u5c0f\u7070\u602a", - "606": "\u5927\u5b87\u602a", - "607": "\u71ed\u5149\u9748", - "608": "\u71c8\u706b\u5e7d\u9748", - "609": "\u6c34\u6676\u71c8\u706b\u9748", - "610": "\u7259\u7259", - "611": "\u65a7\u7259\u9f8d", - "612": "\u96d9\u65a7\u6230\u9f8d", - "613": "\u5674\u568f\u718a", - "614": "\u51cd\u539f\u718a", - "615": "\u5e7e\u4f55\u96ea\u82b1", - "616": "\u5c0f\u5634\u8778", - "617": "\u654f\u6377\u87f2", - "618": "\u6ce5\u5df4\u9b5a", - "619": "\u529f\u592b\u9f2c", - "620": "\u5e2b\u7236\u9f2c", - "621": "\u8d64\u9762\u9f8d", - "622": "\u6ce5\u5076\u5c0f\u4eba", - "623": "\u6ce5\u5076\u5de8\u4eba", - "624": "\u99d2\u5200\u5c0f\u5175", - "625": "\u5288\u65ac\u53f8\u4ee4", - "626": "\u7206\u7206\u982d\u6c34\u725b", - "627": "\u6bdb\u982d\u5c0f\u9df9", - "628": "\u52c7\u58eb\u9df9", - "629": "\u79bf\u9df9\u5c0f\u5b50", - "630": "\u79bf\u9df9\u5a1c", - "631": "\u98df\u87fb\u7210", - "632": "\u9435\u87fb", - "633": "\u55ae\u9996\u9f8d", - "634": "\u96d9\u982d\u9f8d", - "635": "\u4e09\u982d\u9f8d", - "636": "\u71c3\u71d2\u87f2", - "637": "\u706b\u795e\u87f2", - "638": "\u52fe\u5e15\u8def\u7fc1", - "639": "\u4ee3\u62c9\u57fa\u7fc1", - "640": "\u7562\u529b\u5409\u7fc1", - "641": "\u9f8d\u6372\u96f2", - "642": "\u96f7\u96fb\u96f2", - "643": "\u96f7\u5e0c\u62c9\u59c6", - "644": "\u6377\u514b\u7f85\u59c6", - "645": "\u571f\u5730\u96f2", - "646": "\u914b\u96f7\u59c6", - "647": "\u51f1\u8def\u8fea\u6b50", - "648": "\u7f8e\u6d1b\u8036\u5854", - "649": "\u84cb\u8afe\u8cfd\u514b\u7279", - "650": "\u54c8\u529b\u99ac\u9f8d", - "651": "\u80a5\u4ed4\u54c8\u529b", - "652": "\u5e03\u91cc\u5361\u9686", - "653": "\u706b\u72d0\u72f8", - "654": "\u9577\u5c3e\u706b\u72d0", - "655": "\u5996\u706b\u7d05\u72d0", - "656": "\u5471\u5471\u6ce1\u86d9", - "657": "\u5471\u982d\u86d9", - "658": "\u7532\u8cc0\u5fcd\u86d9", - "659": "\u6316\u6316\u5154", - "660": "\u6509\u5730\u5154", - "661": "\u5c0f\u7bad\u96c0", - "662": "\u706b\u7bad\u96c0", - "663": "\u70c8\u7bad\u9df9", - "664": "\u7c89\u86f9", - "665": "\u7c89\u8776\u86f9", - "666": "\u78a7\u7c89\u8776", - "667": "\u5c0f\u7345\u7345", - "668": "\u706b\u708e\u7345", - "669": "\u82b1\u84d3\u84d3", - "670": "\u82b1\u8449\u8482", - "671": "\u82b1\u6f54\u592b\u4eba", - "672": "\u54a9\u54a9\u7f8a", - "673": "\u6307\u8def\u7f8a", - "674": "\u9811\u76ae\u718a\u8c93", - "675": "\u6d41\u6c13\u718a\u8c93", - "676": "\u591a\u9e97\u7c73\u4e9e", - "677": "\u5999\u55b5", - "678": "\u8d85\u80fd\u5999\u55b5", - "679": "\u7368\u528d\u9798", - "680": "\u96d9\u528d\u9798", - "681": "\u5805\u76fe\u528d\u602a", - "682": "\u7c89\u9999\u9999", - "683": "\u82b3\u9999\u7cbe", - "684": "\u7dbf\u7dbf\u6ce1\u8299", - "685": "\u80d6\u751c\u59ae", - "686": "\u6beb\u5587\u9b77", - "687": "\u70cf\u8cca\u738b", - "688": "\u9f9c\u8173\u8173", - "689": "\u9f9c\u8db3\u5de8\u93a7", - "690": "\u5783\u5783\u85fb", - "691": "\u6bd2\u62c9\u871c\u59ae", - "692": "\u9435\u81c2\u69cd\u8766", - "693": "\u92fc\u7832\u81c2\u8766", - "694": "\u767c\u96fb\u8725", - "695": "\u96fb\u5098\u67e5\u7279", - "696": "\u66b4\u9f8d\u4ed4", - "697": "\u602a\u984e\u9f8d", - "698": "\u51b0\u96ea\u9f8d", - "699": "\u51b0\u96ea\u5de8\u9f8d", - "700": "\u4ed9\u5b50\u4f0a\u8c9d", - "701": "\u6230\u9b25\u98db\u9ce5", - "702": "\u549a\u549a\u9f20", - "703": "\u5c0f\u788e\u947d", - "704": "\u9ecf\u9ecf\u5bf6", - "705": "\u9ecf\u7f8e\u5152", - "706": "\u9ecf\u7f8e\u9f8d", - "707": "\u9396\u5708\u5152", - "708": "\u5c0f\u6728\u9748", - "709": "\u673d\u6728\u5996", - "710": "\u5357\u74dc\u7cbe", - "711": "\u5357\u74dc\u602a\u4eba", - "712": "\u51b0\u5bf6", - "713": "\u51b0\u5ca9\u602a", - "714": "\u55e1\u8760", - "715": "\u97f3\u6ce2\u98db\u9f8d", - "716": "\u54f2\u723e\u5c3c\u4e9e\u65af", - "717": "\u4f0a\u79d8\u9b6f\u5854\u8def", - "718": "\u57fa\u683c\u723e\u5fb7", - "719": "\u8482\u5b89\u5e0c", - "720": "\u80e1\u5e15", + "001": "\u5947\u7570\u7a2e\u5b50", + "002": "\u5947\u7570\u8349", + "003": "\u5947\u7570\u82b1", + "004": "\u5c0f\u706b\u9f8d", + "005": "\u706b\u6050\u9f8d", + "006": "\u5674\u706b\u9f8d", + "007": "\u8eca\u5398\u9f9c", + "008": "\u5361\u7f8e\u9f9c", + "009": "\u6c34\u7bad\u9f9c", + "010": "\u7da0\u6bdb\u87f2", + "011": "\u9435\u7532\u87f2", + "012": "\u5df4\u4ed6\u8776", + "013": "\u7368\u89d2\u87f2", + "014": "\u9435\u6bbc\u86f9", + "015": "\u5927\u91dd\u8702", + "016": "\u6ce2\u6ce2", + "017": "\u6bd4\u6bd4\u9ce5", + "018": "\u5927\u6bd4\u9ce5", + "019": "\u5c0f\u54e5\u9054", + "020": "\u54e5\u9054", + "021": "\u9b3c\u96c0", + "022": "\u9b54\u96c0", + "023": "\u963f\u67cf\u86c7", + "024": "\u963f\u67cf\u602a", + "025": "\u6bd4\u5361\u8d85", + "026": "\u96f7\u8d85", + "027": "\u7a7f\u5c71\u9f20", + "028": "\u7a7f\u5c71\u738b", + "029": "\u5c3c\u7f8e\u862d", + "030": "\u5c3c\u7f8e\u863f", + "031": "\u5c3c\u7f8e\u540e", + "032": "\u5c3c\u591a\u90ce", + "033": "\u5c3c\u591a\u5229", + "034": "\u5c3c\u591a\u738b", + "035": "\u76ae\u76ae", + "036": "\u76ae\u53ef\u65af", + "037": "\u516d\u5c3e", + "038": "\u4e5d\u5c3e", + "039": "\u6ce2\u6ce2\u7403", + "040": "\u80a5\u6ce2\u7403", + "041": "\u6ce2\u97f3\u8760", + "042": "\u5927\u53e3\u8760", + "043": "\u884c\u8def\u8349", + "044": "\u602a\u5473\u82b1", + "045": "\u9738\u738b\u82b1", + "046": "\u8611\u83c7\u87f2", + "047": "\u5de8\u83c7\u87f2", + "048": "\u6bdb\u6bdb\u87f2", + "049": "\u9b54\u9b6f\u98a8", + "050": "\u5730\u9f20", + "051": "\u4e09\u982d\u5730\u9f20", + "052": "\u55b5\u55b5\u602a", + "053": "\u9ad8\u7ac7\u8c93", + "054": "\u50bb\u9d28", + "055": "\u9ad8\u8d85\u9d28", + "056": "\u7334\u602a", + "057": "\u706b\u7206\u7334", + "058": "\u8b77\u4e3b\u72ac", + "059": "\u5949\u795e\u72ac", + "060": "\u868a\u9999\u874c\u86aa", + "061": "\u868a\u9999\u86d9", + "062": "\u5927\u529b\u86d9", + "063": "\u5361\u65af", + "064": "\u5c24\u57fa\u7d0d", + "065": "\u5bcc\u8fea", + "066": "\u9435\u8155", + "067": "\u5927\u529b", + "068": "\u602a\u529b", + "069": "\u5587\u53ed\u82bd", + "070": "\u53e3\u5446\u82b1", + "071": "\u5927\u98df\u82b1", + "072": "\u5927\u773c\u6c34\u6bcd", + "073": "\u591a\u8173\u6c34\u6bcd", + "074": "\u5c0f\u62f3\u77f3", + "075": "\u6efe\u52d5\u77f3", + "076": "\u6efe\u52d5\u5ca9", + "077": "\u5c0f\u706b\u99ac", + "078": "\u70c8\u7130\u99ac", + "079": "\u5c0f\u5446\u7378", + "080": "\u5927\u5446\u7378", + "081": "\u5c0f\u78c1\u602a", + "082": "\u4e09\u5408\u4e00\u78c1\u602a", + "083": "\u706b\u8525\u9d28", + "084": "\u591a\u591a", + "085": "\u591a\u591a\u5229", + "086": "\u5c0f\u6d77\u7345", + "087": "\u767d\u6d77\u7345", + "088": "\u721b\u6ce5\u602a", + "089": "\u721b\u6ce5\u7378", + "090": "\u8c9d\u6bbc\u602a", + "091": "\u9435\u7532\u8c9d", + "092": "\u9b3c\u65af", + "093": "\u9b3c\u65af\u901a", + "094": "\u803f\u9b3c", + "095": "\u5927\u5ca9\u86c7", + "096": "\u98df\u5922\u7378", + "097": "\u50ac\u7720\u7378", + "098": "\u5927\u9257\u87f9", + "099": "\u5de8\u9257\u87f9", + "100": "\u9739\u9742\u86cb", + "101": "\u96f7\u9706\u86cb", + "102": "\u86cb\u86cb", + "103": "\u6930\u6a39\u7378", + "104": "\u5361\u62c9\u5361\u62c9", + "105": "\u683c\u62c9\u683c\u62c9", + "106": "\u6c99\u53e4\u62c9", + "107": "\u6bd4\u83ef\u62c9", + "108": "\u5927\u820c\u982d", + "109": "\u6bd2\u6c23\u4e38", + "110": "\u6bd2\u6c23\u96d9\u5b50", + "111": "\u9435\u7532\u7280\u725b", + "112": "\u9435\u7532\u66b4\u9f8d", + "113": "\u5409\u5229\u86cb", + "114": "\u9577\u7c50\u602a", + "115": "\u888b\u7378", + "116": "\u5674\u58a8\u6d77\u99ac", + "117": "\u98db\u523a\u6d77\u99ac", + "118": "\u7368\u89d2\u91d1\u9b5a", + "119": "\u91d1\u9b5a\u738b", + "120": "\u6d77\u661f\u661f", + "121": "\u5bf6\u77f3\u6d77\u661f", + "122": "\u5438\u76e4\u5c0f\u4e11", + "123": "\u98db\u5929\u87b3\u8782", + "124": "\u7d05\u5507\u5a03", + "125": "\u96fb\u64ca\u7378", + "126": "\u9d28\u5634\u706b\u9f8d", + "127": "\u9257\u5200\u7532\u87f2", + "128": "\u5927\u96bb\u725b", + "129": "\u9bc9\u9b5a\u738b", + "130": "\u9bc9\u9b5a\u9f8d", + "131": "\u80cc\u80cc\u9f8d", + "132": "\u767e\u8b8a\u602a", + "133": "\u4f0a\u8c9d", + "134": "\u6c34\u4f0a\u8c9d", + "135": "\u96f7\u4f0a\u8c9d", + "136": "\u706b\u4f0a\u8c9d", + "137": "\u7acb\u65b9\u7378", + "138": "\u83ca\u77f3\u7378", + "139": "\u591a\u523a\u83ca\u77f3\u7378", + "140": "\u842c\u5e74\u87f2", + "141": "\u942e\u5200\u87f2", + "142": "\u5316\u77f3\u98db\u9f8d", + "143": "\u5361\u6bd4\u7378", + "144": "\u6025\u51cd\u9ce5", + "145": "\u96f7\u9ce5", + "146": "\u706b\u9ce5", + "147": "\u8ff7\u4f60\u9f8d", + "148": "\u54c8\u53e4\u9f8d", + "149": "\u555f\u66b4\u9f8d", + "150": "\u8d85\u5922\u5922", + "151": "\u5922\u5922", + "152": "\u83ca\u8349\u8449", + "153": "\u6708\u6842\u8449", + "154": "\u5927\u83ca\u82b1", + "155": "\u706b\u7403\u9f20", + "156": "\u706b\u5ca9\u9f20", + "157": "\u706b\u66b4\u7378", + "158": "\u5c0f\u92f8\u9c77", + "159": "\u85cd\u9c77", + "160": "\u5927\u529b\u9c77", + "161": "\u5c3e\u7acb", + "162": "\u5927\u5c3e\u7acb", + "163": "\u5495\u5495", + "164": "\u8c93\u982d\u591c\u9df9", + "165": "\u82ad\u74e2\u87f2", + "166": "\u5b89\u74e2\u87f2", + "167": "\u7dda\u7403", + "168": "\u963f\u5229\u591a\u65af", + "169": "\u53c9\u5b57\u8760", + "170": "\u71c8\u7c60\u9b5a", + "171": "\u96fb\u71c8\u602a", + "172": "\u6bd4\u8d85", + "173": "\u76ae\u5bf6\u5bf6", + "174": "\u5c0f\u6ce2\u7403", + "175": "\u5c0f\u523a\u86cb", + "176": "\u6ce2\u514b\u57fa\u53e4", + "177": "\u5929\u7136\u96c0", + "178": "\u5929\u7136\u9ce5", + "179": "\u54a9\u5229\u7f8a", + "180": "\u7dbf\u7dbf", + "181": "\u96fb\u9f8d", + "182": "\u7f8e\u9e97\u82b1", + "183": "\u746a\u5229\u9732", + "184": "\u746a\u5229\u9732\u9e97", + "185": "\u80e1\u8aaa\u6a39", + "186": "\u725b\u86d9\u541b", + "187": "\u6bfd\u5b50\u8349", + "188": "\u6bfd\u5b50\u82b1", + "189": "\u6bfd\u5b50\u7dbf", + "190": "\u9577\u5c3e\u602a\u624b", + "191": "\u5411\u65e5\u7a2e\u5b50", + "192": "\u5411\u65e5\u82b1\u602a", + "193": "\u967d\u967d\u746a", + "194": "\u70cf\u6ce2", + "195": "\u6cbc\u738b", + "196": "\u592a\u967d\u4f0a\u8c9d", + "197": "\u6708\u4f0a\u8c9d", + "198": "\u9ed1\u6697\u9d09", + "199": "\u6cb3\u99ac\u738b", + "200": "\u5922\u5996", + "201": "\u672a\u77e5\u5716\u9a30", + "202": "\u679c\u7136\u7fc1", + "203": "\u9e92\u9e9f\u5947", + "204": "\u699b\u679c\u7403", + "205": "\u4f5b\u70c8\u8a17\u65af", + "206": "\u571f\u9f8d\u5f1f\u5f1f", + "207": "\u5929\u880d", + "208": "\u5927\u92fc\u86c7", + "209": "\u5e03\u9b6f", + "210": "\u5e03\u9b6f\u7687", + "211": "\u5343\u91dd\u9b5a", + "212": "\u5de8\u9257\u87b3\u8782", + "213": "\u58fa\u58fa", + "214": "\u8d6b\u62c9\u514b\u7f85\u65af", + "215": "\u72c3\u62c9", + "216": "\u718a\u5bf6\u5bf6", + "217": "\u5708\u5708\u718a", + "218": "\u7194\u5ca9\u87f2", + "219": "\u7194\u5ca9\u8778\u725b", + "220": "\u5c0f\u5c71\u8c6c", + "221": "\u9577\u6bdb\u8c6c", + "222": "\u592a\u967d\u73ca\u745a", + "223": "\u9435\u70ae\u9b5a", + "224": "\u7ae0\u9b5a\u6876", + "225": "\u4fe1\u4f7f\u9ce5", + "226": "\u5de8\u7fc5\u98db\u9b5a", + "227": "\u76d4\u7532\u9ce5", + "228": "\u6234\u9b6f\u6bd4", + "229": "\u9ed1\u9b6f\u52a0", + "230": "\u523a\u9f8d\u738b", + "231": "\u5c0f\u5c0f\u8c61", + "232": "\u51ac\u51e1", + "233": "\u7acb\u65b9\u7378\uff12", + "234": "\u9a5a\u89d2\u9e7f", + "235": "\u5716\u5716\u72ac", + "236": "\u5df4\u723e\u90ce", + "237": "\u67ef\u6ce2\u6717", + "238": "\u8ff7\u5507\u5a03", + "239": "\u96fb\u64ca\u602a", + "240": "\u5c0f\u9d28\u5634\u9f8d", + "241": "\u5927\u5976\u7f50", + "242": "\u5e78\u798f\u86cb", + "243": "\u96f7\u516c", + "244": "\u708e\u5e1d", + "245": "\u6c34\u541b", + "246": "\u7531\u57fa\u62c9", + "247": "\u6c99\u57fa\u62c9", + "248": "\u73ed\u5409\u62c9", + "249": "\u5229\u57fa\u4e9e", + "250": "\u9cf3\u51f0", + "251": "\u96ea\u62c9\u6bd4", + "252": "\u6728\u5b88\u5bae", + "253": "\u68ee\u6797\u8725\u8734", + "254": "\u8725\u8734\u738b", + "255": "\u706b\u7a1a\u96de", + "256": "\u529b\u58ef\u96de", + "257": "\u706b\u7130\u96de", + "258": "\u6c34\u8e8d\u9b5a", + "259": "\u6cbc\u8e8d\u9b5a", + "260": "\u5de8\u6cbc\u602a", + "261": "\u571f\u72fc\u72ac", + "262": "\u5927\u72fc\u72ac", + "263": "\u86c7\u7d0b\u718a", + "264": "\u76f4\u885d\u718a", + "265": "\u523a\u5c3e\u87f2", + "266": "\u7532\u6bbc\u86f9", + "267": "\u72e9\u7375\u9cf3\u8776", + "268": "\u76fe\u7532\u7e6d", + "269": "\u6bd2\u7c89\u8776", + "270": "\u84ee\u8449\u7ae5\u5b50", + "271": "\u84ee\u5e3d\u5c0f\u7ae5", + "272": "\u6a02\u5929\u6cb3\u7ae5", + "273": "\u6a61\u5be6\u679c", + "274": "\u9577\u9f3b\u8449", + "275": "\u72e1\u733e\u5929\u72d7", + "276": "\u50b2\u9aa8\u71d5", + "277": "\u5927\u738b\u71d5", + "278": "\u9577\u7fc5\u9dd7", + "279": "\u5927\u5634\u9dd7", + "280": "\u62c9\u9b6f\u62c9\u7d72", + "281": "\u5947\u9b6f\u8389\u5b89", + "282": "\u6c99\u5948\u6735", + "283": "\u6e9c\u6e9c\u7cd6\u7403", + "284": "\u96e8\u7fc5\u86fe", + "285": "\u8611\u8611\u83c7", + "286": "\u6597\u7b20\u83c7", + "287": "\u61f6\u4eba\u7fc1", + "288": "\u904e\u52d5\u733f", + "289": "\u8acb\u5047\u738b", + "290": "\u571f\u5c45\u5fcd\u58eb", + "291": "\u9435\u9762\u5fcd\u8005", + "292": "\u812b\u6bbc\u5fcd\u8005", + "293": "\u5495\u599e\u599e", + "294": "\u543c\u7206\u5f48", + "295": "\u7206\u97f3\u602a", + "296": "\u5e55\u4e0b\u529b\u58eb", + "297": "\u8d85\u529b\u738b", + "298": "\u9732\u529b\u9e97", + "299": "\u671d\u5317\u9f3b", + "300": "\u5411\u5c3e\u55b5", + "301": "\u512a\u96c5\u8c93", + "302": "\u52fe\u9b42\u773c", + "303": "\u5927\u5634\u5a03", + "304": "\u53ef\u53ef\u591a\u62c9", + "305": "\u53ef\u591a\u62c9", + "306": "\u6ce2\u58eb\u53ef\u591a\u62c9", + "307": "\u746a\u6c99\u90a3", + "308": "\u6070\u96f7\u59c6", + "309": "\u843d\u96f7\u7378", + "310": "\u96f7\u96fb\u7378", + "311": "\u6b63\u96fb\u62cd\u62cd", + "312": "\u8ca0\u96fb\u62cd\u62cd", + "313": "\u96fb\u87a2\u87f2", + "314": "\u751c\u751c\u87a2", + "315": "\u6bd2\u8594\u8587", + "316": "\u6eb6\u98df\u7378", + "317": "\u541e\u98df\u7378", + "318": "\u5229\u7259\u9b5a", + "319": "\u5de8\u7259\u9bca", + "320": "\u543c\u543c\u9be8", + "321": "\u543c\u9be8\u738b", + "322": "\u5446\u706b\u99dd", + "323": "\u5674\u706b\u99dd", + "324": "\u7164\u70ad\u9f9c", + "325": "\u8df3\u8df3\u8c6c", + "326": "\u5657\u5657\u8c6c", + "327": "\u6643\u6643\u6591", + "328": "\u5927\u984e\u87fb", + "329": "\u8d85\u97f3\u6ce2\u5e7c\u87f2", + "330": "\u6c99\u6f20\u873b\u8713", + "331": "\u6c99\u6f20\u5948\u4e9e", + "332": "\u5922\u6b4c\u5948\u4e9e", + "333": "\u9752\u7dbf\u9ce5", + "334": "\u4e03\u5915\u9752\u9ce5", + "335": "\u8c93\u9f2c\u65ac", + "336": "\u98ef\u5319\u86c7", + "337": "\u6708\u77f3", + "338": "\u592a\u967d\u5ca9", + "339": "\u6ce5\u6ce5\u9c0d", + "340": "\u9bf0\u9b5a\u738b", + "341": "\u9f8d\u8766\u5c0f\u5175", + "342": "\u9435\u87c4\u9f8d\u8766", + "343": "\u5929\u79e4\u5076", + "344": "\u5ff5\u529b\u571f\u5076", + "345": "\u89f8\u624b\u767e\u5408", + "346": "\u6416\u7c43\u767e\u5408", + "347": "\u592a\u53e4\u7fbd\u87f2", + "348": "\u592a\u53e4\u76d4\u7532", + "349": "\u7b28\u7b28\u9b5a", + "350": "\u7f8e\u7d0d\u65af", + "351": "\u6f02\u6d6e\u6ce1\u6ce1", + "352": "\u8b8a\u96b1\u9f8d", + "353": "\u6028\u5f71\u5a03\u5a03", + "354": "\u8a5b\u5492\u5a03\u5a03", + "355": "\u591c\u9ab7\u9acf", + "356": "\u591c\u5de8\u4eba", + "357": "\u71b1\u5e36\u9f8d", + "358": "\u98a8\u9234\u9234", + "359": "\u963f\u52c3\u68ad\u9b6f", + "360": "\u679c\u7136\u4ed4", + "361": "\u96ea\u7ae5\u5b50", + "362": "\u51b0\u9b3c\u8b77", + "363": "\u6d77\u8c79\u7403", + "364": "\u6d77\u9b54\u7345", + "365": "\u5e1d\u7259\u6d77\u7345", + "366": "\u73cd\u73e0\u8c9d", + "367": "\u7375\u6591\u9b5a", + "368": "\u6afb\u82b1\u9b5a", + "369": "\u53e4\u7a7a\u68d8\u9b5a", + "370": "\u611b\u5fc3\u9b5a", + "371": "\u5bf6\u8c9d\u9f8d", + "372": "\u7532\u6bbc\u9f8d", + "373": "\u66b4\u8811\u8788", + "374": "\u9435\u555e\u9234", + "375": "\u91d1\u5c6c\u602a", + "376": "\u5de8\u91d1\u602a", + "377": "\u96f7\u5409\u6d1b\u514b", + "378": "\u96f7\u5409\u827e\u65af", + "379": "\u96f7\u5409\u65af\u5947\u9b6f", + "380": "\u62c9\u5e1d\u4e9e\u65af", + "381": "\u62c9\u5e1d\u6b50\u65af", + "382": "\u84cb\u6b50\u5361", + "383": "\u56fa\u62c9\u591a", + "384": "\u70c8\u7a7a\u5750", + "385": "\u57fa\u62c9\u7948", + "386": "\u4ee3\u6b50\u5947\u5e0c\u65af", + "387": "\u8349\u82d7\u9f9c", + "388": "\u6a39\u6797\u9f9c", + "389": "\u571f\u53f0\u9f9c", + "390": "\u5c0f\u706b\u7130\u7334", + "391": "\u731b\u706b\u7334", + "392": "\u70c8\u7130\u7334", + "393": "\u6ce2\u52a0\u66fc", + "394": "\u6ce2\u7687\u5b50", + "395": "\u5e1d\u7687\u62ff\u6ce2", + "396": "\u59c6\u514b\u5152", + "397": "\u59c6\u514b\u9ce5", + "398": "\u59c6\u514b\u9df9", + "399": "\u5927\u7259\u72f8", + "400": "\u5927\u5c3e\u72f8", + "401": "\u5713\u6cd5\u5e2b", + "402": "\u97f3\u7bb1\u87c0", + "403": "\u5c0f\u8c93\u602a", + "404": "\u52d2\u514b\u8c93", + "405": "\u502b\u7434\u8c93", + "406": "\u542b\u7f9e\u82de", + "407": "\u7f85\u7d72\u96f7\u6735", + "408": "\u982d\u84cb\u9f8d", + "409": "\u6230\u69cc\u9f8d", + "410": "\u76fe\u7532\u9f8d", + "411": "\u8b77\u57ce\u9f8d", + "412": "\u7d50\u8349\u5152", + "413": "\u7d50\u8349\u8cb4\u5a66", + "414": "\u7d33\u58eb\u86fe", + "415": "\u4e09\u871c\u8702", + "416": "\u8702\u540e", + "417": "\u5e15\u5947\u5229\u8332", + "418": "\u6cf3\u6c23\u9f2c", + "419": "\u6d6e\u6f5b\u9f2c", + "420": "\u6afb\u82b1\u5bf6", + "421": "\u6afb\u82b1\u5152", + "422": "\u7121\u6bbc\u6d77\u725b", + "423": "\u6d77\u725b\u7378", + "424": "\u96d9\u5c3e\u602a\u624b", + "425": "\u98c4\u98c4\u7403", + "426": "\u9644\u548c\u6c23\u7403", + "427": "\u6372\u6372\u8033", + "428": "\u9577\u8033\u5154", + "429": "\u5922\u5996\u9b54", + "430": "\u70cf\u9d09\u982d\u982d", + "431": "\u9b45\u529b\u55b5", + "432": "\u6771\u65bd\u55b5", + "433": "\u9234\u5679\u97ff", + "434": "\u81ed\u9f2c\u5657", + "435": "\u5766\u514b\u81ed\u9f2c", + "436": "\u9285\u93e1\u602a", + "437": "\u9752\u9285\u9418", + "438": "\u611b\u54ed\u6a39", + "439": "\u9b54\u5c3c\u5c3c", + "440": "\u597d\u904b\u86cb", + "441": "\u8052\u566a\u9ce5", + "442": "\u82b1\u5ca9\u602a", + "443": "\u5713\u9678\u9bca", + "444": "\u5c16\u7259\u9678\u9bca", + "445": "\u70c8\u54ac\u9678\u9bca", + "446": "\u5c0f\u5361\u6bd4\u7378", + "447": "\u5229\u6b50\u8def", + "448": "\u8def\u5361\u5229\u5965", + "449": "\u602a\u6cb3\u99ac", + "450": "\u6cb3\u99ac\u7378", + "451": "\u7d2b\u5929\u880d", + "452": "\u9f8d\u738b\u880d", + "453": "\u4e0d\u826f\u86d9", + "454": "\u6bd2\u9ab7\u86d9", + "455": "\u5c16\u7259\u7c60", + "456": "\u87a2\u5149\u9b5a", + "457": "\u9713\u8679\u9b5a", + "458": "\u5c0f\u7403\u98db\u9b5a", + "459": "\u96ea\u7b20\u602a", + "460": "\u66b4\u96ea\u738b", + "461": "\u746a\u72c3\u62c9", + "462": "\u81ea\u7206\u78c1\u602a", + "463": "\u5927\u820c\u8214", + "464": "\u8d85\u9435\u66b4\u9f8d", + "465": "\u5de8\u8513\u85e4", + "466": "\u96fb\u64ca\u9b54\u7378", + "467": "\u9d28\u5634\u7130\u9f8d", + "468": "\u6ce2\u514b\u57fa\u65af", + "469": "\u6885\u5361\u967d\u746a", + "470": "\u8449\u4f0a\u8c9d", + "471": "\u51b0\u4f0a\u8c9d", + "472": "\u5929\u880d\u738b", + "473": "\u8c61\u7259\u8c6c", + "474": "\u7acb\u65b9\u7378Z", + "475": "\u827e\u8def\u96f7\u6735", + "476": "\u5927\u671d\u5317\u9f3b", + "477": "\u591c\u9ed1\u9b54\u4eba", + "478": "\u96ea\u5996\u5973", + "479": "\u6d1b\u6258\u59c6", + "480": "\u7531\u514b\u5e0c", + "481": "\u827e\u59c6\u5229\u591a", + "482": "\u4e9e\u514b\u8afe\u59c6", + "483": "\u5e1d\u7259\u76e7\u5361", + "484": "\u5e15\u8def\u5947\u72bd", + "485": "\u5e2d\u591a\u85cd\u6069", + "486": "\u96f7\u5409\u5947\u5361\u65af", + "487": "\u9a0e\u62c9\u5e1d\u7d0d", + "488": "\u514b\u96f7\u8272\u5229\u4e9e", + "489": "\u970f\u6b50\u7d0d", + "490": "\u746a\u7d0d\u970f", + "491": "\u9054\u514b\u840a\u4f0a", + "492": "\u6f54\u54aa", + "493": "\u963f\u723e\u5b99\u65af", + "494": "\u6bd4\u514b\u63d0\u5c3c", + "495": "\u85e4\u85e4\u86c7", + "496": "\u9752\u85e4\u86c7", + "497": "\u541b\u4e3b\u86c7", + "498": "\u6696\u6696\u8c6c", + "499": "\u7092\u7092\u8c6c", + "500": "\u708e\u6b66\u738b", + "501": "\u6c34\u6c34\u737a", + "502": "\u96d9\u5203\u4e38", + "503": "\u5927\u528d\u9b3c", + "504": "\u63a2\u63a2\u9f20", + "505": "\u6b65\u54e8\u9f20", + "506": "\u5c0f\u7d04\u514b", + "507": "\u54c8\u7d04\u514b", + "508": "\u9577\u6bdb\u72d7", + "509": "\u6252\u624b\u8c93", + "510": "\u9177\u8c79", + "511": "\u82b1\u6930\u7334", + "512": "\u82b1\u6930\u733f", + "513": "\u7206\u9999\u7334", + "514": "\u7206\u9999\u733f", + "515": "\u51b7\u6c34\u7334", + "516": "\u51b7\u6c34\u733f", + "517": "\u98df\u5922\u5922", + "518": "\u5922\u5922\u8755", + "519": "\u8c46\u8c46\u9d3f", + "520": "\u6ce2\u6ce2\u9d3f", + "521": "\u8f5f\u9686\u96c9\u96de", + "522": "\u6591\u6591\u99ac", + "523": "\u96f7\u96fb\u6591\u99ac", + "524": "\u77f3\u4e38\u5b50", + "525": "\u5730\u5e54\u5ca9", + "526": "\u9f90\u5ca9\u602a", + "527": "\u6efe\u6efe\u8759\u8760", + "528": "\u5fc3\u8759\u8760", + "529": "\u87ba\u91d8\u5730\u9f20", + "530": "\u9f8d\u982d\u5730\u9f20", + "531": "\u5dee\u4e0d\u591a\u5a03\u5a03", + "532": "\u642c\u904b\u5c0f\u5320", + "533": "\u9435\u9aa8\u571f\u4eba", + "534": "\u4fee\u7e55\u8001\u982d", + "535": "\u5713\u874c\u86aa", + "536": "\u85cd\u87fe\u870d", + "537": "\u87fe\u870d\u738b", + "538": "\u6295\u5c04\u9b3c", + "539": "\u6253\u64ca\u9b3c", + "540": "\u87f2\u5bf6\u5305", + "541": "\u5bf6\u5305\u7e6d", + "542": "\u4fdd\u6bcd\u87f2", + "543": "\u767e\u8db3\u8708\u86a3", + "544": "\u8eca\u8f2a\u6bec", + "545": "\u8708\u86a3\u738b", + "546": "\u6728\u68c9\u7403", + "547": "\u98a8\u5996\u7cbe", + "548": "\u767e\u5408\u6839\u5a03\u5a03", + "549": "\u88d9\u5152\u5c0f\u59d0", + "550": "\u52c7\u58eb\u9c78\u9b5a", + "551": "\u9ed1\u773c\u9c77", + "552": "\u6df7\u6df7\u9c77", + "553": "\u6d41\u6c13\u9c77", + "554": "\u706b\u7d05\u4e0d\u5012\u7fc1", + "555": "\u9054\u6469\u72d2\u72d2", + "556": "\u8857\u982d\u6c99\u9234", + "557": "\u77f3\u5c45\u87f9", + "558": "\u5ca9\u6bbf\u5c45\u87f9", + "559": "\u6ed1\u982d\u5c0f\u5b50", + "560": "\u982d\u5dfe\u6df7\u6df7", + "561": "\u8c61\u5fb5\u9ce5", + "562": "\u54ed\u54ed\u9762\u5177", + "563": "\u6b7b\u795e\u68fa", + "564": "\u539f\u84cb\u6d77\u9f9c", + "565": "\u808b\u9aa8\u6d77\u9f9c", + "566": "\u59cb\u7956\u5c0f\u9ce5", + "567": "\u59cb\u7956\u5927\u9ce5", + "568": "\u7834\u7834\u888b", + "569": "\u7070\u5875\u5c71", + "570": "\u7d22\u7f85\u4e9e", + "571": "\u7d22\u7f85\u4e9e\u514b", + "572": "\u6ce1\u6cab\u6817\u9f20", + "573": "\u5947\u8afe\u6817\u9f20", + "574": "\u54e5\u5fb7\u5bf6\u5bf6", + "575": "\u54e5\u5fb7\u5c0f\u7ae5", + "576": "\u54e5\u5fb7\u5c0f\u59d0", + "577": "\u55ae\u5375\u7d30\u80de\u7403", + "578": "\u96d9\u5375\u7d30\u80de\u7403", + "579": "\u4eba\u9020\u7d30\u80de\u5375", + "580": "\u9d28\u5bf6\u5bf6", + "581": "\u9996\u5e2d\u5929\u9d5d", + "582": "\u8ff7\u4f60\u51b0", + "583": "\u591a\u591a\u51b0", + "584": "\u96d9\u500d\u591a\u591a\u51b0", + "585": "\u56db\u5b63\u9e7f", + "586": "\u82bd\u5439\u9e7f", + "587": "\u5c0e\u96fb\u98db\u9f20", + "588": "\u84cb\u84cb\u87f2", + "589": "\u9a0e\u58eb\u8778\u725b", + "590": "\u7cbe\u9748\u7403\u83c7", + "591": "\u66b4\u9732\u83c7", + "592": "\u8f15\u98c4\u98c4", + "593": "\u80d6\u561f\u561f", + "594": "\u4fdd\u6bcd\u66fc\u6ce2", + "595": "\u96fb\u96fb\u87f2", + "596": "\u96fb\u8718\u86db", + "597": "\u7a2e\u5b50\u9435\u7403", + "598": "\u5805\u679c\u555e\u9234", + "599": "\u9f52\u8f2a\u5152", + "600": "\u9f52\u8f2a\u7d44", + "601": "\u9f52\u8f2a\u602a", + "602": "\u9ebb\u9ebb\u5c0f\u9b5a", + "603": "\u9ebb\u9ebb\u9c3b", + "604": "\u9ebb\u9ebb\u9c3b\u9b5a\u738b", + "605": "\u5c0f\u7070\u602a", + "606": "\u5927\u5b87\u602a", + "607": "\u71ed\u5149\u9748", + "608": "\u71c8\u706b\u5e7d\u9748", + "609": "\u6c34\u6676\u71c8\u706b\u9748", + "610": "\u7259\u7259", + "611": "\u65a7\u7259\u9f8d", + "612": "\u96d9\u65a7\u6230\u9f8d", + "613": "\u5674\u568f\u718a", + "614": "\u51cd\u539f\u718a", + "615": "\u5e7e\u4f55\u96ea\u82b1", + "616": "\u5c0f\u5634\u8778", + "617": "\u654f\u6377\u87f2", + "618": "\u6ce5\u5df4\u9b5a", + "619": "\u529f\u592b\u9f2c", + "620": "\u5e2b\u7236\u9f2c", + "621": "\u8d64\u9762\u9f8d", + "622": "\u6ce5\u5076\u5c0f\u4eba", + "623": "\u6ce5\u5076\u5de8\u4eba", + "624": "\u99d2\u5200\u5c0f\u5175", + "625": "\u5288\u65ac\u53f8\u4ee4", + "626": "\u7206\u7206\u982d\u6c34\u725b", + "627": "\u6bdb\u982d\u5c0f\u9df9", + "628": "\u52c7\u58eb\u9df9", + "629": "\u79bf\u9df9\u5c0f\u5b50", + "630": "\u79bf\u9df9\u5a1c", + "631": "\u98df\u87fb\u7210", + "632": "\u9435\u87fb", + "633": "\u55ae\u9996\u9f8d", + "634": "\u96d9\u982d\u9f8d", + "635": "\u4e09\u982d\u9f8d", + "636": "\u71c3\u71d2\u87f2", + "637": "\u706b\u795e\u87f2", + "638": "\u52fe\u5e15\u8def\u7fc1", + "639": "\u4ee3\u62c9\u57fa\u7fc1", + "640": "\u7562\u529b\u5409\u7fc1", + "641": "\u9f8d\u6372\u96f2", + "642": "\u96f7\u96fb\u96f2", + "643": "\u96f7\u5e0c\u62c9\u59c6", + "644": "\u6377\u514b\u7f85\u59c6", + "645": "\u571f\u5730\u96f2", + "646": "\u914b\u96f7\u59c6", + "647": "\u51f1\u8def\u8fea\u6b50", + "648": "\u7f8e\u6d1b\u8036\u5854", + "649": "\u84cb\u8afe\u8cfd\u514b\u7279", + "650": "\u54c8\u529b\u99ac\u9f8d", + "651": "\u80a5\u4ed4\u54c8\u529b", + "652": "\u5e03\u91cc\u5361\u9686", + "653": "\u706b\u72d0\u72f8", + "654": "\u9577\u5c3e\u706b\u72d0", + "655": "\u5996\u706b\u7d05\u72d0", + "656": "\u5471\u5471\u6ce1\u86d9", + "657": "\u5471\u982d\u86d9", + "658": "\u7532\u8cc0\u5fcd\u86d9", + "659": "\u6316\u6316\u5154", + "660": "\u6509\u5730\u5154", + "661": "\u5c0f\u7bad\u96c0", + "662": "\u706b\u7bad\u96c0", + "663": "\u70c8\u7bad\u9df9", + "664": "\u7c89\u86f9", + "665": "\u7c89\u8776\u86f9", + "666": "\u78a7\u7c89\u8776", + "667": "\u5c0f\u7345\u7345", + "668": "\u706b\u708e\u7345", + "669": "\u82b1\u84d3\u84d3", + "670": "\u82b1\u8449\u8482", + "671": "\u82b1\u6f54\u592b\u4eba", + "672": "\u54a9\u54a9\u7f8a", + "673": "\u6307\u8def\u7f8a", + "674": "\u9811\u76ae\u718a\u8c93", + "675": "\u6d41\u6c13\u718a\u8c93", + "676": "\u591a\u9e97\u7c73\u4e9e", + "677": "\u5999\u55b5", + "678": "\u8d85\u80fd\u5999\u55b5", + "679": "\u7368\u528d\u9798", + "680": "\u96d9\u528d\u9798", + "681": "\u5805\u76fe\u528d\u602a", + "682": "\u7c89\u9999\u9999", + "683": "\u82b3\u9999\u7cbe", + "684": "\u7dbf\u7dbf\u6ce1\u8299", + "685": "\u80d6\u751c\u59ae", + "686": "\u6beb\u5587\u9b77", + "687": "\u70cf\u8cca\u738b", + "688": "\u9f9c\u8173\u8173", + "689": "\u9f9c\u8db3\u5de8\u93a7", + "690": "\u5783\u5783\u85fb", + "691": "\u6bd2\u62c9\u871c\u59ae", + "692": "\u9435\u81c2\u69cd\u8766", + "693": "\u92fc\u7832\u81c2\u8766", + "694": "\u767c\u96fb\u8725", + "695": "\u96fb\u5098\u67e5\u7279", + "696": "\u66b4\u9f8d\u4ed4", + "697": "\u602a\u984e\u9f8d", + "698": "\u51b0\u96ea\u9f8d", + "699": "\u51b0\u96ea\u5de8\u9f8d", + "700": "\u4ed9\u5b50\u4f0a\u8c9d", + "701": "\u6230\u9b25\u98db\u9ce5", + "702": "\u549a\u549a\u9f20", + "703": "\u5c0f\u788e\u947d", + "704": "\u9ecf\u9ecf\u5bf6", + "705": "\u9ecf\u7f8e\u5152", + "706": "\u9ecf\u7f8e\u9f8d", + "707": "\u9396\u5708\u5152", + "708": "\u5c0f\u6728\u9748", + "709": "\u673d\u6728\u5996", + "710": "\u5357\u74dc\u7cbe", + "711": "\u5357\u74dc\u602a\u4eba", + "712": "\u51b0\u5bf6", + "713": "\u51b0\u5ca9\u602a", + "714": "\u55e1\u8760", + "715": "\u97f3\u6ce2\u98db\u9f8d", + "716": "\u54f2\u723e\u5c3c\u4e9e\u65af", + "717": "\u4f0a\u79d8\u9b6f\u5854\u8def", + "718": "\u57fa\u683c\u723e\u5fb7", + "719": "\u8482\u5b89\u5e0c", + "720": "\u80e1\u5e15", "721": "\u6ce2\u723e\u51f1\u5c3c\u6069" - }, + }, + "sizes": { + "001": "\u8ff7\u4f60", + "002": "\u5c0f", + "003": "\u6b63\u5e38", + "004": "\u5927", + "005": "\u5de8\u5927" + }, "teams": { - "0": "Neutral (\u4e2d\u7acb)", - "1": "Mystic (\u53e1\u667a)", - "2": "Valor (\u6b66\u52c7)", - "3": "Instinct (\u9748\u7280)" - }, + "000": "Neutral (\u4e2d\u7acb)", + "001": "Mystic (\u53e1\u667a)", + "002": "Valor (\u6b66\u52c7)", + "003": "Instinct (\u9748\u7280)" + }, + "types": { + "001": "\u4e00\u822c", + "002": "\u683c\u9b25", + "003": "\u98db\u884c", + "004": "\u6bd2", + "005": "\u5730\u9762", + "006": "\u5ca9\u77f3", + "007": "\u87f2", + "008": "\u5e7d\u9748", + "009": "\u92fc", + "010": "\u706b", + "011": "\u6c34", + "012": "\u8349", + "013": "\u96fb", + "014": "\u8d85\u80fd\u529b", + "015": "\u51b0", + "016": "\u9f8d", + "017": "\u5996\u7cbe", + "018": "\u60e1" + }, "weather": { - "0": "\u6ca1\u6709", - "1": "\u6674\u5929", - "2": "\u96e8\u5929", - "3": "\u591a\u96f2", - "4": "\u9670\u5929", - "5": "\u5f37\u98a8", - "6": "\u4e0b\u96ea", - "7": "\u8d77\u9727" - }, - "misc": { - "boosted": "\u63D0\u632F" + "000": "\u6ca1\u6709", + "001": "\u6674\u5929", + "002": "\u96e8\u5929", + "003": "\u591a\u96f2", + "004": "\u9670\u5929", + "005": "\u5f37\u98a8", + "006": "\u4e0b\u96ea", + "007": "\u8d77\u9727" } -} +} \ No newline at end of file diff --git a/requirements.txt b/requirements.txt index db944ff3c..cc0419973 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,7 +1,7 @@ configargparse==0.12.0 flask==0.12.2 gevent==1.2.2 -googlemaps==2.5.1 pytz==2017.3 portalocker==1.1.0 shapely>=1.3.0 +requests==2.18.4 \ No newline at end of file diff --git a/rules.json.example b/rules.json.example index 0c38e28cc..14e025c8a 100644 --- a/rules.json.example +++ b/rules.json.example @@ -1,36 +1,36 @@ { - "monsters": { - "first_rule" : { - "filters": [ "filter_by_monsters_example" ], - "alarms": [ "discord_alarm" ] + "monsters":{ + "first_rule":{ + "filters":["filter_by_monsters_example"], + "alarms":["discord_alarm"] }, - "second_rule" : { - "filters": [ "filter_by_ivs_example", "filter_by_moves_example" ], - "alarms": [ "telegram_alarm" ] + "second_rule":{ + "filters":["filter_by_ivs_example","filter_by_moves_example"], + "alarms":["telegram_alarm"] } }, "stops":{ - "all" : { - "filters": [ "filter_by_geofence_example"], - "alarms": [ "discord_alarm", "telegram_alarm" ] + "all":{ + "filters":["filter_by_geofence_example"], + "alarms":["discord_alarm","telegram_alarm"] } }, - "gyms": { - "all" : { - "filters": [ "filter_by_teams_example", "gym_name_contains_regex_example"], - "alarms": [ "discord_alarm", "telegram_alarm" ] + "gyms":{ + "all":{ + "filters":["filter_by_teams_example","gym_name_contains_regex_example"], + "alarms":["discord_alarm","telegram_alarm"] } }, - "eggs": { - "all" : { - "filters": [ "filter_by_lvl_example" ], - "alarms": [ "discord_alarm", "telegram_alarm" ] + "eggs":{ + "all":{ + "filters":["filter_by_lvl_example"], + "alarms":["discord_alarm","telegram_alarm"] } }, - "raids": { - "all" : { - "filters": [ "filter_by_monster", "filter_raid_lvl_and_teams" ], - "alarms": [ "discord_alarm", "telegram_alarm" ] + "raids":{ + "all":{ + "filters":["filter_by_monster","filter_raid_lvl_and_teams"], + "alarms":["discord_alarm","telegram_alarm"] } } -} \ No newline at end of file +} diff --git a/start_pokealarm.py b/start_pokealarm.py index d2bf0d328..f202f061e 100644 --- a/start_pokealarm.py +++ b/start_pokealarm.py @@ -1,4 +1,4 @@ -#!/usr/bin/python +#!/usr/bin/env python # -*- coding: utf-8 -*- # Monkey Patch to allow Gevent's Concurrency @@ -26,7 +26,7 @@ from PokeAlarm import config from PokeAlarm.Cache import cache_options from PokeAlarm.Manager import Manager -from PokeAlarm.Utils import get_path, parse_unicode +from PokeAlarm.Utils import get_path, parse_unicode, parse_boolean from PokeAlarm.Load import parse_rules_file # Reinforce UTF-8 as default @@ -121,6 +121,8 @@ def parse_settings(root_path): parser = configargparse.ArgParser(default_config_files=config_files) parser.add_argument( '-cf', '--config', is_config_file=True, help='Configuration file') + + # Webserver Settings: parser.add_argument( '-d', '--debug', help='Debug Mode', action='store_true', default=False) parser.add_argument( @@ -132,6 +134,8 @@ def parse_settings(root_path): parser.add_argument( '-C', '--concurrency', type=int, help='Maximum concurrent connections for the webserver.', default=200) + + # Manager Settings parser.add_argument( '-m', '--manager_count', type=int, default=1, help='Number of Manager processes to start.') @@ -139,9 +143,7 @@ def parse_settings(root_path): '-M', '--manager_name', type=parse_unicode, action='append', default=[], help='Names of Manager processes to start.') - parser.add_argument( - '-k', '--key', type=str, action='append', default=[], - help='Specify a Google API Key to use.') + # Files parser.add_argument( '-f', '--filters', type=parse_unicode, action='append', default=['filters.json'], @@ -158,6 +160,8 @@ def parse_settings(root_path): '-gf', '--geofences', type=parse_unicode, action='append', default=[None], help='Alarms configuration file. default: None') + + # Location Specific parser.add_argument( '-l', '--location', type=parse_unicode, action='append', default=[None], help='Location, can be an address or coordinates') @@ -171,6 +175,31 @@ def parse_settings(root_path): action='append', choices=['metric', 'imperial'], help='Specify either metric or imperial units to use for distance " ' '+ "measurements. ') + parser.add_argument( + '-tz', '--timezone', type=str, action='append', default=[None], + help='Timezone used for notifications. Ex: "America/Los_Angeles"') + + # GMaps + parser.add_argument( + '-k', '--gmaps-key', type=str, action='append', + default=[], help='Specify a Google API Key to use.') + parser.add_argument( + '--gmaps-rev-geocode', type=parse_boolean, action='append', + default=[None], help='Enable Walking Distance Matrix DTS.') + parser.add_argument( + '--gmaps-dm-walk', type=parse_boolean, action='append', + default=[None], help='Enable Walking Distance Matrix DTS.') + parser.add_argument( + '--gmaps-dm-bike', type=parse_boolean, action='append', + default=[None], help='Enable Bicycling Distance Matrix DTS.') + parser.add_argument( + '--gmaps-dm-drive', type=parse_boolean, action='append', + default=[None], help='Enable Driving Distance Matrix DTS.') + parser.add_argument( + '--gmaps-dm-transit', type=parse_boolean, action='append', + default=[None], help='Enable Transit Distance Matrix DTS.') + + # Misc parser.add_argument( '-ct', '--cache_type', type=parse_unicode, action='append', default=['mem'], choices=cache_options, @@ -182,9 +211,6 @@ def parse_settings(root_path): parser.add_argument( '-ma', '--max_attempts', type=int, default=[3], action='append', help='Maximum attempts an alarm makes to send a notification.') - parser.add_argument( - '-tz', '--timezone', type=str, action='append', default=[None], - help='Timezone used for notifications. Ex: "America/Los_Angeles"') args = parser.parse_args() @@ -201,9 +227,12 @@ def parse_settings(root_path): config['DEBUG'] = args.debug # Check to make sure that the same number of arguments are included - for arg in [args.filters, args.alarms, args.geofences, - args.location, args.locale, args.units, args.cache_type, - args.timelimit, args.max_attempts, args.timezone]: + for arg in [args.filters, args.alarms, args.rules, + args.geofences, args.location, args.locale, args.units, + args.cache_type, args.timelimit, args.max_attempts, + args.timezone, args.gmaps_rev_geocode, args.gmaps_dm_walk, + args.gmaps_dm_bike, args.gmaps_dm_drive, + args.gmaps_dm_transit]: if len(arg) > 1: # Remove defaults from the list arg.pop(0) size = len(arg) @@ -239,7 +268,7 @@ def parse_settings(root_path): config['UNITS'] = get_from_list(args.units, m_ct, args.units[0]) m = Manager( name=args.manager_name[m_ct], - google_key=args.key, + google_key=args.gmaps_key, locale=get_from_list(args.locale, m_ct, args.locale[0]), units=get_from_list(args.units, m_ct, args.units[0]), timezone=get_from_list(args.timezone, m_ct, args.timezone[0]), @@ -257,6 +286,21 @@ def parse_settings(root_path): debug=config['DEBUG'] ) parse_rules_file(m, get_from_list(args.rules, m_ct, args.rules[0])) + + # Set up GMaps stuff + if get_from_list( + args.gmaps_rev_geocode, m_ct, args.gmaps_rev_geocode[0]): + m.enable_gmaps_reverse_geocoding() + if get_from_list(args.gmaps_dm_walk, m_ct, args.gmaps_dm_walk[0]): + m.enable_gmaps_distance_matrix('walking') + if get_from_list(args.gmaps_dm_bike, m_ct, args.gmaps_dm_bike[0]): + m.enable_gmaps_distance_matrix('biking') + if get_from_list(args.gmaps_dm_drive, m_ct, args.gmaps_dm_drive[0]): + m.enable_gmaps_distance_matrix('driving') + if get_from_list( + args.gmaps_dm_transit, m_ct, args.gmaps_dm_transit[0]): + m.enable_gmaps_distance_matrix('transit') + if m.get_name() not in managers: # Add the manager to the map managers[m.get_name()] = m diff --git a/tests/filters/test_egg_filter.py b/tests/filters/test_egg_filter.py index 17672e096..07eb6076f 100755 --- a/tests/filters/test_egg_filter.py +++ b/tests/filters/test_egg_filter.py @@ -39,7 +39,6 @@ def test_gym_names(self): settings = {"gym_name_contains": ["pass"]} egg_filter = Filters.EggFilter('filter1', settings) - # Generate events that should pass # Generate events that should pass pass1 = Events.EggEvent(generate_egg({"name": "pass1"})) pass2 = Events.EggEvent(generate_egg({"name": "2pass"})) @@ -58,6 +57,36 @@ def test_gym_names(self): for e in [fail1, fail2, fail3]: self.assertFalse(egg_filter.check_event(e)) + def test_gym_name_excludes(self): + # Create the filters + settings = {"gym_name_excludes": ["fail"]} + egg_filter = Filters.EggFilter('filter1', settings) + + # Generate events that should pass + for r in ["pass1", "2pass", "3pass3"]: + event = Events.EggEvent(generate_egg({"name": r})) + self.assertTrue(egg_filter.check_event(event)) + + # Generate events that should fail + for r in ["fail1", "failpass", "passfail"]: + event = Events.EggEvent(generate_egg({"name": r})) + self.assertFalse(egg_filter.check_event(event)) + + def test_park(self): + # Create the filters + settings = {"park_contains": ["pass"]} + egg_filter = Filters.EggFilter('filter1', settings) + + # Test events that should pass + for n in ["pass1", "2pass", "3pass3"]: + event = Events.EggEvent(generate_egg({"park": n})) + self.assertTrue(egg_filter.check_event(event)) + + # Test events that should fail + for n in ["fail1", "failpas", "pasfail"]: + event = Events.EggEvent(generate_egg({"park": n})) + self.assertFalse(egg_filter.check_event(event)) + def test_current_team(self): # Create the filters settings = {"current_teams": [1, "2", "Instinct"]} @@ -78,6 +107,23 @@ def test_current_team(self): for e in [fail1]: self.assertFalse(egg_filter.check_event(e)) + def test_sponsored(self): + # Create the filters + filter1 = Filters.RaidFilter('filter1', {"sponsored": False}) + filter2 = Filters.RaidFilter('filter2', {"sponsored": True}) + + # Generate events + not_sponsored = Events.EggEvent(generate_egg({"sponsor": 0})) + sponsored = Events.EggEvent(generate_egg({"sponsor": 4})) + + # Test passing events + self.assertTrue(filter1.check_event(not_sponsored)) + self.assertTrue(filter2.check_event(sponsored)) + + # Test failing events + self.assertFalse(filter2.check_event(not_sponsored)) + self.assertFalse(filter1.check_event(sponsored)) + def test_missing_info1(self): # Create the filters settings = {"max_dist": "inf", "is_missing_info": True} @@ -174,7 +220,9 @@ def generate_egg(values): "end": 1499246052, "level": 5, "latitude": 37.7876146, - "longitude": -122.390624 + "longitude": -122.390624, + "sponsor": None, + "park": None } egg.update(values) return egg diff --git a/tests/filters/test_gym_filter.py b/tests/filters/test_gym_filter.py index 1ba974a1e..b88f22961 100644 --- a/tests/filters/test_gym_filter.py +++ b/tests/filters/test_gym_filter.py @@ -33,6 +33,21 @@ def test_gym_names(self): for e in [fail1, fail2, fail3]: self.assertFalse(gym_filter.check_event(e)) + def test_gym_name_excludes(self): + # Create the filters + settings = {"gym_name_excludes": ["fail"]} + gym_filter = Filters.GymFilter('filter1', settings) + + # Generate events that should pass + for r in ["pass1", "2pass", "3pass3"]: + event = Events.GymEvent(generate_gym({"name": r})) + self.assertTrue(gym_filter.check_event(event)) + + # Generate events that should fail + for r in ["fail1", "failpass", "passfail"]: + event = Events.GymEvent(generate_gym({"name": r})) + self.assertFalse(gym_filter.check_event(event)) + def test_gym_guards(self): # Create the filters settings = {"min_slots": 2, "max_slots": 4} diff --git a/tests/filters/test_monster_filter.py b/tests/filters/test_monster_filter.py index 09eb56787..805ebc029 100644 --- a/tests/filters/test_monster_filter.py +++ b/tests/filters/test_monster_filter.py @@ -41,6 +41,30 @@ def test_monster_id(self): for e in [fail1, fail2, fail3]: self.assertFalse(mon_filter.check_event(e)) + def test_monsters_exclude(self): + # Create the filters + settings = { + "monsters_exclude": [4, "5", "Charizard"] + } + mon_filter = Filters.MonFilter('filter1', settings) + + # Generate events that should pass + pass1 = Events.MonEvent(generate_monster({"pokemon_id": 1})) + pass2 = Events.MonEvent(generate_monster({"pokemon_id": 2})) + pass3 = Events.MonEvent(generate_monster({"pokemon_id": 3})) + # Test passing events + for e in [pass1, pass2, pass3]: + self.assertTrue(mon_filter.check_event(e)) + + # Generate events that should fail + fail1 = Events.MonEvent(generate_monster({"pokemon_id": 4})) + fail2 = Events.MonEvent(generate_monster({"pokemon_id": 5})) + fail3 = Events.MonEvent(generate_monster({"pokemon_id": 6})) + + # Test failing events + for e in [fail1, fail2, fail3]: + self.assertFalse(mon_filter.check_event(e)) + def test_lvl(self): # Create the filters settings = {"min_lvl": 5, "max_lvl": 10} @@ -177,6 +201,21 @@ def test_form(self): self.assertFalse(mon_filter.check_event(create_event({'form': 2}))) self.assertFalse(mon_filter.check_event(create_event({'form': 999}))) + def test_costume(self): + # Create filter that forces settings + settings = {"costume_ids": [1, 2]} + mon_filter = Filters.MonFilter('costume_filter', settings) + + # Test events that should pass + for c in [1, 2]: + event = Events.MonEvent(generate_monster({"costume": c})) + self.assertTrue(mon_filter.check_event(event)) + + # Test events that should fail + for c in [3, 4]: + event = Events.MonEvent(generate_monster({"costume": c})) + self.assertFalse(mon_filter.check_event(event)) + def test_moves(self): quick_settings = {"quick_moves": ["Vine Whip", "Tackle"]} quick_mon_filter = Filters.MonFilter('quick_move_filter', diff --git a/tests/filters/test_raid_filter.py b/tests/filters/test_raid_filter.py index c7fadec03..a37f20de5 100755 --- a/tests/filters/test_raid_filter.py +++ b/tests/filters/test_raid_filter.py @@ -35,6 +35,29 @@ def test_monster_id(self): for e in [fail1, fail2, fail3]: self.assertFalse(raid_filter.check_event(e)) + def test_exclude_monster_id(self): + # Create the filters + settings = {"monsters_exclude": [382, "383", "Rayquaza"]} + raid_filter = Filters.RaidFilter('filter1', settings) + + # Generate events that should fail + pass1 = Events.RaidEvent(generate_raid({"pokemon_id": 20})) + pass2 = Events.RaidEvent(generate_raid({"pokemon_id": 150})) + pass3 = Events.RaidEvent(generate_raid({"pokemon_id": 301})) + + # Test failing events + for e in [pass1, pass2, pass3]: + self.assertTrue(raid_filter.check_event(e)) + + # Generate events that should pass + fail1 = Events.RaidEvent(generate_raid({"pokemon_id": 382})) + fail2 = Events.RaidEvent(generate_raid({"pokemon_id": 383})) + fail3 = Events.RaidEvent(generate_raid({"pokemon_id": 384})) + + # Test passing events + for e in [fail1, fail2, fail3]: + self.assertFalse(raid_filter.check_event(e)) + def test_quick_move(self): # Create the filters settings = {"quick_moves": [225, "88", "Present"]} @@ -102,13 +125,13 @@ def test_raid_lvl(self): def test_gym_names(self): # Create the filters - settings = {"gym_name_contains": ["pass"]} + settings = {"gym_name_contains": ["pass"]} raid_filter = Filters.RaidFilter('filter1', settings) # Generate events that should pass pass1 = Events.RaidEvent(generate_raid({"name": "pass1"})) pass2 = Events.RaidEvent(generate_raid({"name": "2pass"})) - pass3 = Events.RaidEvent(generate_raid({"name": "3pass3"})) + pass3 = Events.RaidEvent(generate_raid({"name": "3pass3"})) # Test passing events for e in [pass1, pass2, pass3]: self.assertTrue(raid_filter.check_event(e)) @@ -116,12 +139,42 @@ def test_gym_names(self): # Generate events that should fail fail1 = Events.RaidEvent(generate_raid({"name": "fail1"})) fail2 = Events.RaidEvent(generate_raid({"name": "failpas"})) - fail3 = Events.RaidEvent(generate_raid({"name": "pasfail"})) + fail3 = Events.RaidEvent(generate_raid({"name": "pasfail"})) # Test failing events for e in [fail1, fail2, fail3]: self.assertFalse(raid_filter.check_event(e)) + def test_gym_name_excludes(self): + # Create the filters + settings = {"gym_name_excludes": ["fail"]} + raid_filter = Filters.RaidFilter('filter1', settings) + + # Generate events that should pass + for r in ["pass1", "2pass", "3pass3"]: + event = Events.RaidEvent(generate_raid({"name": r})) + self.assertTrue(raid_filter.check_event(event)) + + # Generate events that should fail + for r in ["fail1", "failpass", "passfail"]: + event = Events.RaidEvent(generate_raid({"name": r})) + self.assertFalse(raid_filter.check_event(event)) + + def test_park(self): + # Create the filters + settings = {"park_contains": ["pass"]} + raid_filter = Filters.RaidFilter('filter1', settings) + + # Test events that should pass + for n in ["pass1", "2pass", "3pass3"]: + event = Events.RaidEvent(generate_raid({"park": n})) + self.assertTrue(raid_filter.check_event(event)) + + # Test events that should fail + for n in ["fail1", "failpas", "pasfail"]: + event = Events.RaidEvent(generate_raid({"park": n})) + self.assertFalse(raid_filter.check_event(event)) + def test_current_team(self): # Create the filters settings = {"current_teams": [1, "2", "Instinct"]} @@ -142,6 +195,23 @@ def test_current_team(self): for e in [fail1]: self.assertFalse(raid_filter.check_event(e)) + def test_sponsored(self): + # Create the filters + raid_filter1 = Filters.RaidFilter('filter1', {"sponsored": False}) + raid_filter2 = Filters.RaidFilter('filter2', {"sponsored": True}) + + # Generate events + not_sponsored = Events.RaidEvent(generate_raid({"sponsor": 0})) + sponsored = Events.RaidEvent(generate_raid({"sponsor": 4})) + + # Test passing events + self.assertTrue(raid_filter1.check_event(not_sponsored)) + self.assertTrue(raid_filter2.check_event(sponsored)) + + # Test failing events + self.assertFalse(raid_filter2.check_event(not_sponsored)) + self.assertFalse(raid_filter1.check_event(sponsored)) + def test_missing_info1(self): # Create the filters settings = {"max_dist": "inf", "is_missing_info": True} @@ -251,7 +321,9 @@ def generate_raid(values): "end": 1499246052, "level": 5, "latitude": 37.7876146, - "longitude": -122.390624 + "longitude": -122.390624, + "sponsor": None, + "park": None } raid.update(values) return raid diff --git a/tools/webhook_test.py b/tools/webhook_test.py index 1f8783c07..6f14a9243 100644 --- a/tools/webhook_test.py +++ b/tools/webhook_test.py @@ -6,6 +6,17 @@ import os import portalocker import pickle +from glob import glob + + +def get_path(path): + path = os.path.join(ROOT_PATH, path) + if not os.path.exists(path): + print 'The webhook_test.py file has moved from the PokeAlarm/tools' + \ + ' folder!\nPlease put it back or re-download PokeAlarm.' + sys.exit(1) + return path + truthy = frozenset([ "yes", "Yes", "y", "Y", "true", "True", "TRUE", "YES", "1", "!0" @@ -19,47 +30,21 @@ "5": "raid" } -teams = { - "0": "Uncontested", - "1": "Mystic", - "2": "Valor", - "3": "Instinct" -} - -weather = { - "0": "None", - "1": "Clear", - "2": "Rain", - "3": "Partly Cloudy", - "4": "Cloudy", - "5": "Windy", - "6": "Snow", - "7": "Fog" -} +ROOT_PATH = os.path.abspath(os.path.dirname(__file__)) +locales_file = glob(get_path('../locales/en.json'))[0] +data = json.loads(open(locales_file, 'rb+').read()) teams_formatted = re.sub('[{}",]', '', json.dumps( - teams, indent=4, sort_keys=True)) + data['teams'], indent=2, sort_keys=True)) weather_formatted = re.sub('[{}",]', '', json.dumps( - weather, indent=4, sort_keys=True)) + data['weather'], indent=2, sort_keys=True)) _cache = {} _gym_info = {} -def get_image_url(image): - return \ - "https://raw.githubusercontent.com/not4profit/images/master/" + image - - -_default_gym_info = { - "name": "unknown", - "description": "unknown", - "url": get_image_url('icons/gym_0.png') -} - - def set_init(webhook_type): payloadr = {} current_time = time.time() @@ -68,28 +53,28 @@ def set_init(webhook_type): "type": "pokemon", "message": { "pokemon_id": 149, - "pokemon_level": 30, - "player_level": 30, + "pokemon_level": None, + "player_level": None, "latitude": 37.7876146, "longitude": -122.390624, "encounter_id": current_time, "cp_multiplier": 0.7317000031471252, "form": None, - "cp": 768, - "individual_attack": 10, - "individual_defense": 1, - "individual_stamina": 9, - "move_1": 281, - "move_2": 133, + "cp": None, + "individual_attack": None, + "individual_defense": None, + "individual_stamina": None, + "move_1": None, + "move_2": None, "height": 0.5694651007652283, - "weight": 5.733094215393066, + "weight": None, "gender": 3, "seconds_until_despawn": 1754, "spawn_start": 2153, "spawn_end": 3264, "verified": False, - "weather": 0, - "boosted_weather": 0 + "weather": None, + "boosted_weather": None } } elif webhook_type == whtypes["2"]: @@ -108,7 +93,7 @@ def set_init(webhook_type): "type": "gym", "message": { "raid_active_until": 0, - "gym_id": 0, + "gym_id": current_time, "gym_name": "unknown", "team_id": 3, "slots_available": 0, @@ -124,11 +109,8 @@ def set_init(webhook_type): payloadr = { "type": "raid", "message": { - "gym_id": 0, - "name": "Test gym", - "team": 1, - "park": None, - "sponsor": 4, + "gym_id": current_time, + "gym_name": "unknown", "level": 5, "latitude": 37.7876146, "longitude": -122.390624, @@ -138,12 +120,8 @@ def set_init(webhook_type): payloadr = { "type": "raid", "message": { - "gym_id": 0, - "name": "Test gym", - "team": 1, - "park": "Test park", - "sponsor": 4, - "weather": 5, + "gym_id": current_time, + "gym_name": "unknown", "pokemon_id": 150, "cp": 12345, "move_1": 123, @@ -172,17 +150,17 @@ def int_or_default(input_parm): def get_gym_info(gym_id): """ Gets the information about the gym. """ - return _gym_info.get(gym_id, _default_gym_info) + return _gym_info.get(gym_id, 'unknown') def gym_or_invalid(prm, prm2): questionable_input = raw_input() - while get_gym_info(questionable_input)['name'] == "unknown": + while get_gym_info(questionable_input) == "unknown": print "Not a valid gym. Please try again..\n>", questionable_input = raw_input() - print "Gym found! {}".format(get_gym_info(questionable_input)['name']) + print "Gym found! {}".format(get_gym_info(questionable_input)) payload["message"][prm] = questionable_input - payload["message"][prm2] = get_gym_info(questionable_input)['name'] + payload["message"][prm2] = get_gym_info(questionable_input) def cache_or_invalid(): @@ -204,7 +182,7 @@ def load_cache(file): global _gym_info with portalocker.Lock(file, mode="rb") as f: data = pickle.load(f) - _gym_info = data.get('gym_info', {}) + _gym_info = data.get('gym_name', {}) def list_cache(): @@ -220,9 +198,8 @@ def list_gyms(): if len(_gym_info) > 50: with portalocker.Lock(os.path.join(path, "gyms.txt"), mode="wb+") as f: i = 0 - for key in _gym_info.keys(): + for key, name in _gym_info.items(): i += 1 - name = get_gym_info(key)['name'] f.write("[{}] {} : {} \n".format(i, name, key)) f.close() print "Find list of gyms in your \\tools\ folder (gyms.txt)" @@ -230,9 +207,8 @@ def list_gyms(): else: print "Here is a list of gyms found in your cache:" i = 0 - for key in _gym_info.keys(): + for key, name in _gym_info.items(): i += 1 - name = get_gym_info(key)['name'] print "[{}] {} : {} ".format(i, name, key) print "Enter gym id for raid (from above)\n>", @@ -268,25 +244,27 @@ def reset_timers_and_encounters(): }) elif payload["type"] == "raid": payload["message"].update({ + "gym_id": current_time, "start": current_time + 20, "end": current_time + 20 + 60, }) def get_and_validate_team(): - team = teams.get(raw_input(), 5) + team = data['teams'].get(raw_input(), 5) if team == 5: - print "Team invalid, defaulting to Uncontested" + print "Team invalid, defaulting to Neutral" team = 0 else: - for team_id, team_name in teams.iteritems(): + for team_id, team_name in data['teams'].iteritems(): if team_name == team: team = int(team_id) + break payload["message"]["team_id"] = team webhooks_formatted = re.sub('[{}",]', '', json.dumps( - whtypes, indent=4, sort_keys=True)) + whtypes, indent=2, sort_keys=True)) print "What kind of webhook would you like to send?(put in a number)\n"\ + webhooks_formatted + ">", type = whtypes.get(raw_input(), 0) @@ -324,29 +302,30 @@ def get_and_validate_team(): int_or_default("pokemon_id") print "Gender (1-3)\n>", int_or_default("gender") - if payload["message"]["pokemon_id"] == 201: - print "Which form of Unown would you like? (default: A)\n>", - form_character = raw_input()[0:1].upper() - if form_character == '': - print "Defaulting to A" - payload["message"]["form"] = 1 - else: - form = ord(form_character) - # A-Z = 1-26, ! = 27, ? = 28 - if ord('A') <= form <= ord('Z'): - form -= ord('A') - 1 - elif form == 33: - # ! - form = 27 - elif form == 63: - # ? - form = 28 - else: - print "Invalid form type. Defaulting to A" - form = 1 - payload["message"]["form"] = form + monster_id = "{:03d}".format(payload["message"]["pokemon_id"]) + if monster_id in data['forms'].keys(): + sorted_forms = sorted(data['forms'][monster_id]) + default_form_id = next(iter(sorted_forms)) + forms_formatted = ', '.join(data['forms'][monster_id][x] + for x in sorted_forms) + print "Which form of " + \ + data["pokemon"][monster_id] + ' would you like? (default: ' + \ + data['forms'][monster_id][default_form_id] + ')\n' + \ + forms_formatted + '\n>', + form_character = raw_input().lower() + found = False + for key, x in data['forms'][monster_id].items(): + if x.lower() == form_character: + payload['message']['form'] = int(key) + found = True + break + if not found: + print "Not a valid value, using default" + payload["message"]["form"] = int(default_form_id) print "Encounters enabled?\n>", if raw_input() in truthy: + payload["message"]["player_level"] = 30 + payload["message"]["height"] = 0.5694651007652283 print "CP?\n>", int_or_default("cp") print "Attack IV\n>", @@ -360,17 +339,19 @@ def get_and_validate_team(): print "Id of move 2\n>", int_or_default("move_2") if payload["message"]["pokemon_id"] == 19: - print "Count towards tiny Rattata medal?" + print "Count towards tiny Rattata medal?\n>", if raw_input() in truthy: payload["message"]["weight"] = 2.0 if payload["message"]["pokemon_id"] == 129: - print "Count towards big Magikarp medal?" + print "Count towards big Magikarp medal?\n>", if raw_input() in truthy: payload["message"]["weight"] = 14.0 - print "What type of weather? (put in a number)\n" + \ + print "Monster level?\n>", + int_or_default("pokemon_level") + print "What type of weather? (number only)(Default: None)\n" + \ weather_formatted + "\n>", int_or_default("weather") - print "Is this mon boosted by the weather? (y/n)\n", + print "Is this mon boosted by the weather? (y/n)\n>", if raw_input() in truthy: payload["message"]["boosted_weather"] = payload["message"]["weather"] elif type == whtypes["3"]: @@ -379,16 +360,14 @@ def get_and_validate_team(): get_and_validate_team() elif type == whtypes["4"]: gym_cache() - print "What level of gym egg? (1-5)\n>", - egglevel = check_int(raw_input(), payload["message"]["level"]) - if 6 > egglevel > 0: - payload["message"]["level"] = egglevel - else: - print "Egg level invalid. Assuming level 5" + print "Which team?(put in a number)\n" + teams_formatted + "\n>", + get_and_validate_team() elif type == whtypes["5"]: gym_cache() print "Enter pokemon id for raid\n>", int_or_default("pokemon_id") + print "Which team?(put in a number)\n" + teams_formatted + "\n>", + get_and_validate_team() print "Moveset important?\n>", if raw_input() in truthy: print "Id of move 1\n>", @@ -399,6 +378,14 @@ def get_and_validate_team(): weather_formatted + "\n>", int_or_default("weather") +if type in ["4", "5"]: + print "What level of raid/egg? (1-5)\n>", + level = check_int(raw_input(), payload["message"]["level"]) + if 6 > level > 0: + payload["message"]["level"] = level + else: + print "Egg/Raid level invalid. Assuming level 5" + reset_timers_and_encounters() while True: