import json import os import requests from .utils.dataIO import dataIO from __main__ import send_cmd_help from discord.ext import commands from .utils import checks class Pug: def __init__(self, bot): self.bot = bot self.settings = dataIO.load_json("data/pug/config.json") self.fp = "data/pug/config.json" API_KEY = self.settings["blizzard_api_key"] default_region = self.settings["default_region"] LEG_WITH_SOCKET = [ 132369, 132410, 137044, 132444, 132449, 132452, 132460, 133973, 133974, 137037, 137038, 137039, 137040, 137041, 137042, 137043, 132378, 137045, 137046, 137047, 137048, 137049, 137050, 137051, 137052, 137054, 137055, 137220, 137223, 137276, 137382, 138854 ] ENCHANTABLE_SLOTS = ["neck", "back", "finger1", "finger2"] region_locale = { 'us': ['us', 'en_US', 'en'], 'eu': ['eu', 'en_GB', 'en'] # 'kr': ['kr', 'ko_KR', 'ko'], # 'tw': ['tw', 'zh_TW', 'zh'], # 'es': ['es', 'es_MX', 'es'], es lookup is broken until the armory site is migrated to the new format } def get_sockets(self, player_dictionary): """ Return dict with total sockets and count of equipped gems and slots that are missing :param player_dictionary: Retrieved player dict from API :return: dict() """ sockets = 0 equipped_gems = 0 for item in player_dictionary["items"]: if item in "averageItemLevel" or item in "averageItemLevelEquipped": continue if int(player_dictionary["items"][item]["id"]) in self.LEG_WITH_SOCKET: sockets += 1 for bonus in player_dictionary["items"][item]["bonusLists"]: if bonus == 1808: # 1808 is Legion prismatic socket bonus sockets += 1 if item in ["neck", "finger1", "finger2"]: if player_dictionary["items"][item]["context"] == "trade-skill": sockets += 1 for ttip in player_dictionary["items"][item]["tooltipParams"]: if item in "mainHand" or item in "offHand": # Ignore Relic continue if "gem" in ttip: # Equipped gems are listed as gem0, gem1, etc... equipped_gems += 1 return {"total_sockets": sockets, "equipped_gems": equipped_gems} def get_enchants(self, player_dictionary): """ Get count of enchants missing and slots that are missing :param player_dictionary: :return: dict() """ self.missing_enchant_slots = [] for slot in self.ENCHANTABLE_SLOTS: if "enchant" not in player_dictionary["items"][slot]["tooltipParams"]: self.missing_enchant_slots.append(slot) return { "enchantable_slots": len(self.ENCHANTABLE_SLOTS), "missing_slots": self.missing_enchant_slots, "total_missing": len(self.missing_enchant_slots) } def get_raid_progression(self, player_dictionary, raid): r = [x for x in player_dictionary["progression"] ["raids"] if x["name"] in raid][0] normal = 0 heroic = 0 mythic = 0 for boss in r["bosses"]: if boss["normalKills"] > 0: normal += 1 if boss["heroicKills"] > 0: heroic += 1 if boss["mythicKills"] > 0: mythic += 1 return {"normal": normal, "heroic": heroic, "mythic": mythic, "total_bosses": len(r["bosses"])} def get_mythic_progression(self, player_dictionary): achievements = player_dictionary["achievements"] plus_two = 0 plus_five = 0 plus_ten = 0 if 33096 in achievements["criteria"]: index = achievements["criteria"].index(33096) plus_two = achievements["criteriaQuantity"][index] if 33097 in achievements["criteria"]: index = achievements["criteria"].index(33097) plus_five = achievements["criteriaQuantity"][index] if 33098 in achievements["criteria"]: index = achievements["criteria"].index(33098) plus_ten = achievements["criteriaQuantity"][index] return { "plus_two": plus_two, "plus_five": plus_five, "plus_ten": plus_ten } def get_char(self, name, server, target_region): self.settings = dataIO.load_json("data/pug/config.json") # Load Configs API_KEY = self.settings["blizzard_api_key"] r = requests.get("https://%s.api.battle.net/wow/character/%s/%s?fields=items+progression+achievements&locale=%s&apikey=%s" % ( self.region_locale[target_region][0], server, name, self.region_locale[target_region][1], API_KEY)) if r.status_code != 200: raise Exception("Could not find character (No 200 from API).") player_dict = json.loads(r.text) r = requests.get( "https://%s.api.battle.net/wow/data/character/classes?locale=%s&apikey=%s" % ( self.region_locale[target_region][0], self.region_locale[target_region][1], API_KEY)) if r.status_code != 200: raise Exception("Could Not Find Character Classes (No 200 From API)") class_dict = json.loads(r.text) class_dict = {c['id']: c['name'] for c in class_dict["classes"]} r = requests.get("https://%s.api.battle.net/wow/character/%s/%s?fields=stats&locale=%s&apikey=%s" % ( self.region_locale[target_region][0], server, name, self.region_locale[target_region][1], API_KEY)) if r.status_code != 200: raise Exception("Could not find character stats (No 200 From API).") stats_dict = json.loads(r.text) health = stats_dict["stats"]["health"] power = stats_dict["stats"]["power"] powertype = stats_dict["stats"]["powerType"] powertypeproper = powertype.title() strength = stats_dict["stats"]["str"] agi = stats_dict["stats"]["agi"] int = stats_dict["stats"]["int"] sta = stats_dict["stats"]["sta"] crit = stats_dict["stats"]["critRating"] critrating = stats_dict["stats"]["crit"] haste = stats_dict["stats"]["hasteRating"] hasterating = stats_dict["stats"]["haste"] mastery = stats_dict["stats"]["masteryRating"] masteryrating = stats_dict["stats"]["mastery"] vers = stats_dict["stats"]["versatility"] versrating = stats_dict["stats"]["versatilityDamageDoneBonus"] equipped_ivl = player_dict["items"]["averageItemLevelEquipped"] sockets = self.get_sockets(player_dict) enchants = self.get_enchants(player_dict) tov_progress = self.get_raid_progression(player_dict, "Trial of Valor") en_progress = self.get_raid_progression(player_dict, "The Emerald Nightmare") nh_progress = self.get_raid_progression(player_dict, "The Nighthold") tos_progress = self.get_raid_progression(player_dict, "Tomb of Sargeras") mythic_progress = self.get_mythic_progression(player_dict) armory_url = 'http://{}.battle.net/wow/{}/character/{}/{}/advanced'.format( self.region_locale[target_region][0], self.region_locale[target_region][2], server, name) return_string = '' return_string += "**%s** - **%s** - **%s %s**\n" % ( name.title(), server.title(), player_dict['level'], class_dict[player_dict['class']]) return_string += '<{}>\n'.format(armory_url) return_string += '```ini\n' # start Markdown # iLvL return_string += "[Equipped Item Level]: %s\n" % equipped_ivl # Mythic Progression return_string += "[Mythics]: +2: %s, +5: %s, +10: %s\n" % (mythic_progress["plus_two"], mythic_progress["plus_five"], mythic_progress["plus_ten"]) # Raid Progression return_string += "[EN]: {1}/{0} (N), {2}/{0} (H), {3}/{0} (M)\n".format(en_progress["total_bosses"], en_progress["normal"], en_progress["heroic"], en_progress["mythic"]) return_string += "[TOV]: {1}/{0} (N), {2}/{0} (H), {3}/{0} (M)\n".format(tov_progress["total_bosses"], tov_progress["normal"], tov_progress["heroic"], tov_progress["mythic"]) return_string += "[NH]: {1}/{0} (N), {2}/{0} (H), {3}/{0} (M)\n".format(nh_progress["total_bosses"], nh_progress["normal"], nh_progress["heroic"], nh_progress["mythic"]) return_string += "[TOS]: {1}/{0} (N), {2}/{0} (H), {3}/{0} (M)\n".format(tos_progress["total_bosses"], tos_progress["normal"], tos_progress["heroic"], tos_progress["mythic"]) # Gems return_string += "[Gems Equipped]: %s/%s\n" % ( sockets["equipped_gems"], sockets["total_sockets"]) # Enchants return_string += "[Enchants]: %s/%s\n" % (enchants["enchantable_slots"] - enchants["total_missing"], enchants["enchantable_slots"]) if enchants["total_missing"] > 0: return_string += "[Missing Enchants]: {0}".format( ", ".join(enchants["missing_slots"])) # Stats return_string += "\n" return_string += "[Health]: {} [{}]: {}\n".format(health, powertypeproper, power) return_string += "[Str]: {} [Agi]: {}\n".format(strength, agi, int, sta) return_string += "[Int]: {} [Sta]: {}\n".format(int, sta) return_string += "[Crit]: {}, {}% [Haste]: {}, {}%\n".format(crit, critrating, haste, hasterating,) return_string += "[Mastery]: {}, {}% [Vers]: {}, {}% bonus damage\n".format(mastery, masteryrating, vers, versrating) return_string += '```' # end Markdown return return_string @commands.command(name="pug", pass_context=True, no_pm=True) async def _pug(self, ctx, *, message): """A Warcraft Armory character lookup tool. Use: !pug Hyphenate two-word servers (Ex: Twisting-Nether).""" self.settings = dataIO.load_json("data/pug/config.json") # Load Configs default_region = self.settings["default_region"] target_region = default_region channel = ctx.message.channel try: i = str(ctx.message.content).split(' ') name = i[1] server = i[2] if len(i) == 4 and i[3].lower() in self.region_locale.keys(): target_region = i[3].lower() character_info = self.get_char(name, server, target_region) await self.bot.send_message(ctx.message.channel, character_info) except Exception as e: print(e) await self.bot.send_message(ctx.message.channel, "Error with character name or server.") @commands.command(pass_context=True, name='pugtoken') @checks.is_owner() async def _pugtoken(self, context, key: str): """Sets the token for the Blizzard API. You can use this command in a private message to the bot. Get an API token at: https://dev.battle.net/member/register""" settings = dataIO.load_json(self.fp) settings['blizzard_api_key'] = key dataIO.save_json(self.fp, settings) await self.bot.say("API key set.") @commands.command(pass_context=True, name='pugregion') @checks.is_owner() async def _pugregion(self, context, key: str): """Sets the default region.""" settings = dataIO.load_json(self.fp) settings['default_region'] = key dataIO.save_json(self.fp, settings) await self.bot.say("Default region set.") @commands.command() async def pugcredits(self): """Code credits.""" message = await self._credit() await self.bot.say(message) async def _credit(self): message = "```This cog is made possible by Pugbot.\n" message+= "Please visit https://github.com/reznok/PugBot for more information.\n" message+= "```" return message def check_folders(): if not os.path.exists("data/pug"): print("Creating data/pug folder...") os.mkdir("data/pug") def check_files(): fp = "data/pug/config.json" if not dataIO.is_valid_json(fp): print("Creating config.json...") dataIO.save_json(fp, {"blizzard_api_key": "", "default_region": "us"}) def setup(bot): check_folders() check_files() n = Pug(bot) bot.add_cog(n)