2016-08-12 13:55:59 +00:00
|
|
|
import asyncio
|
|
|
|
import discord
|
2016-08-12 15:23:45 +00:00
|
|
|
import json
|
|
|
|
import overwatch
|
2016-08-12 20:53:12 +00:00
|
|
|
import league
|
2016-08-12 19:08:36 +00:00
|
|
|
import strings as s
|
2016-08-13 12:19:41 +00:00
|
|
|
import telegram
|
2016-08-16 20:16:22 +00:00
|
|
|
import bs4
|
|
|
|
import brawlhalla
|
2016-08-12 15:48:35 +00:00
|
|
|
|
|
|
|
loop = asyncio.get_event_loop()
|
2016-08-12 15:23:45 +00:00
|
|
|
d_client = discord.Client()
|
2016-08-13 13:36:08 +00:00
|
|
|
discord_is_ready = False
|
|
|
|
|
|
|
|
|
|
|
|
# When Discord is ready, set discord_is_ready to True
|
|
|
|
@d_client.event
|
|
|
|
async def on_ready():
|
|
|
|
global discord_is_ready
|
|
|
|
discord_is_ready = True
|
2016-08-12 15:23:45 +00:00
|
|
|
|
|
|
|
# Get player database from the db.json file
|
|
|
|
file = open("db.json")
|
|
|
|
db = json.load(file)
|
|
|
|
file.close()
|
2016-08-12 13:55:59 +00:00
|
|
|
|
2016-08-12 14:01:05 +00:00
|
|
|
# Get the discord bot token from "discordtoken.txt"
|
2016-08-12 19:08:36 +00:00
|
|
|
file = open("discordtoken.txt", "r")
|
|
|
|
token = file.read()
|
|
|
|
file.close()
|
2016-08-12 15:23:45 +00:00
|
|
|
|
2016-08-12 20:53:12 +00:00
|
|
|
# Every timeout seconds, update player status and check for levelups
|
2016-08-12 17:21:43 +00:00
|
|
|
async def overwatch_level_up(timeout):
|
|
|
|
while True:
|
2016-08-13 13:36:08 +00:00
|
|
|
if discord_is_ready:
|
2016-08-13 13:52:11 +00:00
|
|
|
print("[Overwatch] Starting check...")
|
2016-08-13 13:36:08 +00:00
|
|
|
# Update data for every player in list
|
|
|
|
for player in db:
|
|
|
|
if "overwatch" in db[player]:
|
2016-08-13 18:03:47 +00:00
|
|
|
try:
|
|
|
|
r = await overwatch.get_player_data(**db[player]["overwatch"])
|
|
|
|
except overwatch.NotFoundException:
|
|
|
|
print("[Overwatch] Player not found.")
|
2016-08-16 13:28:07 +00:00
|
|
|
except Exception:
|
|
|
|
# If some other error occours, skip the player
|
|
|
|
print("[Overwatch] Request returned an unhandled exception.")
|
2016-08-13 18:03:47 +00:00
|
|
|
else:
|
|
|
|
if "level" not in db[player]["overwatch"] \
|
|
|
|
or r["data"]["level"] > db[player]["overwatch"]["level"]:
|
|
|
|
# Send the message
|
|
|
|
loop.create_task(send_event(eventmsg=s.overwatch_level_up,
|
|
|
|
player=player,
|
|
|
|
level=r["data"]["level"]))
|
|
|
|
# Update database
|
|
|
|
db[player]["overwatch"]["level"] = r["data"]["level"]
|
|
|
|
f = open("db.json", "w")
|
|
|
|
json.dump(db, f)
|
|
|
|
f.close()
|
|
|
|
finally:
|
|
|
|
asyncio.sleep(1)
|
2016-08-13 13:52:11 +00:00
|
|
|
print("[Overwatch] Check completed successfully.")
|
2016-08-13 13:36:08 +00:00
|
|
|
# Wait for the timeout
|
|
|
|
await asyncio.sleep(timeout)
|
|
|
|
else:
|
|
|
|
await asyncio.sleep(1)
|
|
|
|
|
|
|
|
# Every timeout seconds, update player league and check for rank changes
|
|
|
|
async def league_rank_change(timeout):
|
|
|
|
while True:
|
|
|
|
if discord_is_ready:
|
2016-08-13 18:03:47 +00:00
|
|
|
print("[League] Starting check for rank changes...")
|
2016-08-13 13:36:08 +00:00
|
|
|
# Update data for every player in list
|
|
|
|
for player in db:
|
|
|
|
if "league" in db[player]:
|
|
|
|
try:
|
|
|
|
r = await league.get_player_rank(**db[player]["league"])
|
|
|
|
except league.NoRankedGamesCompletedException:
|
|
|
|
# If the player has no ranked games completed, skip him
|
2016-08-16 13:28:07 +00:00
|
|
|
pass
|
2016-08-13 13:56:27 +00:00
|
|
|
except league.RateLimitException:
|
|
|
|
# If you've been ratelimited, skip the player and notify the console.
|
|
|
|
print("[League] Request rejected for rate limit.")
|
2016-08-16 13:28:07 +00:00
|
|
|
except Exception:
|
|
|
|
# If some other error occours, skip the player
|
|
|
|
print("[League] Request returned an unhandled exception.")
|
2016-08-13 13:36:08 +00:00
|
|
|
else:
|
|
|
|
# Convert tier into a number
|
|
|
|
tier_number = league.ranklist.index(r["tier"])
|
|
|
|
roman_number = league.roman.index(r["entries"][0]["division"])
|
|
|
|
# Check for tier changes
|
2016-08-13 18:03:47 +00:00
|
|
|
if tier_number != db[player]["league"]["tier"] \
|
|
|
|
or roman_number != db[player]["league"]["division"]:
|
2016-08-13 14:23:58 +00:00
|
|
|
# Send the message
|
|
|
|
loop.create_task(send_event(eventmsg=s.league_rank_up,
|
|
|
|
player=player,
|
|
|
|
tier=s.league_tier_list[tier_number],
|
2016-08-19 12:03:25 +00:00
|
|
|
division=r["entries"][0]["division"],
|
|
|
|
oldtier=db[player]["league"]["tier"],
|
|
|
|
olddivision=db[player]["league"]["division"]))
|
2016-08-13 13:36:08 +00:00
|
|
|
# Update database
|
|
|
|
db[player]["league"]["tier"] = tier_number
|
|
|
|
db[player]["league"]["division"] = roman_number
|
|
|
|
f = open("db.json", "w")
|
|
|
|
json.dump(db, f)
|
|
|
|
f.close()
|
2016-08-13 13:57:38 +00:00
|
|
|
finally:
|
2016-08-13 13:52:11 +00:00
|
|
|
# Prevent getting ratelimited by Riot
|
2016-08-13 18:03:47 +00:00
|
|
|
await asyncio.sleep(2)
|
|
|
|
print("[League] Rank check completed.")
|
|
|
|
# Wait for the timeout
|
|
|
|
await asyncio.sleep(timeout)
|
|
|
|
else:
|
|
|
|
await asyncio.sleep(1)
|
|
|
|
|
|
|
|
# Every timeout seconds, update player level and check for changes
|
|
|
|
async def league_level_up(timeout):
|
|
|
|
while True:
|
|
|
|
if discord_is_ready:
|
|
|
|
print("[League] Starting check for level changes...")
|
|
|
|
# Update data for every player in list
|
|
|
|
for player in db:
|
|
|
|
if "league" in db[player]:
|
|
|
|
try:
|
|
|
|
r = await league.get_player_info(**db[player]["league"])
|
|
|
|
except league.RateLimitException:
|
|
|
|
# If you've been ratelimited, skip the player and notify the console.
|
|
|
|
print("[League] Request rejected for rate limit.")
|
2016-08-16 13:28:07 +00:00
|
|
|
except Exception:
|
|
|
|
# If some other error occours, skip the player
|
|
|
|
print("[League] Request returned an unhandled exception.")
|
2016-08-13 18:03:47 +00:00
|
|
|
else:
|
|
|
|
# Check for level changes
|
2016-08-13 18:06:47 +00:00
|
|
|
if "level" not in db[player]["league"] or r["summonerLevel"] > db[player]["league"]["level"]:
|
2016-08-13 18:03:47 +00:00
|
|
|
# Send the message
|
|
|
|
loop.create_task(send_event(eventmsg=s.league_level_up,
|
|
|
|
player=player,
|
2016-08-13 18:06:47 +00:00
|
|
|
level=r["summonerLevel"]))
|
2016-08-13 18:03:47 +00:00
|
|
|
# Update database
|
2016-08-13 18:06:47 +00:00
|
|
|
db[player]["league"]["level"] = r["summonerLevel"]
|
2016-08-13 18:03:47 +00:00
|
|
|
f = open("db.json", "w")
|
|
|
|
json.dump(db, f)
|
|
|
|
f.close()
|
|
|
|
finally:
|
|
|
|
# Prevent getting ratelimited by Riot
|
|
|
|
await asyncio.sleep(2)
|
|
|
|
print("[League] Level check completed.")
|
2016-08-13 13:36:08 +00:00
|
|
|
# Wait for the timeout
|
|
|
|
await asyncio.sleep(timeout)
|
|
|
|
else:
|
|
|
|
await asyncio.sleep(1)
|
2016-08-12 17:21:43 +00:00
|
|
|
|
2016-08-16 20:16:22 +00:00
|
|
|
# Every timeout seconds, update player mmr and rank
|
|
|
|
async def brawlhalla_update_mmr(timeout):
|
|
|
|
while True:
|
|
|
|
if discord_is_ready:
|
|
|
|
print("[Brawlhalla] Starting check for mmr changes...")
|
|
|
|
# Update mmr for every player in list
|
|
|
|
for player in db:
|
|
|
|
if "brawlhalla" in db[player]:
|
|
|
|
try:
|
|
|
|
r = await brawlhalla.get_leaderboard_for(db[player]["brawlhalla"]["username"])
|
2016-08-17 21:46:58 +00:00
|
|
|
except None:
|
2016-08-16 20:16:22 +00:00
|
|
|
print("[Brawlhalla] Request returned an unhandled exception.")
|
|
|
|
else:
|
|
|
|
# Parse the page
|
2016-08-17 21:46:58 +00:00
|
|
|
bs = bs4.BeautifulSoup(r.text, "html.parser")
|
2016-08-16 20:16:22 +00:00
|
|
|
# Divide the page into rows
|
|
|
|
rows = bs.find_all("tr")
|
|
|
|
# Find the row containing the rank
|
|
|
|
for row in rows:
|
|
|
|
# Skip header rows
|
2016-08-17 21:46:58 +00:00
|
|
|
if row.has_attr('id') and row['id'] == "rheader":
|
2016-08-16 20:16:22 +00:00
|
|
|
continue
|
|
|
|
# Check if the row belongs to the correct player
|
|
|
|
# (Brawlhalla searches aren't case sensitive)
|
2016-08-17 21:46:58 +00:00
|
|
|
columns = list(row.children)
|
|
|
|
for column in columns:
|
2016-08-16 20:16:22 +00:00
|
|
|
# Find the player name column
|
2016-08-17 21:46:58 +00:00
|
|
|
if column.has_attr('class') and column['class'][0] == "pnameleft":
|
2016-08-16 20:16:22 +00:00
|
|
|
# Check if the name matches the parameter
|
|
|
|
if column.string == db[player]["brawlhalla"]["username"]:
|
|
|
|
break
|
|
|
|
else:
|
|
|
|
continue
|
|
|
|
# Get the current mmr
|
2016-08-17 21:46:58 +00:00
|
|
|
mmr = int(list(row.children)[7].string)
|
2016-08-16 20:16:22 +00:00
|
|
|
# Compare the mmr with the value saved in the database
|
|
|
|
if mmr != db[player]["brawlhalla"]["mmr"]:
|
|
|
|
# Send a message
|
2016-08-19 12:03:25 +00:00
|
|
|
loop.create_task(send_event(s.brawlhalla_new_mmr, player, mmr=mmr,
|
2016-08-19 12:03:49 +00:00
|
|
|
oldmmr=db[player]["brawlhalla"]["mmr"]))
|
2016-08-16 20:16:22 +00:00
|
|
|
# Update database
|
|
|
|
db[player]["brawlhalla"]["mmr"] = mmr
|
|
|
|
f = open("db.json", "w")
|
|
|
|
json.dump(db, f)
|
|
|
|
f.close()
|
|
|
|
break
|
|
|
|
finally:
|
|
|
|
await asyncio.sleep(1)
|
2016-08-17 21:46:58 +00:00
|
|
|
print("[Brawlhalla] Request returned an unhandled exception.")
|
2016-08-17 18:26:20 +00:00
|
|
|
await asyncio.sleep(timeout)
|
|
|
|
else:
|
|
|
|
await asyncio.sleep(1)
|
2016-08-16 20:16:22 +00:00
|
|
|
|
2016-08-13 14:23:58 +00:00
|
|
|
# Send a new event to both Discord and Telegram
|
|
|
|
async def send_event(eventmsg: str, player: str, **kwargs):
|
|
|
|
# Create arguments dict
|
|
|
|
mapping = kwargs.copy()
|
|
|
|
mapping["eventmsg"] = None
|
|
|
|
# Discord
|
|
|
|
# The user id is the player argument; convert that into a mention
|
|
|
|
mapping["player"] = "<@" + player + ">"
|
|
|
|
# Format the event message
|
|
|
|
msg = eventmsg.format(**mapping)
|
|
|
|
# Send the message
|
|
|
|
loop.create_task(d_client.send_message(d_client.get_channel("213655027842154508"), msg))
|
|
|
|
# Telegram
|
|
|
|
# Find the matching Telegram username inside the db
|
|
|
|
mapping["player"] = "@" + db[player]["telegram"]["username"]
|
|
|
|
# Convert the Discord Markdown to Telegram Markdown
|
|
|
|
msg = eventmsg.replace("**", "*")
|
|
|
|
# Format the event message
|
|
|
|
msg = msg.format(**mapping)
|
|
|
|
# Send the message
|
|
|
|
loop.create_task(telegram.send_message(msg, -2141322))
|
|
|
|
|
2016-10-01 22:27:57 +00:00
|
|
|
|
|
|
|
loop.create_task(overwatch_level_up(600))
|
|
|
|
print("[Overwatch] Added level up check to the queue.")
|
2016-08-13 13:52:11 +00:00
|
|
|
|
2016-08-29 10:31:55 +00:00
|
|
|
loop.create_task(league_rank_change(900))
|
2016-08-13 13:52:11 +00:00
|
|
|
print("[League] Added rank change check to the queue.")
|
2016-08-12 20:53:12 +00:00
|
|
|
|
2016-08-29 10:31:55 +00:00
|
|
|
loop.create_task(league_level_up(900))
|
2016-08-13 18:03:47 +00:00
|
|
|
print("[League] Added level change check to the queue.")
|
|
|
|
|
2016-08-29 10:31:55 +00:00
|
|
|
loop.create_task(brawlhalla_update_mmr(1800))
|
2016-08-17 18:26:20 +00:00
|
|
|
print("[Brawlhalla] Added mmr change check to the queue.")
|
|
|
|
|
|
|
|
|
2016-08-12 20:53:12 +00:00
|
|
|
try:
|
|
|
|
loop.run_until_complete(d_client.start(token))
|
|
|
|
except KeyboardInterrupt:
|
|
|
|
loop.run_until_complete(d_client.logout())
|
|
|
|
# cancel all tasks lingering
|
|
|
|
finally:
|
|
|
|
loop.close()
|