Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
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
6 changes: 6 additions & 0 deletions config.py.example
Original file line number Diff line number Diff line change
Expand Up @@ -29,3 +29,9 @@ REPORT_SINCE = datetime(2016, 7, 29)
GOOGLE_MAPS_KEY = 's3cr3t'
MAP_PROVIDER_URL = '//{s}.tile.osm.org/{z}/{x}/{y}.png'
MAP_PROVIDER_ATTRIBUTION = '&copy; <a href="http://osm.org/copyright">OpenStreetMap</a> contributors'

#Discord stuff required if using discord notifications
DISCORD_APP_ID = 'secret'
DISCORD_TOKEN = 'secret'
DISCORD_CHANNELS = ['id',] #List of channel id's the bot should post to
DISCORD_UPDATE_INTERVAL = 2 #Time in minutes between checks for new sightings
43 changes: 43 additions & 0 deletions messages.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
import config

EN_MESSAGES = {
'ready':['[INFO] To add me visit this url: {}', '[INFO] READY to begin!', '[INFO] You are connected to {} servers!'],
'ready_msg': 'Looking for new Pokemon!',
'error': 'Caught error: {}',
'shutdown': 'Let me logout first...',
'sighting': '**{}** ({}) sighted!\n{}\nDisappearing in {:.0f} minutes.',
'bot_desc': 'Reports sightings of rare Pokemon',
'cmd_read_desc': 'Lists all tracked Pokemon',
'cmd_read_msg': 'These are the tracked Pokemon:\n',
'cmd_add_desc': 'Adds Pokemon to the watchlist',
'cmd_add_added': 'Tracking {} now :rainbow:',
'cmd_add_already_added': '{} is already on the watchlist :warning:',
'cmd_add_usage': 'Usage: "!add pokemon_id" :point_up:',
'cmd_remove_desc': 'Removes Pokemon from the Watchlist',
'cmd_remove_removed': 'Stopped tracking {} :rainbow:',
'cmd_remove_no_on_list' : '{} Is not being tracked :warning:',
'cmd_remove_usage': 'Usage: "!remove pokemon_id" :point_up:',
}

DE_MESSAGES = {
'ready':['[INFO] Um mich hinzuzufügen besuche diese url: {}', '[INFO] BEREIT!', '[INFO] Du bist mit {} servern verbunden!'],
'ready_msg': 'Auf der Suche nach neuen Pokemon!',
'error': 'Fehler gefunden: {}',
'shutdown': 'Logge aus...',
'sighting': '**{}** ({}) gesichtet!\n{}\nVerschwindet in {:.0f} Minuten.',
'bot_desc': 'Berichtet über Sichtungen seltener Pokemon',
'cmd_read_desc': 'Listet alle beobachteten Pokemon auf',
'cmd_read_msg': 'Dies sind die beobachteten Pokemon:\n',
'cmd_add_desc': 'Fügt ein Pokemon zu den beobachteten Pokemon hinzu',
'cmd_add_added': 'Beobachte nun {} :rainbow:',
'cmd_add_already_added': '{} wird bereits beobachtet :warning:',
'cmd_add_usage': 'Verwendung: "!add pokemon_id" :point_up:',
'cmd_remove_desc': 'Entferne ein Pokemon von den beobachteten Pokemon',
'cmd_remove_removed': 'Beobachte {} nichtmehr :rainbow:',
'cmd_remove_no_on_list' : '{} Wird nicht beobachtet :warning:',
'cmd_remove_usage': 'Verwendung: "!remove pokemon_id" :point_up:',
}

DISCORD_MESSAGES = {
'DE': DE_MESSAGES,
}.get(config.LANGUAGE.upper(), EN_MESSAGES)
133 changes: 133 additions & 0 deletions notifications.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,133 @@
import discord
from discord.ext import commands
import asyncio
import signal
import sys
import time
from geopy.geocoders import GoogleV3
import json

import config
import db
from names import POKEMON_NAMES
from messages import DISCORD_MESSAGES

# Check whether config has all necessary attributes
REQUIRED_SETTINGS = (
'DISCORD_APP_ID',
'DISCORD_TOKEN',
'DISCORD_CHANNELS',
'DISCORD_UPDATE_INTERVAL',
'GOOGLE_MAPS_KEY',
)
for setting_name in REQUIRED_SETTINGS:
if not hasattr(config, setting_name):
raise RuntimeError('Please set "{}" in config'.format(setting_name))

join_url = "https://discordapp.com/oauth2/authorize?client_id=" + config.DISCORD_APP_ID + "&scope=bot&permissions="

client = commands.Bot(command_prefix='!', description=DISCORD_MESSAGES['bot_desc'])
already_seen = {}
geolocator = GoogleV3(api_key=config.GOOGLE_MAPS_KEY)

