XML is dead; long live XML! Or, rather…let’s not. XML was always a silly format that mirrored HTML too closely and XML parsing was such a pain in the ass, so that while it was the king of portable formats for quite some time, it’s rapidly being dethroned in favor of JSON.
JSON is not complicated. It is structured in the form of key: value and each element is separated by a comma. You can nest data (as you see above in that “lobby” has three child elements) which is super-useful for constructing a relational hierarchy. And because JSON is basically a string, it’s portable. Serialize it, and you can move it pretty much anywhere.
Discord.js offers some suggestions on persisting data such as ORM (object relational mapping) solutions and databases, but I’m kicking my way through learning Discord.js and the semantics of Discord bot building right now and don’t have time or inclination to branch my attention into a light-weight data storage option. So I’m relying on plain old JSON, read and written to my hosting solution via Node.js’ “fs” (“file system”) library.
Let’s get this out of the way: I realize that reading and writing files is kind of a minefield on account of file access sorcery and security concerns. If someone gets access to the file system where the bot is running they could easily open the file and read the contents, so maybe later on I will look into a small-scale database or layer some encryption on top of my config files. Beyond security, though, simultaneous attempts to read and write by multiple people is where things get into trouble, so in an attempt to alleviate that I’m putting everything into two modular methods: LoadSettings and SaveSettings.
When the bot starts it’ll call Init() which in turn calls LoadSettings internally. This reads the JSON file specified at the path fileloc and puts the JSON string into the Settings variable. This variable is accessible to the main program:
This instance of settings is passed around where it’s needed. If you refer to the previous post you might notice that once the admin uses the !setlobby command with the channel and role parameters, those values are written to the settings variable that was passed into the method. As a result, the JSON string in memory is updated with the important info we need to secure the lobby: channel ID (how Discord prefers for the channel to be referenced), channel name, and role name.
Now, we want to make sure that these changes are saved so if the bot needs to be rebooted the admin doesn’t have to set everything again. The last part of the Init() method, then, sets up a timer that reads from the settings and calls the SaveSettings() method internally each timer interval (currently set to 60 seconds).
SaveSettings() takes the JSON and saves it back to the file on disk, and notifies the bot console that the save has taken place. We can’t notify the user because we don’t have a reference to the server here; just the local file system.
Having these two methods that are called A) on bot startup and B) every 60 seconds means that there’s only one place where the file is read, and one place where the file is written so that we don’t have multiple users trying to update the bot or read from disk at the same time. The settings will stay in memory as they are updated, and the current state of the JSON settings are flushed to disk periodically, so even in the event of a crash any modifications will only be 60 seconds behind. It’s a simple (possibly too simple) implementation, but it provides the persistence that I need to be able to press ahead with commands that require information to be on hand (and that I don’t have to set up every single time I test the system).