In Depth Explanations¶
Here we will be looking in-depth at different aspects of BulletBot and the Installers.
This document is broken up into two parts: Installers and BulletBot Modules and Code. The "Installers" section focuses on all the important things that the installers do. It will go in-depth about how and why it does some of the things it does. The "BulletBot Modules and Code" section explains the basic working of the different parts of BulletBot (called modules). This can help you gain a basic overview of the bot.
Installers¶
As their name implies, the installers are designed for installing and setting up BulletBot. On top of this, they keep BulletBot up to date by giving users the option to download the newest release, run BulletBot in different run modes, and so on.
Important
- The installers are designed to only work on Linux based systems.
Installer Hierarchy¶
Many of the terms used throughout the guides, documentation, and scripts, are things such as "master installer", "sub-master installers", and "sub-installers". They refer to different types/groups of installers that perform specific tasks and execute/are executed by other installers.
Master Installer¶
The master installer (linux-master-installer.sh
) is used for identifying and determining whether BulletBot supports the system it's running on. After confirming that the system is supported, the master installer then executes the sub-master installer that corresponds to it's designed Linux Distribution.
Unsupported doesn't mean incompatible
Just because the master installer determines that the system is not supported, does not mean that the system is not compatible. What the master installer deems as "supported", is an Officially Supported Linux Distribution. These distributions are Linux Distros that BulletBot has been tested and are confirmed to work on. So even if a system is not "officially supported", that does not mean that it won't work on that system.
Sub-Master Installers¶
The sub-master installers (centos-rhel-installer.sh
and debian-ubuntu-installer.sh
) perform the actual installation and setting up of BulletBot. They install all required prerequisites, assist in setting up BulletBot's config file, and starting BulletBot in different run modes.
Because BulletBot is supported on several Linux Distributions that are different in many ways, two sub-master installers had to be created to account for those differences. As the names of each sub-master installer imply, centos-rhel-installer.sh
is used on CentOS and RHEL Linux Distros, while debian-ubuntu-installer.sh
is used on Debian and Ubuntu Linux Distros.
Sub-Installers¶
The sub-installers refer to all the other installers/scripts and are always executed by the sub-master installers.
BulletBot System User¶
One thing that the installers do immediately after running for the first time is to create a system user named bulletbot
, along with a home directory for that user. It is in this home directory that all of BulletBot's code is stored.
There are two main reasons for the creation of this user:
- The first and major reason is due to security. By creating
bulletbot
and having that user run services used by/for BulletBot, it is easier to track what each of them is doing. On top of that, any service ran bybulletbot
, will only have the permissions required to perform their task (A.K.A., the principle of least privilege). - The second reason is that having a home directory where all of BulletBot’s code can be stored, creates a centralized location where one can always expect it to be. This also makes it easier for the end-user, as well as us, in terms of programming.
Running BulletBot¶
BulletBot is run by a service called bulletbot.service
, which is created when the installers are executed for the first time.
Note
bulletbot.service
should never be enabled.bulletbot.service
is run by thebulletbot
user.
BulletBot has two main methods/modes of running:
Run BulletBot in the background with auto-restart¶
This method runs BulletBot in the background of your system. If the system is restarted or shutdown, BulletBot will automatically be started upon system reboot.
This run mode is dependent on two files: a service file (bullet-mongo-start.service
) and a bash script (bullet-mongo-start.sh
).
Bash Script¶
The bash script makes sure that BulletBot is started correctly. A problem we ran into was that if bulletbot.service
was enabled, BulletBot would start before the database had fully initialized. It occurred even when bulletbot.service
was told to only start after mongod.service
started. As a solution, we created this bash script.
After being executed by bullet-mongo-start.service
, the script waits to make sure that mongod.service
successfully started, then waits a little longer to give the database enough time to initialize. Once all that is done, the script will attempt to start bulletbot.service
.
On top of everything mentioned above, this script also has the capability of sending 'BulletBot Startup Status Reports'. These are sent when BulletBot is being ran in the background with auto-restart. These reports lists whether or not BulletBot was successfully started, the exit status of essential services, and the startup logs of three services that can be used to help identify errors that might have occurred during BulletBot's startup. Though please note that for this feature to work, you need to install third party mailing software. Follow this guide to help you set this feature up.
Service File¶
The purpose of the service file is to initiate the auto-restart process. It is done by having the service execute bullet-mongo-start.sh
on system reboot.
This service is the sole decider of whether or not BulletBot is run with or without auto-restart. When the service is enabled, BulletBot will run WITH auto-restart, but if disabled, it will run WITHOUT auto-restart.
Note
bullet-mongo-start.service
is NOT run by the bulletbot
user, because the service needs to run as the root user to allow bullet-mongo-start.sh
to start bulletbot.service
.
Run BulletBot in the background¶
Just like the method above, this method will start bulletbot in the background of the system, except when the system is restarted or shutdown, BulletBot will NOT be started upon system reboot.
As mentioned in the description of the service file, if bullet-mongo-start.service
is disabled, the run mode will default to this one. This applies even if you specifically started BulletBot with auto-restart.
Downloading and Updating BulletBot¶
Every time you download/update BulletBot, the installers will first archive all of BulletBot's code currently in /home/bulletbot/
, to Old_BulletBot/${date}
(${date} is the time at which BulletBot's code is archived).
Currently, the installers do not manage any of the archives it creates. This means that the number of archives it creates in Old_BulletBot
will continue to grow and increase in size. If you would like to remove old archives, you will need to manually delete them. Each are labeled with the date at which they were created (formatted as such: Wed Apr 29 23:28:10 PDT 2020), which will make it easier identifying what archives are old and which ones are new.
BulletBot Modules and Code¶
Commands Module¶
This module loads and manages all commands. Its main class is located at src/commands.ts
. Commands are stored in two different variables. One is a single array of all commands, and the other is an object structured with subcategories (strucObject
). The subcategory names in the strucObject are all lowercase, and there is a property named _categoryName
which holds the unmodified name of the subcategory.
Commands File Structure¶
The Commands module imports the commands based on their location in the commands
directory. If they are in a subdirectory, they will be loaded into a subcategory of the subdirectories name. Because of this, the file location and subdirectory names are essential. The actual name of the file holding the command isn't crucial, as the module takes the name specified in the command object.
Filters Module¶
The Filters module is build up like the Commands Module.
MStats Module¶
MStats module stands for "management statistics module", which is responsible for logging statistical data about bot usage to the database. It caches all data and saves it to the database at a certain interval (every 10 seconds). Each hour (at XX:00:01
), it creates a new hour document to save to. After a day (at 00:00:01
), it also summarizes the statistics of the last 24 hours and saves it to a day document and also adds its information to an all-time document, which is a summary of all statistical data. The hour documents of the last day will then be deleted from the database, which means the first 24 hours the stats are precise to the hour and after that only to the day. For more information about what the MStats module stores see the database documentation
PActions Module¶
The PActions module is responsible for saving time delayed tasks and then executing them. Its name stands for pending Actions
. All tasks that are scheduled with this module get saved to the main
database in the pActions
collection. This is done to ensure that the tasks still get executed when the bot randomly crashes. If nodes native function setTimeout
would have been used, there wouldn't have been a way to save this somewhere. The PActions module periodically checks the database for tasks that need to be executed. The interval between checks is defined by the pActionsInterval
(in milliseconds) in the bot-config.json
file. When a task is executed, PActions will treat the argument differently depending on the tasks action ID, which are defined in the schema.ts
file
Webhook System¶
Unlike in other bots, where creating a webhook just creates a discord webhook, BulletBot directs the webhook to its server to "catch" and then manually sends a message in the channel. This is done so unmentionable Mentions can be used. The bot has one port dedicated to catching webhooks from all services (currently only YouTube). Because each service has it's own data structure when returning webhook data, each service has a custom catcher that listens on a different path. The catcher.ts
file only is responsible for creating an express server and getting all catchers for all services.
YouTube Webhooks¶
For YouTube webhooks, the bot uses the PubSubHubbub protocol and the hub provided by Google. It only subscribes to every channel once, so if different servers have webhooks for the same channel, the bot will only subscribe the first time.
Command Cache¶
Some commands require the user to reply with more information (?!abc
as an example). To do this, BulletBot uses something called command caches. This allows a command to temporarily store data the user previously provided and also makes the bot send the reply message which doesn't have the prefix with the command to the specific command. For this to also work in DMs, the cache only stores the channel and the user ID, not the server ID. Then each time the bot receives a message, it checks if there is a command cache for that user and channel. If there is one, it will call the command as it normally would but also passes the command cache as a parameter. What the command does with that depends on the command. To check how the command cache document is build up check out the database documentation.
Rank/Permission System¶
BulletBot uses a very common rank system where you can add users or roles to a list of a certain rank. There are the following ranks:
- Bot Master
- Admin
- Mod
- Immune
- Member
By default, every non-admin member is a Member
and only members with admin permissions have the Admin
rank (without being in the Admin
list). In addition to the normal Admin
and Mod
ranks there is also the Immune
rank which can exclude a user from currently non-existent auto-moderation and Bot Master
which can only have users in its list and is defined in the botMasters
property of the bot-config.json
file. Users in that list have the the highest permission level in every server.