Files
aikaterna-cogs/pug/pug.py
2017-12-02 15:16:04 -08:00

314 lines
14 KiB
Python

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")
ant_progress = self.get_raid_progression(player_dict, "Antorus, the Burning Throne")
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"])
return_string += "[ANT]: {1}/{0} (N), {2}/{0} (H), {3}/{0} (M)\n".format(ant_progress["total_bosses"],
ant_progress["normal"],
ant_progress["heroic"],
ant_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 <name> <server> <region>
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)