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]