Discord
Discord was the main platform for the bot! Many new features, bug fixes and tests since the first release!
Bot
To perform an exercise based on the Discord platform, you will need to provide a Bot token. If you already have a bot created, you can skip the creation part and go straight to the provisioning part.
Bot creation
Navigate to Discord Developers
Create a new application
Go to the Bot tab
On the Privileged Gateway Intents enable all the intents
Enable PRESENCE INTENT
Enable SERVER MEMBERS INTENT
Enable MESSAGE CONTENT INTENT
Reset the bot token
Copy it and keep it in a safe place, because you will only see it once.
Inviting the bot to a server
Navigate to Discord Developers
Select you recently created Application
Go now to the OAuth2 tab
Select the URL Generator
On SCOPES, select “bot” and on BOT PERMISSIONS, select “Administrator”
Navigate to the generate URL
You will be asked for the name of the server you want to add the bot to. (You must be a user with server privileges or the server owner)
Once the server is selected, authorize the bot to get Administrator privileges.
Done!
Starting the Framework
Once you have installed in all the libraries dependent on the platform, created your bot and added it to your server, you will need to provide the token to the framework for it to work and choose the Discord platform on T3SF.start
.
Providing the token
The framework expects a bot token with the name DISCORD_TOKEN
.
You have two common options for this:
- Create a
.env
file On the same path as your
main.py
file create a.env
fileInside of it, add the variable
DISCORD_TOKEN
and your bot’s token, as following:DISCORD_TOKEN=MTEpMDU2OTc9MjQ0NDE4ODc2Mw.GP0bxK.5J2xWb3D40zSIRxYiJgGlNiTSq8OkSR4xCcvpY
Note
Note that the token will be stored and everyone with read access to the file will be able to read it.
- Create a
- Export the variable to your shell environment
Create a variable with the name
DISCORD_TOKEN
as following:export DISCORD_TOKEN=MTEpMDU2OTc9MjQ0NDE4ODc2Mw.GP0bxK.5J2xWb3D40zSIRxYiJgGlNiTSq8OkSR4xCcvpY
Initializing the framework
As explained in the Initializing T3SF page, you will need to set 3 variables inside your main.py
file.
This example is for an exercise using Discord with a GUI:
from T3SF import T3SF
import asyncio
async def main():
await T3SF.start(MSEL="MSEL_Company.json", platform="Discord", gui=True)
if __name__ == '__main__':
asyncio.run(main())
And that’s it!
Module
To maintain the modular structure of the framework, we developed a module with all the platform specific functions inside. Including the integrated bot and the functions to contact the Discord API.
The file structure is shown below:
Discord
├── bot.py
├── discord.py
└── __init__.py
Class Functions
- async SendMessage(color=None, style: str = 'simple', title: str = None, description: str = None)
Message sending controller.
- color
Parameter with the color of the embedded message.
- Type:
str
- Required:
False
- title
The title of the message.
- Type:
str
- Required:
True
- description
The description/main text of the message.
- Type:
str
- Required:
True
- async EditMessage(color=None, style: str = 'simple', title: str = None, description: str = None)
Message editing controller.
- color
Parameter with the color of the embedded message.
- Type:
str
- Required:
False
- title
The title of the message.
- Type:
str
- Required:
True
- description
The description/main text of the message.
- Type:
str
- Required:
True
- async InboxesAuto(self)
Fetches automatically all the inboxes, based in a regular expression (RegEx), notifies the Game masters about differents parts of this process.
- async InjectHandler(T3SF_instance)
This method handles the injection of a message in a specific channel using a Discord bot.
- T3SF_instance
An instance of the T3SF class.
- Type:
obj
- Required:
True
- async PollHandler(T3SF_instance)
Handles the injects with polls. Creates the poll with the two options and sends it to the player’s channel.
- T3SF_instance
An instance of the T3SF class.
- Type:
obj
- Required:
True
- async PollAnswerHandler(T3SF_instance, interaction=None)
Detects the answer in the poll sent. Modifies the poll message and notifies the game master about the selected option.
- T3SF_instance
An instance of the T3SF class.
- Type:
obj
- Required:
True
- interaction
The received interaction.
- Type:
obj
- Required:
False
Integrated bot
We integrated the bot to fully manage the platform from within the framework. The bot handles poll responses, commands and environment creation.
- class create_bot(MSEL)
This class creates the bot, will handle the commands, messages and interactions with it.
- MSEL
The location of the MSEL.
- Type:
str
- Required:
True
- define_commands()
Within this method, we will create the following command management functions
- async on_ready()
Detects when the bot is ready to receive commands and process messages.
- async on_interaction(interaction)
Detects when the bot receives an interaction (as a response to a poll).
- async start_bot()
This functions will start the bot, but also generate tasks for the async_handler_exercise create_environment_task listeners.
Note
Because the library we are using is asynchronous and the exercise can be started directly from the GUI, we need to add this “listeners” to start it without problems.
- async async_handler_exercise()
This function waits for the
start_incidents_gui
global event to be triggered and starts the exercise.
- async run_async_incidents()
This function sets the
start_incidents_gui
global event to start the exercise.
- async create_environment_task()
This function waits for the
create_env
global event to be triggered and creates the environment.
- async create_environment(server)
This function sets the
create_env
global event to create the environment.- server
The server/guild identifier.
- Type:
int
- Required:
True
- async create_role_if_not_exists(guild, name)
Create a role within the guild if it does not already exist.
- guild
The guild identifier.
- Type:
int
- Required:
True
- name
The role’s name.
- Type:
str
- Required:
True
- async create_category_if_not_exists(guild, name, private=False, role=None)
Create a category within the guild if it does not already exist.
- guild
The guild identifier.
- Type:
str
- Required:
True
- name
The category’s name.
- Type:
str
- Required:
True
- private
Determines if the category should be private and only available to a specific role
- Type:
bool
- Required:
False
- role
The role’s name.
- Type:
str
- Required:
False
|True
ifprivate
is set toTrue
- async create_channel_if_not_exists(category, name)
Create a channel within the given category if it does not already exist.
- category
The category in which the channel should be created.
- Type:
str
- Required:
True
- name
The channel’s name.
- Type:
str
- Required:
True