Skip to content

Commit

Permalink
Refactoring and simplifying logic
Browse files Browse the repository at this point in the history
- Enabled the bot to run standalone, with an Atlas Database, or with a Local Database
- Split event handlers into their own folder
- Created helper scripts for environment variables

Signed-off-by: Diana <[email protected]>
  • Loading branch information
xN4P4LM committed Feb 12, 2024
1 parent d2ffd7c commit e49b75e
Show file tree
Hide file tree
Showing 18 changed files with 659 additions and 315 deletions.
27 changes: 27 additions & 0 deletions .dockerignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
**/__pycache__
**/.venv
**/.classpath
**/.dockerignore
**/.env
**/.git
**/.gitignore
**/.project
**/.settings
**/.toolstarget
**/.vs
**/.vscode
**/*.*proj.user
**/*.dbmdl
**/*.jfm
**/bin
**/charts
**/docker-compose*
**/compose*
**/Dockerfile*
**/node_modules
**/npm-debug.log
**/obj
**/secrets.dev.yaml
**/values.dev.yaml
LICENSE
README.md
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,9 @@ cloudflare.ini
# ignore shell configs
*.config

# ignore sensitve shell scripts
*.shs

### OS generated files ###

# mac files
Expand Down
95 changes: 18 additions & 77 deletions bot.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,123 +2,64 @@
This is the main file for the bot.
"""

import asyncio
import logging
from os.path import expanduser
import discord
from discord.ext import commands
from helpers.database.connection import getDbConnection
from helpers.get_file import getFile
from helpers.database.connection import DatabaseConnection
from helpers.get_ssh_key import getPubKey
from helpers.logs import Logger
from helpers.env import getEnvVar
from helpers.terminal_colors import TerminalColors
from helpers.guild.add_guilds import addGuild
from helpers.help_command import getHelpCommand
from helpers.core_cogs import loadCoreCogs
from event_handlers.guilds import setupGuildEvents
from event_handlers.bot import setupBotEvents


def main():
"""
Main entry point for the bot.
"""
# Set up overall logging
Logger.setup_logging(int(getEnvVar("DISCORD_BOT_LOG_LEVEL")))
Logger.setup_logging(int(getEnvVar("DISCORD_BOT_LOG_LEVEL", "20")))

# Set up the logger
startup_logging = logging.getLogger("discord.bot.startup")

# check if the bot should use a database
use_database = getEnvVar("DISCORD_USE_DATABASE")

# Create a new bot instance
bot = commands.Bot(
command_prefix=getEnvVar("DISCORD_BOT_COMMAND_PREFIX"),
command_prefix=getEnvVar("DISCORD_BOT_COMMAND_PREFIX", "."),
intents=discord.Intents.all(),
description=getEnvVar("DISCORD_BOT_DESCRIPTION"),
owner_id=int(getEnvVar("DISCORD_BOT_OWNER_ID")),
case_insensitive=True,
help_command=getHelpCommand(),
)

if use_database == "True":
# Test the database connection
db_conn = getDbConnection()
if db_conn is not None:
startup_logging.info("Connected to the database.")
db_conn.close()

@bot.event
async def on_guild_join(guild): # pylint: disable=invalid-name
"""
Event: Bot joins a guild
This event is called when the bot joins a new guild and
adds the guild to the database.
"""
if use_database == "True":
# Add the guild to the database
db_conn = getDbConnection()
if db_conn is not None:
addGuild(db_conn, guild)
db_conn.close()

@bot.event
async def on_ready(): # pylint: disable=invalid-name
"""
Event: Bot is ready
This event is called when the bot is ready to be used and
prints information about the bot.
"""

if bot.user is not None:
startup_logging.info("Logged in as %s", bot.user.name)

# Print the join URL
startup_logging.info(
"Invite URL: \
%shttps://discord.com/api/oauth2/authorize?\
client_id=%s&permissions=8&scope=bot%s",
TerminalColors.GREEN_BOLD,
bot.user.id,
TerminalColors.RESET_COLOR
)

# list all servers the bot is connected to
if bot.user is not None:
startup_logging.info(
"%s%s%s is connected to %s%s guilds %s",
TerminalColors.GREEN_BOLD,
bot.user.name,
TerminalColors.RESET_COLOR,
TerminalColors.GREEN_BOLD,
len(bot.guilds),
TerminalColors.RESET_COLOR
)

startup_logging.info("Loading core cogs...")
await loadCoreCogs(bot, "core")

# check if using root or user ssh key if not set default to root
use_user = getEnvVar("DISCORD_USE_USER_SSH") or "False"

if use_user == "True":
ssh_file = expanduser("~") + "/.ssh/id_ed25519.pub"
else:
ssh_file = "/root/.ssh/id_ed25519.pub"
if getEnvVar("DISCORD_USE_DATABASE", "False") == "True":
database_connection: DatabaseConnection = DatabaseConnection()

# Read public ssh key from file and log it
startup_logging.info(
"Public SSH key: %s%s%s",
TerminalColors.GREEN_BOLD,
getFile(ssh_file).strip("\n"),
TerminalColors.RESET_COLOR
getPubKey(),
TerminalColors.RESET_COLOR,
)

# instantiate the bot events
asyncio.run(setupBotEvents(bot))

# Run the bot
bot.run(
getEnvVar("DISCORD_BOT_TOKEN"),
log_handler=None,
)

# Close the database connection before exiting
database_connection.close_connection()


# Run the main function
if __name__ == "__main__":
Expand Down
File renamed without changes.
60 changes: 60 additions & 0 deletions event_handlers/bot.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
"""
This file contains the operations to setup a new guild
in the database, and is used by the bot when a new guild is added.
"""

import logging
from discord.ext import commands
from event_handlers.guilds import addMissingGuilds, setupGuildEvents
from helpers.env import getEnvVar
from helpers.terminal_colors import TerminalColors
from helpers.core_cogs import loadCoreCogs


logger = logging.getLogger("discord.bot.events")


async def setupBotEvents(bot: commands.Bot):
"""
This function sets up the bot events
"""

@bot.event
async def on_ready(): # pylint: disable=invalid-name
"""
Event: Bot is ready
This event is called when the bot is ready to be used and
prints information about the bot.
"""

if bot.user is not None:

# Print the join URL
logger.info(
"Invite URL: \
%shttps://discord.com/api/oauth2/authorize?\
client_id=%s&permissions=8&scope=bot%s",
TerminalColors.GREEN_BOLD,
bot.user.id,
TerminalColors.RESET_COLOR,
)

logger.info(
"%s%s%s is connected to %s%s guilds %s",
TerminalColors.GREEN_BOLD,
bot.user.name,
TerminalColors.RESET_COLOR,
TerminalColors.GREEN_BOLD,
len(bot.guilds),
TerminalColors.RESET_COLOR,
)

logger.info("Loading core cogs...")
await loadCoreCogs(bot, "core")

if getEnvVar("DISCORD_USE_DATABASE", "False") == "True":
await setupGuildEvents(bot)
addMissingGuilds(bot)

logger.info("Bot is ready")
100 changes: 100 additions & 0 deletions event_handlers/guilds.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
"""
This file contains the operations to setup a new guild
in the database, and is used by the bot when a new guild is added.
"""

import logging
from pymongo import MongoClient
from discord import Guild
from discord.ext import commands
from helpers.database.connection import DatabaseConnection
from helpers.env import getEnvVar

logger = logging.getLogger("discord.guilds")


async def setupGuildEvents(bot: commands.Bot):
"""
This function sets up the bot events for the guildis
"""

# get the database connection
db_connection = DatabaseConnection().get_connection()

@bot.event
async def on_guild_join(guild: Guild): # pylint: disable=invalid-name
"""
Add the guild to the database when the bot joins a new guild.
"""
if getEnvVar("DISCORD_USE_DATABASE", "False") == "True":
# Add the guild to the database
addGuild(db_connection, guild)

@bot.event
async def on_guild_remove(guild: Guild): # pylint: disable=invalid-name
"""
Remove the guild from the database when the bot leaves a guild.
"""
if getEnvVar("DISCORD_USE_DATABASE", "False") == "True":
# Remove the guild to the database
removeGuild(db_connection, guild)


def addGuild(db_connection: MongoClient, guild: Guild) -> bool:
"""
Add a new guild to the database.
"""
# create the database
guild_collection = db_connection["guilds"].create_collection(str(guild.id))

if guild_collection.name == str(guild.id):
logger.info(
"Database %s for guild %s created successfully", guild.id, guild.name
)
return True

logger.error(
"You shouldn't see this message, check that guild %s was created successfully",
guild.name,
)

return False


def removeGuild(db_connection: MongoClient, guild: Guild) -> bool:
"""
Remove a guild from the database.
"""

# Connect to the guilds database
db_connection["guilds"].drop_collection(str(guild.id))

# check if the database was deleted
if str(guild.id) not in db_connection["guilds"].list_collection_names():
logger.info(
"Database %s for guild %s removed successfully", guild.id, guild.name
)
return True

logger.error(
"You shouldn't see this message, check that guild %s was removed successfully",
guild.name,
)

return False


def addMissingGuilds(bot: commands.Bot):
"""
Add the guilds that the bot is already in to the database.
"""
# get the database connection
db_connection = DatabaseConnection().get_connection()

# existing guilds in the database
guilds = db_connection["guilds"].list_collection_names()

# add the guilds to the database
for guild in bot.guilds:
if str(guild.id) not in guilds:
addGuild(db_connection, guild)
Loading

0 comments on commit e49b75e

Please sign in to comment.