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

  1. Navigate to Discord Developers

  2. Create a new application

  3. Go to the Bot tab

  1. On the Privileged Gateway Intents enable all the intents

  2. Enable PRESENCE INTENT

  3. Enable SERVER MEMBERS INTENT

  4. Enable MESSAGE CONTENT INTENT

  1. Reset the bot token

  2. Copy it and keep it in a safe place, because you will only see it once.

Inviting the bot to a server

  1. Navigate to Discord Developers

  2. Select you recently created Application

  3. Go now to the OAuth2 tab

  4. Select the URL Generator

  5. On SCOPES, select “bot” and on BOT PERMISSIONS, select “Administrator”

  6. Navigate to the generate URL

  7. 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)

  8. Once the server is selected, authorize the bot to get Administrator privileges.

  9. 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:

  1. Create a .env file
    1. On the same path as your main.py file create a .env file

    2. Inside 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.

  2. Export the variable to your shell environment
    1. 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

similar(a, b)

Based in graphics, find the similarity between 2 strings.

a
Type:

str

Required:

True

b
Type:

str

Required:

True

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 ping_command(ctx)

Handles the !ping command and returns a pong message.

ctx

The context of the received message.

Type:

obj

Required:

True

async start_command(ctx, *, query=None)

Handles the !start command and starts the exercise.

ctx

The context of the received message.

Type:

obj

Required:

True

query

The query of the message.

Type:

obj

Required:

False

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 if private is set to True

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

async create_voice_if_not_exists(category, name)

Create a voice 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

async create_gm_channels(guild)

Creates the Game Masters section, text channels and voice channel.

guild

The guild identifier.

Type:

int

Required:

True