icon_path = './static/icons/{}.png'
watchlist_path = 'watchlist.json'
with open(watchlist_path) as json_data:
watchlist = json.load(json_data)['watchlist']

@client.event
async def on_ready():
print(DISCORD_MESSAGES['ready'][0].format(join_url))
print(DISCORD_MESSAGES['ready'][1])
print(DISCORD_MESSAGES['ready'][2].format(count_iterable(client.servers)))
client.loop.create_task(sightings_update_task())
for id in config.DISCORD_CHANNELS:
channel = client.get_channel(id)
await client.send_message(channel, DISCORD_MESSAGES['ready_msg'])


@client.event
async def on_error(event, *args, **kwargs):
print(DISCORD_MESSAGES['error'].format(event))

@client.command(description=DISCORD_MESSAGES['cmd_read_desc'], help=DISCORD_MESSAGES['cmd_read_desc'])
async def read(): #Displays all tracked pokemon
tracked_pokemon = "```\n"
for id in watchlist:
tracked_pokemon += '{} {}\n'.format(id, POKEMON_NAMES[id])
tracked_pokemon += "```"
await client.say(DISCORD_MESSAGES['cmd_read_msg'] + tracked_pokemon)

@client.command(description=DISCORD_MESSAGES['cmd_add_desc'], help=DISCORD_MESSAGES['cmd_add_desc'])
async def add(id: int):
if id not in watchlist:
watchlist.append(id)
with open(watchlist_path, 'w') as json_data:
json.dump({'watchlist': watchlist}, json_data)
await client.say(DISCORD_MESSAGES['cmd_add_added'].format(POKEMON_NAMES[id]))
else:
await client.say(DISCORD_MESSAGES['cmd_add_already_added'].format(POKEMON_NAMES[id]))

@add.error
async def add_error(error, id):
await client.say(DISCORD_MESSAGES['cmd_add_usage'])

@client.command(description=DISCORD_MESSAGES['cmd_remove_desc'], help=DISCORD_MESSAGES['cmd_remove_desc'])
async def remove(id: int):
if id is None:
await client.say(DISCORD_MESSAGES['cmd_remove_usage'])
elif id in watchlist:
watchlist.remove(id)
with open(watchlist_path, 'w') as json_data:
json.dump({'watchlist': watchlist}, json_data)
await client.say(DISCORD_MESSAGES['cmd_remove_removed'].format(POKEMON_NAMES[id]))
else:
await client.say(DISCORD_MESSAGES['cmd_remove_no_on_list'].format(POKEMON_NAMES[id]))

@remove.error
async def remove_error(error, id):
await client.say(DISCORD_MESSAGES['cmd_remove_usage'])

async def check_pokemon():
session = db.Session()
pokemons = db.get_sightings(session)
session.close()

for sighting in pokemons:
await process_sighting(sighting)

remove_stale_sightings()

async def process_sighting(sighting):
if sighting.pokemon_id in watchlist:
if sighting.id not in already_seen.keys():
already_seen[sighting.id] = sighting
await report_sighting(sighting)

async def report_sighting(sighting):
name = POKEMON_NAMES[sighting.pokemon_id]
location = geolocator.reverse('' + sighting.lat + ', ' + sighting.lon, exactly_one=True)
street = location.address
disapper_time_diff = ((sighting.expire_timestamp - time.time()) // 60)
message = DISCORD_MESSAGES['sighting'].format(name, sighting.pokemon_id, street, disapper_time_diff)

for id in config.DISCORD_CHANNELS:
channel = client.get_channel(id)
await client.send_file(channel, icon_path.format(sighting.pokemon_id), content=message)

async def sightings_update_task():
await client.wait_until_ready()
while not client.is_closed:
await check_pokemon()
await asyncio.sleep(60 * config.DISCORD_UPDATE_INTERVAL)

def remove_stale_sightings():
old_seen = already_seen.copy()
for key in old_seen:
if old_seen[key].expire_timestamp < time.time():
del already_seen[key]

def count_iterable(i):
return sum(1 for e in i)

client.run(config.DISCORD_TOKEN)
1 change: 1 addition & 0 deletions requirements.txt
Original file line number Diff line number Diff line change
Expand Up @@ -9,3 +9,4 @@ werkzeug==0.11.10
sqlalchemy==1.0.14
-e git+https://github.com/keyphact/pgoapi.git@39ea20d31b770dd7bc83180d60283e171090e16d#egg=pgoapi
enum34==1.1.6
discord.py==0.11.0
3 changes: 3 additions & 0 deletions watchlist.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
{
"watchlist": [3, 6, 9, 26, 38, 40, 51, 76, 94, 95, 104, 107, 110, 115, 122, 123, 128, 132, 139, 141, 142, 143, 148, 149, 150, 151]
}