259 lines
8.9 KiB
Python
259 lines
8.9 KiB
Python
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 a plaer 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)
|
|
|
|
Takes one argument, a large json data set from the stats API and parses it
|
|
to figure out who the players favorite champion is. Stores all the data
|
|
in a temp dictionary, play_times, then grabs the max value from it
|
|
"""
|
|
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)
|
|
|
|
Takes one argument, a large json data set from the stats API and parses it
|
|
to figure out what the players favorite weapon is. Stores all the data
|
|
in a temp dictionary, weapon_stats, then grabs the max value from it
|
|
"""
|
|
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)
|
|
|
|
Takes one argument, a large json data set from the stats API and parses it
|
|
to figure the players total K/D ratio
|
|
"""
|
|
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 = [x for x in blob['playerRatings'] if blob['playerRatings'][x]['lastChange'] != 0][0]
|
|
|
|
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']
|
|
|
|
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(
|
|
match_data['teamScores'],
|
|
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' : '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 DOTt',
|
|
'FLAME' : 'Flame',
|
|
'ACID' : 'Acid',
|
|
'DRONE_KAMIKAZE_EXPLOSION' : 'Drone Kamikaze Explosion',
|
|
'RECON_DRONE' : 'Recon Drone',
|
|
'RECON_DRONE_EXPLOSION' : 'Recon Drone Explosion',
|
|
'ANARKI': 'Anarki',
|
|
'BJ_BLAZKOWICZ': 'BJ Blazkowicz',
|
|
'CLUTCH': 'Clutch',
|
|
'DOOM_SLAYER': 'Doom Slayer',
|
|
'GALENA': 'Galena',
|
|
'KEEL': 'Keel',
|
|
'NYX': 'Nyx',
|
|
'RANGER': 'Ranger',
|
|
'SCALEBEARER': 'Scalebearer',
|
|
'SLASH': 'Slash',
|
|
'SORLAG': 'Sorlag',
|
|
'STROGG': 'Strogg',
|
|
'VISOR': 'Visor',
|
|
}
|
|
|
|
return item_map[name] |