I’ve been playing World of Warcraft lately in my spare time. Something I’ve been enjoying is the Mythic+ dungeons that were introduced with the Legion expansion. For these dungeons players must complete them within a time limit, but doing so requires a very competent team of players. The problem with the in-game tools that World of Warcraft provides is that it doesn’t show all of the data you may need to properly audit a players progress to see if they are experienced enough to do the dungeon.
I wanted to create a way to easily view a player’s progress without having to click through multiple menus on the games player profile website. I decided to create a bot user for the chat program Discord which ideally would present all of the information I needed in an easy to digest format.
You're Not Prepared
I decided to write my bot in Python as there’s an open source API wrapper called discord.py available which does all of the heavy lifting for you when it comes to sending and recieving messages from Discord. There’s also something very similar for NodeJS.
Setting up a simple bot is easy. First you’ll also need to invite your bot user to your Discord server using the following URL, replacing the client ID part first.
Now all you need to do is use the following scaffold, and once the script is executed anytime a user types a message in the chat which starts with ‘hello’ your bot will reply with the word ‘world’. This will be known as our message listening function.
Making It Do Things
Now that the bot can post messages to the Discord server some methods are needed so it does more than just say the word ‘world’. I want my bot to respond to a set of specific trigger words so it knows it’s being talked to. For this I decided to go with the format
!armory pve <name> <realm>. Once a user sends a message with this format I want it to make an API call to World of Warcraft using the name and realm fields in the message, fetch all of the data I need, and then return that data to my message listening function. From there I could then use that information to format and post the information to Discord.
I created an ‘umbrella’ function called
character_info and set it up to take three arguments, the players name, realm, and the type of content requested, for example PVE. The goal of this function is to create and return a piece of JSON with information pertaining to the character.
get_data function in the example above is used to do exactly that, get data. The World of Warcraft API doesn’t have a single method for fetching all of the data I want to show, so this reusable function shows up multiple times throughout my bots code. The function takes three arguments, the players name, realm, and the type of data you want to retrieve, for instance ‘items’ or ‘achievements’. These data types can be found on the Blizzard API explorer.
Once it has returned with the requested data we can then start forming our character object.
character_info is called it returns a JSON object with some information that your message listening function can use to display in the Discord chat. In the following example the bot will reply with the players item level whenever
!armory pve <name> <realm> is typed.
Now that the basic functionality of the bot has been implemented it’s time to extend its abilities. Because our
character_info function simply returns some JSON we can easily add additional properties so it returns even more information about a specific character.
I want a way to check if a player has completed a specific achievement, luckily for me the World of Warcraft API has a method for fetching achievement data about a character, however the way it’s organized can be a bit confusing. Each achievement is represented by an ID number and it’s stored within a lengthy array called
achievementsCompleted. I wrote a basic function that accepts data from the achievements API and then sorts through the
achievementsCompleted array. If the user hasn’t completed the achievement it returns ‘In Progress’, if they have it switches to ‘Completed’.
In an effort to make the achievement tracking function cleaner I setup a
constants.py file which would act as a dictionary, mapping ID numbers to a name.
Within my achievement function I can now see if the
achievementsCompleted array contains an ID by simply referncing the name I setup in the constants file.
character_info I call the
achievement_data function and use the JSON it returns to add more information to my character object.
Within the message listner function I can now organize the data retrieved from
character_info to publish the data to Discord. You can utilize message attachments with discord.py which allow you to modify how the content looks when it’s posted to Discord.
I spent quite a bit of time extending the functionality of my bot, it can track notable achievements, raid progression, item level, race, faction, and more. I also added another method called
!armory pvp <name> <realm> so you can gather information about a characters PVP progression.