Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
87 commits
Select commit Hold shift + click to select a range
3fefee2
Update shebang line to work with virtualenv (#584)
skofisk Jan 29, 2018
153f216
Fix for weather boosts indexing (#586)
DavisPoGo Jan 29, 2018
66f03dc
Fix lazy load for Twitter (#589)
LegitDongo Jan 31, 2018
fb66d04
Reseed image urls.
Jan 31, 2018
6eb53e9
Fix bugs in weather alerts for 3.6
evilmoses Feb 2, 2018
7ddf2c5
removing personal code
evilmoses Feb 2, 2018
ce3f22d
weather alert bugfixes
evilmoses Feb 2, 2018
48e7f49
Update zh_hk translations. (#588)
Buncertainc Jan 30, 2018
1666f5f
Update filters and rules examples (#592)
MARTINI1 Feb 2, 2018
a75fd6e
Weather Boost Fixes (#594)
evilmoses Feb 2, 2018
3735f0e
Merge remote-tracking branch 'upstream/dev' into dev
evilmoses Feb 4, 2018
ba3c1d7
Fix bug with incorrect timezones for Stops(#598)
LegitDongo Feb 7, 2018
97f8749
Updates en.json to add Castform's Forms
billyjbryant Feb 11, 2018
7f681ab
Added Deoxys Forms as well
billyjbryant Feb 11, 2018
0b59ae3
Form Locale Updates for Castform, Deoxys and Updated Rayquaza Base St…
billyjbryant Feb 12, 2018
2a76823
Minor fix for zh_hk.json. (#596)
Buncertainc Feb 6, 2018
2cd0927
Make it possible to add a list of monsters to NOT trigger alarm. (#599)
fosJoddie Feb 12, 2018
befab25
Merge pull request #9 from billyjbryant/patch-1
evilmoses Feb 12, 2018
8720f5d
Merge remote-tracking branch 'upstream/master' into dev
evilmoses Feb 12, 2018
943180a
Merge branch 'dev' of https://github.com/evilmoses/PokeAlarm into dev
evilmoses Feb 12, 2018
6874372
Reseed image urls for cache busting.
Feb 12, 2018
80ed94f
Improve custom_dts inheritance.
Feb 13, 2018
8f89715
Add 'address_eu' to API detection. (#608)
fosJoddie Feb 16, 2018
0886913
Fix Geofence ordering in Filters. (#604)
kvangent Feb 16, 2018
e7cd036
Caching Improvements (#606)
kvangent Feb 16, 2018
6f34665
Data file cleanup (#609)
billyjbryant Feb 18, 2018
6c7df07
Bugfix for filecache save on windows.
Feb 18, 2018
f220065
Move Types DTS (#610)
billyjbryant Feb 19, 2018
2d6dbde
Fix bug with filecache when running multiple instances.
Feb 19, 2018
007b997
Really fix bug with FileCache which running multiple instances.
Feb 19, 2018
4ddfde6
Fix rules
thunder123456 Feb 19, 2018
ab7074b
merge recent stock commits
evilmoses Feb 19, 2018
eb1eebb
set up rules for weather alerts and set gmaps key default to None
evilmoses Feb 19, 2018
a2d55c5
Merge branch 'rules' into dev
evilmoses Feb 19, 2018
4210039
fix multi gmaps bugs in PR11
evilmoses Feb 19, 2018
817f77f
Do not set key default to None
evilmoses Feb 19, 2018
0ee29b6
Adding "gym_name_excludes" restriction to Gym, Egg, Raid filters (#611)
billyjbryant Feb 22, 2018
911c92c
Add Costume support
billyjbryant Feb 25, 2018
90fba54
Add Gym Sponsor and Parks DTS. (#603)
evilmoses Feb 26, 2018
2fc3620
GMaps Improvements (#612)
kvangent Feb 26, 2018
e1b0f65
Add "web_preview" option to Telegram (#620)
LegitDongo Feb 26, 2018
5134d28
Fixed is_sponsor filter bug for Raids
billyjbryant Feb 26, 2018
1950ee0
Fixed incorrect attribute refference in raids.
Feb 26, 2018
c55ca19
Added ignore for unlured stops.
Feb 26, 2018
cd7a0d6
Adding catch prob and movese rating DTS(#615)
rlodev67 Feb 27, 2018
bac0e43
Cleaned up locales
LegitDongo Feb 27, 2018
efe8d73
merge latest PA commits, including gmaps improvements and park/sponso…
evilmoses Feb 27, 2018
abd244c
remove merge duplication
evilmoses Feb 27, 2018
2ab93d3
Fixed bug with filtering with unknown sponsored id.
Feb 28, 2018
e637835
Fixed timedelta bug when hitting GMaps limit.
Feb 28, 2018
7d79743
Update Wiki to new outline (#619)
kvangent Feb 28, 2018
204f3fc
Add precision DTS for height and weight (#624)
Romfrosk Feb 28, 2018
f344d86
RTD - Installation & FAQ (#627)
MARTINI1 Mar 2, 2018
edf18d3
RTD - Add Misc Changes (#628)
MARTINI1 Mar 2, 2018
468d62a
RTD - Add Guides Section (#629)
MARTINI1 Mar 2, 2018
83d3188
RTD - Added Server Settings (#630)
MARTINI1 Mar 2, 2018
5a90ed2
RTD - Update Filters (#632)
MARTINI1 Mar 2, 2018
277e7db
RTD - Update Events (#631)
MARTINI1 Mar 2, 2018
c8e246e
RTD - Update Alarms (#633)
MARTINI1 Mar 2, 2018
7d0114e
Fix issue with gmaps sleep.
Mar 3, 2018
1edb3f6
Remove extra line in RaidEvent.
Mar 3, 2018
c9bf9ad
Update monster events for RMs new standard.
Mar 3, 2018
2ab9ccc
RTD - fix index.
Mar 3, 2018
3ad9a52
Added note to unfinished pages.
Mar 3, 2018
51751aa
RTD - Clean up sidebar.
Mar 3, 2018
7db7d7a
Correct boosted_weather field name.
Mar 3, 2018
ba57508
Really fixed bug with is_sponsor filter.
Mar 3, 2018
0f011a6
RTD - more index tweaks.
Mar 3, 2018
b6737fc
Update Webhook Tester (#637)
LegitDongo Mar 3, 2018
110b66e
RTD - new Geofence page.
Mar 3, 2018
a7624dd
RTD - Add Custom DTS (#638)
MARTINI1 Mar 4, 2018
982aac4
3.7 Patch Notes (#639)
billyjbryant Mar 4, 2018
8e7c5c8
RTD - New Rules page.
Mar 4, 2018
3c78c7b
Add additional catch probability dts (#635)
Romfrosk Mar 4, 2018
100e6bf
RTD - Add rules to sidebar.
Mar 4, 2018
f8b0061
Shortened Patch Notes.
Mar 4, 2018
31fb5c6
Change 'is_sponsor' to 'sponsored' and improve unit test.
Mar 4, 2018
da79256
Update wiki for sponsored filters/dts.
Mar 4, 2018
71bdaa8
Change 'ignore_monsters' to 'monsters_exclude' and added to raids.
Mar 4, 2018
e585dd4
RTD - Update FAQ.
Mar 4, 2018
391538d
RTD - move geofence image.
Mar 4, 2018
b582642
RTD - remove unfinished files.
Mar 4, 2018
5a5eda4
RTD - add sponsor dts to raids.
Mar 4, 2018
2601fa0
merge latest stock commits
evilmoses Mar 6, 2018
c3e0e13
send transformed pokemon name in form for ditto
evilmoses Mar 20, 2018
4e5d659
bugfix
evilmoses Mar 20, 2018
9cddc08
Adding deep linking for PokeGo++2.0
billyjbryant Apr 12, 2018
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ _build

# pa runtime files
*.pyc
cache/*.cache
cache/*

# OS files
.DS_Store
7 changes: 4 additions & 3 deletions PokeAlarm/Alarms/Discord/DiscordAlarm.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,9 +28,9 @@ class DiscordAlarm(Alarm):
'username': "<mon_name>",
'content': "",
'icon_url': get_image_url(
"regular/monsters/<mon_id_3>_<form_id_3>.png"),
"regular/monsters/<image_suffix>.png"),
'avatar_url': get_image_url(
"regular/monsters/<mon_id_3>_<form_id_3>.png"),
"regular/monsters/<image_suffix>.png"),
'title': "A wild <mon_name> has appeared!",
'url': "<gmaps>",
'body': "Available until <24h_time> (<time_left>)."
Expand Down Expand Up @@ -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(
Expand Down
2 changes: 1 addition & 1 deletion PokeAlarm/Alarms/FacebookPage/FacebookPageAlarm.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ class FacebookPageAlarm(Alarm):
'monsters': {
'message': "A wild <mon_name> has appeared!",
'image': get_image_url(
"regular/monsters/<mon_id_3>_<form_id_3>.png"),
"regular/monsters/<image_suffix>.png"),
'link': "<gmaps>",
'name': "<mon_name>",
'description': "Available until <24h_time> (<time_left>).",
Expand Down
2 changes: 1 addition & 1 deletion PokeAlarm/Alarms/Slack/SlackAlarm.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ class SlackAlarm(Alarm):
'monsters': {
'username': "<mon_name>",
'icon_url': get_image_url(
"regular/monsters/<mon_id_3>_<form_id_3>.png"),
"regular/monsters/<image_suffix>.png"),
'title': "A wild <mon_name> has appeared!",
'url': "<gmaps>",
'body': "Available until <24h_time> (<time_left>)."
Expand Down
19 changes: 13 additions & 6 deletions PokeAlarm/Alarms/Telegram/TelegramAlarm.py
Original file line number Diff line number Diff line change
Expand Up @@ -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 <mon_name> has appeared!*\n"
"Available until <24h_time> (<time_left>).",
'sticker_url': get_image_url(
"telegram/monsters/<mon_id_3>_<form_id_3>.webp")
"telegram/monsters/<image_suffix>.webp")
},
'stops': {
'message': "*Someone has placed a lure on a Pokestop!*\n"
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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:
Expand Down Expand Up @@ -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
}
}
Expand Down
4 changes: 2 additions & 2 deletions PokeAlarm/Alarms/Twitter/__init__.py
Original file line number Diff line number Diff line change
@@ -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
119 changes: 58 additions & 61 deletions PokeAlarm/Cache/Cache.py
Original file line number Diff line number Diff line change
Expand Up @@ -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')

Expand All @@ -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. """
Expand All @@ -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()
Expand Down
61 changes: 39 additions & 22 deletions PokeAlarm/Cache/FileCache.py
Original file line number Diff line number Diff line change
Expand Up @@ -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()))
18 changes: 11 additions & 7 deletions PokeAlarm/Events/EggEvent.py
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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)
Expand Down
Loading