Markkop / corvo-astral
A Discord Bot that serves as an Wakfu helper
🌙 Corvo Astral
Corvo Astral is a Discord Bot that provides information about the Wakfu MMORPG game.
If you wish to add this bot to your server, access this link.
Most features support Wakfu community languages: en, es, pt and fr.
If you need help or want to report bugs, feel free to join the bot's discord: https://discord.gg/aX6j3gM8HC
This bot is now featured in top.gg: https://top.gg/bot/750529201161109507
To keep the bot running, please consider donating
/alma: returns the Almanax Bonus for the current day
/calc: calculates the damage for an attack given some values
/subli: search for sublimations by name, slot combination or source
/recipe: search for recipes by name and rarity
/equip: search for equipment by name and rarity
/party: create, update, join or leave a party listing
/about: get information about this bot
/config: configure custom…
🤖 About the Bot
Corvo Astral is an open-source Discord Bot that provides information about an MMORPG game called Wakfu, made by Ankama. It's being used in over 230 servers, and it's also featured in top.gg bot listing.
It started with a simple command that did some calculation given some character attributes, but as soon as I saw potential for cool stuff to do I went all in.
💻 Initial Development
Also, the DiscordJS library have a pretty neat documentation, so that really helped.
I started by google searching all the way up to make the bot working, as any developer would do when starting a project for the first time.
Having it responding to commands was pretty easy, and adapting the code to accept multiple commands without
switch statements was not that hard too.
After implementing the
.calc command I got hyped to add the
.alma command, which stands for Almanax, the name for the daily bonus that can be obtained in the game.
While the current bonus cannot be obtained using an external API, it can be guessed using date manipulation.
I was very happy to come up with this solution. And I even used in my guild's website.
By the way, I was looking to improve my testing skills, so most of the code - including my precious daily bonus prediction command - was implemented using Test Driven Development (TDD). It ended up being great for maintenance and future upgrades I made in the bot.
📥 Importing Data
My next and biggest command implemented was
.equip. While creating the logic for finding the matching equipment based on its name and rarity was not that hard, the real work lied into obtaining the equipment data from the game.
The good news was that Wakfu had a Content Delivery Network (CDN) that I could use.
The bad news is that it comes with lots of split data, so I would have to assemble all the information I'd get from there.
This time I went in a Go Horse mode and coded all my way up into having readable content that the bot could provide to the user.
Surely enough, I've regretted not making tests or even a better code as soon as the game launched a new version with newer items.
The bot would be outdated for several months then.
Here's an article I wrote about interpreting some Wakfu data:
Mark Kop ・ Sep 28 '20 ・ 6 min read
💡 Side note: semantic commit names are worth
I mean, to write this post, I'm basically looking in the project's commit history to remember the order I've built the project and its difficulties.
💾 Importing extra data
While the CDN had almost all the data I needed, it didn't had some really useful information like equipment states (their special effects description) and equip conditions.
The way I've found to obtain them was getting all the equipment from a fan site that had a Builder tool and enrich the data.
Almost a year later, this webpage shut down (not my fault, I swear!), and my data was even more outdated.
🕸️ Web Page Scrapping
Another way I found to get cool data was scrapping the game's encyclopedia webpage. The user could request the drop information for a given equipment, monsters strengths, weaknesses and drop table or even get some trivia facts for the current ingame date.
Unfortunately I had to remove these features after the company implemented a website protection service against DDoS attack and - in my case - web scrapping.
The web scrapper implementation in the bot was not totally useless thought. I made it so whenever someone would share a character build link in a channel, the bot would scrap the page, sum the total equipment stats, take a screenshot and reply the user with a preview, so people didn't need to actually access the website to check the build.
🌟 Even more features
I couldn't stop there. I implemented other cool commands, such as finding sublimations (equipment enchantments) according to their color slots. Not only that, but I even did a Party Finder system that allows users to post a party listing, and others were able to join it or leave it simply by reacting to it.
Also, as I wanted to reach more people, I've added internationalization in the project, allowing commands to be used and translated in all four languages supported by the game: English, French, Spanish and Portuguese.
⚙️ It's Refactor time: OOP and Typescript
As I was creating new commands, I felt that I could reuse and abstract a lot of code. Furthermore, I was studying Object-Oriented Paradigm concepts and Typescript by that time, so it was the perfect opportunity to practice both.
On top of that, I tried to follow some SOLID principles and Design Patterns, but sometimes I felt that they would increase a lot the code complexity.
And some of them are kinda incompatible.
Using the Singleton pattern to let a single class instance manage each server's config was great, but it broke the Open/Closed principle.
That shows how practicing OOP/SOLID/Design Patterns in this project was awesome: I was able to understand, in a real project, why these programming references are great to know, but aren't always the best solution.
And by using Typescript I barely had bugs in production. I still can remember implementing a new command before the TS migration and finding
undefined behavior as errors in Heroku's logs.
Surely having those test cases implemented since the start helped a lot as well.
⚙️ Refactoring tests
As I said earlier, the reason I coded lots of tests since the start of the project was also because I wanted to practice TDD and tests frameworks.
However, since I've changed a lot the source code with OOP classes and Typescript, I had to adapt those as well.
The biggest challenge was mocking the Discord dependency entirely.
While in the previous approach I could just mock and spy the
.send method with an object and some other methods, this time TS would complain a lot about missing properties.
Pretty ugly, right? (but hey, it worked for its purposes)
After lots of searching, I've found a pretty cool mock that I was able to adapt. Here's the current code: tests/mockDiscord.ts
Along with this new approach I had the ability to test some features that I had no idea how I would do previously, like message reactions (and therefore the Party System itself)
🔮 The future
Now you can get the idea on how big and cool this project is (specially if you play this MMORPG).
There are still some things I'd like to change and implement, such as using slash Discord commands, adding more translations, allowing users to add custom extra equipment information and more.
However, there's only one thing that can kill this bot: money.
Since the start, I've been paying its Heroku hosting costs with Github Education credits, and they should last for a few more month
s, however once they vanish I will not be able to keep it running anymore.
Seven dollars per month it's not that much, but our currency here in Brazil isn't in its best situation and anything evaluated in dollars are 6 times more expensive for us.
That's an extra reason to refactor this project. By making it easier to maintain, I could update its database and ask for donations.
If you would like to help a fellow developer or if you're a Corvo Astral user, please consider contributing:
Thanks for reading!
Top comments (0)