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) 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 = [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'] 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', '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]