-
Notifications
You must be signed in to change notification settings - Fork 17
3. Working on the Bot
- 1. Setup Python Environment
- 2. Setup and run Wall-E
- 3. Before opening a PR
- 4. Testing on CSSS Bot Test Server
- Test Cases
- FAQs
- Variable Initialization Details
sudo apt-get install -y python3.9
curl https://bootstrap.pypa.io/get-pip.py -o get-pip.py
python3.9 get-pip.py --user
python3.9 -m pip install virtualenv --user
python3.9 -m virtualenv walle
. walle/bin/activate
https://www.python.org/downloads/release/python-3913/
python3.9 -m pip install --upgrade pip
python3.9 -m pip install virtualenv
python3.9 -m virtualenv walle
. walle/bin/activate
open to anyone to make a PR adding this section
If you encounter any errors doing the following commands, feel free to add it to the FAQs section for future reference :)
Pre-requisites: git
If you have not cloned your forked version yet
wget https://raw.githubusercontent.com/CSSS/wall_e/master/download_repo.sh
./download_repo.sh
If you have forked your version
./run_site.sh
Please follow the format below when adding a new help message so that layout is unified across all commands
@commands.command(
brief="short help message in main help embed",
help=(
'Description of command purpose.\n'
'Arguments:\n'
'---argument_1: argument_1 description\n'
'---argument_2: argument_2 description\n\n'
'Example:\n'
'.command_name "foo"\n'
'.command_name "foo" "bar"\n\n'
),
usage='foo [bar]'
)
async def command_name(self, ctx, *args):
@commands.has_any_role("role1", "role2")
async def command_name(self, ctx, *args):
OR
@commands.has_role("role1")
async def command_name(self, ctx, *args):
@commands.has_guild_permissions(administrator=True, manage_roles=True) # this does an AND
async def command_name(self, ctx, *args):
If the above examples don't provide a way for the sort of permission checking you are attempting, you can write your own logic using the below example
def user_has_perms(ctx):
return ctx.author.guild_permissions.administrator or ctx.author.guild_permissions.manage_roles
@commands.check(user_has_perms)
async def command_name(self, ctx, *args):
@app_commands.command(name="command_name", description="command description")
@app_commands.describe(argument_name="argument description")
async def function_name(self, interaction: discord.Interaction, argument_name: str):
@app_commands.checks.has_role("role1")
async def command_name(self, interaction: discord.Interaction):
OR
@app_commands.checks.has_any_role("role1", "role2")
async def command_name(self, interaction: discord.Interaction):
@app_commands.checks.has_permissions(administrator=True, manage_roles=True) # this does an AND
async def command_name(self, interaction: discord.Interaction):
If the above examples don't provide a way for the sort of permission checking you are attempting, you can write your own logic using the below example
def user_permission_check(interaction: discord.Interaction) -> bool:
return interaction.user.guild_permissions.administrator or interaction.user.guild_permissions.manage_roles
@app_commands.check(user_permission_check)
async def command_name(self, interaction: discord.Interaction):
slash commands introduced the ability to provide users with a menu of options they can choose from for a command's argument. You can see this in action with the /iam
command on the CSSS Discord guild
OR
@app_commands.autocomplete(argument_name=[
# list of app_commands.Choice items
# choice object example: app_commands.Choice(name="string that will be shown in discord, value="value passed to the command")
])
async def command_name(self, interaction: discord.Interaction, argument_name: str):
If the options you want to provide need to be pulled from discord in some way, you can extend the functionality of the autocomplete function like this:
async def argument_options(interaction: discord.Interaction, current: str) -> List[app_commands.Choice[str]]:
// create choice object using data pulled from interaction and using "current" as a filter to pass the objects through
return [choice]
@app_commands.autocomplete(argument_name=argument_options)
async def command_name(self, interaction: discord.Interaction, argument_name: str):
General layout to follow when adding a new cog class
class NewCog(commands.Cog):
def __init__(self, bot, config, bot_channel_manager):
log_info = Loggers.get_logger(logger_name="NewCog")
self.logger = log_info[0]
self.debug_log_file_absolute_path = log_info[1]
self.error_log_file_absolute_path = log_info[2]
self.logger.info("[NewCog __init__()] initializing NewCog")
self.bot = bot
self.config = config
self.guild: discord.Guild = None
self.bot_channel_manager = bot_channel_manager
@commands.Cog.listener(name="on_ready")
async def get_guild(self):
self.guild = self.bot.guilds[0]
@commands.Cog.listener(name="on_ready")
async def upload_debug_logs(self):
if self.config.get_config_value('basic_config', 'ENVIRONMENT') != 'TEST':
while self.guild is None:
await asyncio.sleep(2)
await start_file_uploading(
self.logger, self.guild, self.bot, self.config, self.debug_log_file_absolute_path, "new_cog_debug"
)
@commands.Cog.listener(name="on_ready")
async def upload_error_logs(self):
if self.config.get_config_value('basic_config', 'ENVIRONMENT') != 'TEST':
while self.guild is None:
await asyncio.sleep(2)
await start_file_uploading(
self.logger, self.guild, self.bot, self.config, self.error_log_file_absolute_path, "new_cog_error"
)
# specify any new command to listeners below
Add the cog to the .ini files in the https://github.com/CSSS/wall_e/tree/master/wall_e/utilities/config folder
If you need to add any logic to the cog class that the bot will execute as soon as the on_ready signal has been received [when its logged into the discord guild], use the below template
@commands.Cog.listener(name='on_ready')
async def function_name(self):
while self.guild is None:
await asyncio.sleep(2)
# function logic
You can see the list of discord events that a discord bot can listen for here
the above documentation was adapted from
- https://webcache.googleusercontent.com/search?q=cache:qOc8clK6CCcJ:https://gist.github.com/Ash-02014/b6f57065f394b54f43666037ade38d32&cd=1&hl=en&ct=clnk&gl=us
- https://gist.github.com/Samarthh2601/b6f57065f394b54f43666037ade38d32
git clone <fork of https://github.com/CSSS/wall_e_models.git> #do not do this in the wall_e repo
cd /path/to/walle_repo/wall_e
ln -sn /path/to/wall_e_models/wall_e_models wall_e_models
cd /path/to/wall_e_models
# git add, commit and push and changes to your forked models repo and then open a PR to https://github.com/CSSS/wall_e_models.git
- if you are done deving locally, you can run
/delete_log_channels
to delete all the log channels that wall_e created for better visibility into which cogs had which errors - If you want to wipe a channel after populating it with a lot of test messages, just run
/purge_messages <last_x_messages_to_delete>
Please submit PRs one week before they need to be merged.
Validating the code locally:
./CI/user_scripts/test_walle.sh
4. Testing on CSSS Bot Test Server
Only works with Text Commands
After you have tested on your own Discord Test Guild, create a PR to the Wall-E Repo that follows the rules for PRs before pushing your changes to Wall-E. Creating the PR will automatically load it into the CSSS Bot Test Server. the name of the channel will be pr-<PR number>
.
ERROR: could not find an available, non-overlapping IPv4 address pool among the defaults to assign to the network
resolution: If you are using a VPN, please disconnect and try again.
This may be outdated at this point, not sure anymore
How the Variable needs to be initialized [only relevant to you if you like granularized variable initializations]
Variable | Dockerized | Non-Dockerized | |||
---|---|---|---|---|---|
env variable | wall_e.env | local.ini | env variable | local.ini | |
ENVIRONMENT | X | x | |||
COMPOSE_PROJECT_NAME | X | X | |||
POSTGRES_PASSWORD | X | X | x | ||
DOCKERIZED | - | - | - | - | |
WALL_E_DB_USER | X | x | |||
WALL_E_DB_PASSWORD | X | x | |||
WALL_E_DB_DBNAME | X | x | |||
DB_ENABLED | - | - | - | - | |
HOST | - | - | x | ||
ORIGIN_IMAGE | X | ||||
BOT_LOG_CHANNEL | - | - | - | - | |
BOT_GENERAL_CHANNEL | - | - | - | - | |
DB_PORT | X | X |
X indicates that its necessary to be declared in that way
'-' indicates that the user can choose to declare it only that way