297 lines
9.7 KiB
Python
Executable File
297 lines
9.7 KiB
Python
Executable File
import requests
|
|
|
|
import discord
|
|
import help_methods
|
|
|
|
base_url = "https://stats.quake.com/api/v2/"
|
|
|
|
|
|
def parse_message(message):
|
|
"""
|
|
parse_message(message)
|
|
|
|
Handles the message and looks for the player's name.
|
|
"""
|
|
# Return the player's name
|
|
name = message.content.split()[1]
|
|
if len(message.content.split()) > 1:
|
|
name = "%20".join(message.content.split()[1:])
|
|
|
|
return get_player_stats(player=name)
|
|
|
|
|
|
def get_player_stats(player):
|
|
"""
|
|
get_player_stats(player)
|
|
|
|
Makes the request to stats.quake.com and returns an embed object with a
|
|
bunch of data about the player
|
|
"""
|
|
player_endpoint = "Player/Stats?name={}".format(player)
|
|
|
|
try:
|
|
request = requests.get("{}{}".format(base_url, player_endpoint)).json()
|
|
return create_embed(stats=request)
|
|
except Exception:
|
|
return discord.Embed(
|
|
description="404, Player not found",
|
|
color=discord.Color.dark_red(),
|
|
type="rich",
|
|
)
|
|
|
|
|
|
def create_embed(stats):
|
|
"""
|
|
create_embed(stats)
|
|
|
|
Expects a json blob to be passed in and then builds the embed
|
|
object
|
|
"""
|
|
|
|
# Parse the json and pull out the numbers we want
|
|
champ_name, play_time = get_favorite_champion(stats)
|
|
fav_weapon, fav_weapon_kills = get_favorite_weapon(stats)
|
|
kd_ratio = get_kd(stats)
|
|
|
|
embed = discord.Embed(
|
|
description="**All Time account statistics**",
|
|
color=discord.Color.dark_red(),
|
|
type="rich",
|
|
)
|
|
embed.set_author(
|
|
name="\nShowing stats for {}".format(stats["name"]),
|
|
icon_url="https://stats.quake.com/icons/{}.png".format(
|
|
stats["playerLoadOut"]["iconId"]
|
|
),
|
|
)
|
|
|
|
embed.add_field(name="Current level:", value=stats["playerLevelState"]["level"])
|
|
embed.add_field(name="Total XP:", value=stats["playerLevelState"]["exp"])
|
|
embed.add_field(name="K/D:", value=kd_ratio)
|
|
|
|
embed.add_field(name="\u200b", value="\u200b", inline=False)
|
|
|
|
embed.add_field(name="Favorite Champion:", value=champ_name)
|
|
embed.add_field(name="Total Playtime:", value="~{} hours".format(play_time))
|
|
|
|
embed.add_field(name="\u200b", value="\u200b", inline=False)
|
|
|
|
embed.add_field(name="Favorite Weapon:", value=fav_weapon)
|
|
embed.add_field(name="Num of kills with it:", value=fav_weapon_kills)
|
|
|
|
embed.add_field(name="\u200b", value="\u200b", inline=False)
|
|
|
|
# If they've played a ranked match, show the stats
|
|
if len(stats["playerRatings"]["tdm"]["history"]):
|
|
match_blob = get_match_stats(stats, stats["name"])
|
|
embed.add_field(name="Last Ranked Game:", value=match_blob)
|
|
|
|
embed.set_footer(
|
|
text="Stats pulled from https://stats.quake.com",
|
|
icon_url="https://stats.quake.com/icons/profile_icon_cbt_participant.png",
|
|
)
|
|
|
|
return embed
|
|
|
|
|
|
def get_favorite_champion(blob):
|
|
"""
|
|
get_favorite_champion(blob)
|
|
|
|
figure out who the players favorite champion is
|
|
"""
|
|
play_times = {}
|
|
all_champions = blob["playerProfileStats"]["champions"]
|
|
|
|
for champion in all_champions:
|
|
for game_mode in blob["playerProfileStats"]["champions"][champion]["gameModes"]:
|
|
if champion in play_times:
|
|
play_times[champion] += blob["playerProfileStats"]["champions"][
|
|
champion
|
|
]["gameModes"][game_mode]["timePlayed"]
|
|
play_times[champion] += blob["playerProfileStats"]["champions"][
|
|
champion
|
|
]["gameModes"][game_mode]["rankedTimePlayed"]
|
|
else:
|
|
play_times[champion] = blob["playerProfileStats"]["champions"][
|
|
champion
|
|
]["gameModes"][game_mode]["timePlayed"]
|
|
play_times[champion] = blob["playerProfileStats"]["champions"][
|
|
champion
|
|
]["gameModes"][game_mode]["rankedTimePlayed"]
|
|
|
|
champion_play_time = max(play_times.values()) # maximum value
|
|
champion_name = [k for k, v in play_times.items() if v == champion_play_time][
|
|
0
|
|
] # getting all keys containing the `maximum`
|
|
|
|
# Convert play_time from miliseconds to hours
|
|
champion_play_time = round(float(champion_play_time) / (1000 * 60 * 60), 2)
|
|
return (prettify(champion_name), champion_play_time)
|
|
|
|
|
|
def get_favorite_weapon(blob):
|
|
"""
|
|
get_favorite_weapon(blob)
|
|
|
|
figure out what the players favorite weapon is
|
|
"""
|
|
weapon_stats = {}
|
|
all_champions = blob["playerProfileStats"]["champions"]
|
|
|
|
for champion in all_champions:
|
|
for weapon in blob["playerProfileStats"]["champions"][champion][
|
|
"damageStatusList"
|
|
]:
|
|
if weapon in weapon_stats:
|
|
weapon_stats[weapon] += blob["playerProfileStats"]["champions"][
|
|
champion
|
|
]["damageStatusList"][weapon]["kills"]
|
|
else:
|
|
weapon_stats[weapon] = blob["playerProfileStats"]["champions"][
|
|
champion
|
|
]["damageStatusList"][weapon]["kills"]
|
|
|
|
total_kills = max(weapon_stats.values()) # maximum value
|
|
weapon_name = [k for k, v in weapon_stats.items() if v == total_kills][
|
|
0
|
|
] # getting all keys containing the `maximum`
|
|
|
|
return (prettify(weapon_name), total_kills)
|
|
|
|
|
|
def get_kd(blob):
|
|
"""
|
|
get_kd(blob)
|
|
|
|
Parses json to find the player's k/d
|
|
"""
|
|
total_kills = 0
|
|
total_deaths = 0
|
|
all_champions = blob["playerProfileStats"]["champions"]
|
|
|
|
for champion in all_champions:
|
|
for game_mode in blob["playerProfileStats"]["champions"][champion]["gameModes"]:
|
|
total_kills += blob["playerProfileStats"]["champions"][champion][
|
|
"gameModes"
|
|
][game_mode]["kills"]
|
|
total_deaths += blob["playerProfileStats"]["champions"][champion][
|
|
"gameModes"
|
|
][game_mode]["deaths"]
|
|
|
|
return round(float(total_kills / total_deaths), 2)
|
|
|
|
|
|
def get_match_stats(blob, target_player):
|
|
"""
|
|
get_match_stats(blob, target_player)
|
|
|
|
Takes the stats blob and a player name (so we know who's K/D we care about).
|
|
Attempts to figure out what the ranked game type was and then pulls stats from that game
|
|
"""
|
|
|
|
# Figure out which ranked gametype they last played
|
|
game_type = (
|
|
"tdm"
|
|
if blob["playerRatings"]["tdm"]["lastUpdated"]
|
|
< blob["playerRatings"]["duel"]["lastUpdated"]
|
|
else "duel"
|
|
)
|
|
|
|
most_recent_match_id = blob["playerRatings"][game_type]["history"][0]["sessionId"]
|
|
match_endpoint = "Player/Games?id={}".format(most_recent_match_id)
|
|
match_data = requests.get("{}{}".format(base_url, match_endpoint)).json()
|
|
fav_weapon = match_data["battleReportPersonalStatistics"][0]["bestWeapon"]
|
|
accuracy = match_data["battleReportPersonalStatistics"][0][
|
|
"bestWeaponAccuracyPercent"
|
|
]
|
|
score = "-".join(str(x) for x in match_data["teamScores"])
|
|
|
|
for team_mate in match_data["battleReportPersonalStatistics"]:
|
|
if team_mate["nickname"].lower() == target_player.lower():
|
|
earnedXp = team_mate["earnedXp"]
|
|
earnedFavor = team_mate["earnedFavor"]
|
|
|
|
kill_death_ratio = round(
|
|
float(match_data["battleReportPersonalStatistics"][0]["kills"])
|
|
/ match_data["battleReportPersonalStatistics"][0]["deaths"],
|
|
2,
|
|
)
|
|
|
|
return_blob = "Final score: {}\nK/D: {}\nFavorite Weapon: {} | {}% Accuracy\nXP Earned: {} | Favor Earned: {}".format(
|
|
score,
|
|
kill_death_ratio,
|
|
prettify(fav_weapon),
|
|
accuracy,
|
|
earnedXp,
|
|
earnedFavor,
|
|
)
|
|
|
|
return return_blob
|
|
|
|
|
|
def prettify(name):
|
|
"""
|
|
prettify(name)
|
|
|
|
Takes in an items name and returns a cleaned up / readable version
|
|
"""
|
|
|
|
item_map = {
|
|
"UNKNOWN_DAMAGE_TYPE": "Unknown Damage Type",
|
|
"GAUNTLET": "Gauntlet",
|
|
"MACHINEGUN": "Machinegun",
|
|
"MACHINEGUN_GRADE1": "Heavy Machinegun",
|
|
"SHOTGUN": "Basic Shotgun",
|
|
"SHOTGUN_GRADE1": "Super Shotgun",
|
|
"NAILGUN": "Nailgun",
|
|
"NAILGUN_GRADE1": "Super Nailgun",
|
|
"ROCKET_LAUNCHER": "Rocket Launcher",
|
|
"LIGHTNING_GUN": "Lightning Gun",
|
|
"RAILGUN": "Railgun",
|
|
"LAGBOLT": "TriBolt",
|
|
"ACID_DOMAIN": "Environmental Acid Death",
|
|
"DAMAGE_DOMAIN": "Environmental Damage Death",
|
|
"KILL_DOMAIN": "Environmental Kill Death",
|
|
"DIRE_ORB": "Dire Orb",
|
|
"DIRE_ORB_EXPLOSION": "Dire Orb Explosion",
|
|
"DIRE_ORB_TELEFRAG": "Dire Orb Telefrag",
|
|
"UNHOLY": "Galena's Totem",
|
|
"TELEFRAG": "Telefrag",
|
|
"FALL_DAMAGE": "Fall Damage",
|
|
"PLASMA_TRAIL": "Slash's Plasma Trail",
|
|
"PLASMA_TRAIL_EXPLOSION": "Slash's Plasma Trail Explosion",
|
|
"MINING_LASER": "Mining Laser",
|
|
"ABILITY_BERSERK": "Doom Slayer's Berserk Mode",
|
|
"SWARM_GRENADE": "Keel's Swarm Grenade",
|
|
"SB_DASH": "Scalbarer's Rush",
|
|
"SB_STOMP": "Scalbarer's Stomp",
|
|
"ACID_SPIT_DIRECT": "Acid Spit Direct",
|
|
"VENDETTA_TELEFRAG": "Vendetta Telefrag",
|
|
"ACID_DOT": "Sorlag's Acid DOT",
|
|
"FLAME_DOT": "Flame DOT",
|
|
"FLAME": "Flame",
|
|
"ACID": "Acid",
|
|
"DRONE_KAMIKAZE_EXPLOSION": "Drone Kamikaze Explosion",
|
|
"RECON_DRONE": "Recon Drone",
|
|
"RECON_DRONE_EXPLOSION": "Recon Drone Explosion",
|
|
"ANARKI": "Anarki",
|
|
"ATHENA": "Athena",
|
|
"BJ_BLAZKOWICZ": "BJ Blazkowicz",
|
|
"CLUTCH": "Clutch",
|
|
"DEATH_KNIGHT": "Death Knight",
|
|
"DOOM_SLAYER": "Doom Slayer",
|
|
"EISEN": "Eisen",
|
|
"GALENA": "Galena",
|
|
"KEEL": "Keel",
|
|
"NYX": "Nyx",
|
|
"RANGER": "Ranger",
|
|
"SCALEBEARER": "Scalebearer",
|
|
"SLASH": "Slash",
|
|
"SORLAG": "Sorlag",
|
|
"STROGG": "Strogg",
|
|
"VISOR": "Visor",
|
|
}
|
|
|
|
return item_map[name]
|