So 42 just reached her 5,000th server, which is crazy to me!
She and I have been through a lot together, but when I first created her, I never expected her to reach this many people. As of today, she has 5000 servers, and knows 563,000 people! Another nearby milestone is that she’s almost at 2 million command calls, which is just insane to me.
It’s been a long journey, but maybe 10,000 wont be quite as far away.
So, I suppose I should talk about how all this started then.
Back in late 2015, I used to be a very active member of the Reddit Splatoon community, specifically, I was one of the first 5 people to join the newly made Discord server. Along side us, was a user named Danny.
Danny plays a very important role in this story, as he was one of the first people to try and reverse engineer discord, and long story short, he succeeded, and
discord.py was created. Using his new library, he created a bot called R. Danny, who at the time was primarily a Splatoon helper bot. Here is where 42’s conception was.
Back then, R. Danny didn’t exactly have the most reliable up-time, with a lot of significant outages and other issues, so I decided here is where I would start my journey. I pulled together my prior Python knowledge and after some experimentation and prototyping, 42v2 was born. At this time, she existed completely in R. Danny’s shadow, stepping in to take over when she was needed. Things mostly remained this way, until some people started to see potential in 42. From here, I allowed them to add her to a few choice servers, namely “Swood Dechscord”, which is a JonTron community, and “/r/Undertale Discord” which is for Undertale, if that wasn’t clear already. They liked her re-implementation of the “tag” system, which is like a bookmark directory idea that also took inspiration from R. Danny
Now that I think back on it, I feel like expansion was always my plan with 42, since right from the beginning, my re-implementations of R. Danny’s commands were built with a more… server by server idea in mind. I can let each server use 42 however they want, and it wont affect other servers. Even though at this point, my tag system was the same as R. Danny’s, as in, all the tags were global, and could be used by anyone, I did one specific thing different: I remembered what server each tag belonged to.
Jump to very early 2016. R. Danny has a much improved uptime, leading to 42’s role on the Splatoon server being made a bit redundant, so with 42 now being on 3 large servers, as well as a few smaller ones, I decided I would start to push towards a new 42. One designed to be generic instead of just about Splatoon. I started work on 42v3. This is where a lot of new and more unique and creative features started turning up, though I was kind of the innovative force on that one since a lot of what v3 did is also in a lot of new bots that were sprouting up at this time.
I should make a small note at this point: All of 42’s data was being handled via JSON format files. This will be important later.
By now, 42 was growing at a steady pace joining new servers, meeting new people, accumulating more tags, I was sat at the sidelines watching my pride and joy making people’s experience on Discord a little bit better. Occasionally, I’d get a message from one of 42’s users asking me if she had a specific feature, or asking me to implement a specific feature, and dutifully, I obliged, slowly increasing 42’s feature set, command by command, until after a couple months, it started being unsustainable.
You see… Discord updated, and all the bots that were using the
discord.py/master branch broke simultaniously. Danny pushed a hotfix to get the branch working again, but it became very clear that this was not a road I wanted to be stuck on. With that reality check, I started work on 42v4, with a brand new library version bump onto the
async branch. This was exciting (and also a little difficult) for me, because this was my first steps into asynchronous programming, which opened up a huge amount of things that I could do, lots of new ideas for long running commands and with the brand new
wait_for_message function, I could actually do lots of interactive stuff too! Looking back on my progress, having a time without interactivity must have been such a huge hindrance.
Interestingly, the framework I wrote for 42v4 is still used almost in its entirety to this date, sure its not perfect, but for what I need, it worked flawlessly. The idea behind the new design is very simple: Every command separate. New commands didn’t need to care what was going on with the rest of the bot, I just needed to add one extra line to tell the bot that a new command existed, and the framework would handle everything else for me, (As made obvious by the fact that despite working on v4 up until early 2017, the last edit to her main file was made in March 2016.)
This is where I should take a sidetrack to talk about a user named Jagrosh and their bot Spectra (formerly Jagbot.) You see, when I made the push to v4, I did a lot of things to make 42 stand out from other bots, specifically in the tags department. I added a lot of things that made 42 seem like the best choice, such as allowing for swift and easy transferring of tags between users, marking tags as “NSFW” (now known as “spoiler”) to prevent them from being shown in the random function, and an easy ability to copy tags between servers (since at this point, I had enforced that tags only exist for the server that created them.)
When I first heard of Spectra, it was on the Splatoon server, the same one that inspired 42, and Jagrosh had written a tag system with features suspiciously similar to 42’s, however he made one very interesting addition: he created a way to have dynamic elements in the tags. Things like substituting in the name of the caller, or the channel you’re in, simple stuff. I asked him if I could borrow the idea, and he said sure. Since Spectra is built in Java, I assume this must have been a much harder task for him than it was for me, but I managed to make it work simply using Python’s native
format function. About 30 minutes of work later, I had what would be the basis of 42’s bespoke scripting language, which will soon come to be known as “yna.” Funnily enough though, since it was quite simple to add these kinds of things, I added quite a bit more than was in Spectra, at least in the simple substitution department.
I’m not entirely sure what both of our motivations were at the time, but I chose to see it more as a friendly rivalry and building off of each other’s ideas, but he added a few extra neat features, presumably (initially) designed to make 2 specific function tags work: “shipscore” which picks 2 random users, and then rolls a number between 0 and 99; and “memegen” which generates a URL based on a user’s inputs, so he had taken the idea of tag arguments, and added data manipulation functions. I refactored to make scripting work and wrote up functions for random choice, random number, string replaces, uppercase and lowercase functions, and flow control, specifically IF statements.
This is the part where Spectra and Jagrosh kind of fade out of memory, though I do wonder what became of them. On the other hand 42’s scripting kept on improving a small amount, which in turn actually drew more people towards wanting to use 42, which in turn lead to more tags, and oh would you look at that data volume.
Remember near the start where I said 42 was using JSON to store everything? Well at this point, she has about 12000 tags. Not a devastating amount… Actually… It was a devastating amount. With how she was written, every time someone makes a call to create or modify a tag, 42 attempted to dump the tag list back to JSON, which started causing little lag spikes, and later on, larger lag spikes. Freezes of upwards of 6 to 8 seconds eventually started happening as the dataset got bigger. Eventually I would shift to using SQLite databases for storing tags, but for now I needed a fix and fast. It was a very duct-tape fix and it made 42 not 100% reliable for a few weeks, but what ended up happening was that she would keep track of any changes in RAM, and then every 10 minutes, she’d perform the JSON dump to save everything. An unfortunate accident here by the way is how I learned about what atomic saving is and why it is so important (thank the lord for backups. Even a single mistake is enough justification for all the backups.)
I’m actually going to take a small deviation here to explain 42’s growth model. She is not published on any of the large public bot listing sites, Carbonitex, Discord Bots, DiscordServerList, etc. Her audience is entirely word of mouth, and she spreads from server to server based on mutual members, though occasionally I’ll see a post on the /r/DiscordApp subreddit asking if anyone knows of a bot to do XYZ. If 42 can do a thing, I’ll let them know, provide information on who 42 is, what she does, and how to do what they want, and hopefully she’ll have gained a new follower, but exactly twice, I’ve seen feature suggestions on the subreddit that no other bot has: Specifically, reassigning a user’s roles when they leave and rejoin, and being able to perform a command regularly without user input (to clear channels.) What I decided to do for those was simply write up a command in 42 to do what they wanted, then ping them with the results and ask if it worked how they wanted, or if they wanted me to tweak it. 42’s development process has been half creative liberty, and half changing my implementation to match what the specific user requesting a feature wants out of that feature.
Anyway, back onto the story. My next big task is to make tags use SQLite. The code here is already messy, so a big rewrite and update seems to be the best cours– “Error connecting to Discord: Too many servers. Please connect using a shard.”
So what just happened: 42 hit 2000 servers, and Discord doesn’t like that, so it is preventing 42 from connecting completely. Now, what sharding means for those interested is that the bot is run as multiple processes each connecting to Discord independently and servicing a different subset of the servers. What this meant for me though, is that with how I have been handling data, 42 is no longer sustainable at all, which was a devastating blow, but fear not, research is here to save the day. First thing’s first though, I need to get 42 back online ASAP.
I hate the immediate solution I came up with, but it was the only fix for 42 in her current state. It was clear now that v4 was going to be killed off and that I could do nothing about it, but what I could do, was prolong the inevitable to buy some time to make changes. I logged 42 in on Shard 0/1, which means that for the time being, she was only aware of half her servers, and only half her servers could use the commands. Whilst logged on in this reduced state, I simply asked 42 to go through her servers, and if any servers had less than 3 human users, then she was to leave. After doing this for each shard, 42 went down to about 1500 servers.
Enter 42v5 or as she was more well known at the time: Beta 42. This is 42’s last major rewrite, and this one was designed with 2 tasks in mind: 1. move tags into a database. 2. ensure that multiple processes can use all of 42’s data without significant issues. I made a start making a few tweaks to her framework, adding some new features to the framework, and then porting and rewriting commands. This was the longest stage of 42’s lifespan by far, as this was when I really felt confident in python, and as such, where my code started looking less like overcooked spaghetti.
After learning how to use SQLite, (thankfully, I have a lot of SQL knowledge from my 6th form days,) I got tags working again, I ported over the data on v4, and decided that to buy more time, I’d open up Beta 42 to the public, which helped out my development a lot, since I got a lot of instant feedback on newly ported features, as well as feedback on how to improve the features. about 3/4 of the way into my development of v5 though, a miracle happened.
discord.py/rewrite branch released and it brought with it one incredible feature:
AutoShardedClient! All of the trouble I was having getting data to work properly between multiple instances of the bot, so having a simple way to shard 42 without all of the headache was such a relief. I buckled down and started converting the entirety of v5 into the rewrite branch, bringing her up to version 5.3, and a bit of testing later, I decided she was ready: She could do everything v4 could do and more, and she can do it without hanging every 10 minutes to save her tags.
So v5.3 was ready to be put on 42, but I still have a small issue: I have 2 bots with conflicting data sets, and I need to discontinue one of them. What I decided to do was start a set of polls on my website to see what people thought would be the best way to merge the two bots, including questions such as what to do when the same tag exists on both bots, or what to do to user profiles. After gathering results, I shut down both bots, and had Beta 42 send a special goodbye message to her servers saying to get the real 42 instead, and started merging the data. It took me about 2 hours to download both bot’s data, merge them together, and upload the new code onto my server and verify that it is working. It was such a long time ago now since this whole thing happened, but I suppose I’m glad it did. It made me think fast to solve a very immediate problem.
Anyways, since then, a few extra things have happened. Other than the routine fixing bugs and unforeseen exploits that are brought to my attention, I’ve built a lot of new features into her. Interestingly, she’s been through some other updates whilst in version 5, the most notable being:
v5.2, or the Tagsv5 update. I refactored tags (which is now a 60 subcommand command) into its own entire module, as well as adding some new fancy config options that a few servers were asking for
v5.3, the aformentioned Rewrite update. I converted her to using the rewrite branch of discord.py to access the
v5.5, the Patreon update. I added a lot of new exclusive features that people could access by pledging to me on Patreon.
and lastly, I’m working on v5.6, the Database update, where I’m going to be refactoring how databases are handled entirely inside 42 and to help set up some framework to streamline converting other commands to databases.
And that is most of the history of 42, in her journey from a speck on the Splatoon server into the giant beast she is. I may have a few details mixed up or slightly out of order, since time is not something my memory likes coping with, but at the very least, the facts, stories, hardships and everything else there is accurate.
One last achievement I am extremely proud of by the way. I had reached out to Mary Cagle, the author of Kiwi Blitz which 42 is from, to ask for her blessing, but was met with an offhand (but affirmative) response, but back in March, she decided to join a fan server for her other comic Sleepless Domain. Hearing the news, I reached out again to her and the admins, and well, with how much 42 is liked there, I think it doesn’t need to be said that I have full permission to use 42’s name and likeness.