Source code for src.discord_bot
"""
This module contains the discord bot implementation with definitions for the bot and its commands.
The bot is implemented using the discord.py library and provides a simple command to test the bot.
"""
import discord
from discord import app_commands
from discord.ext import commands
from .configuration import Configuration
from .discord_permissions import check_permissions_historian
from .game import (
create_game,
keep_telling_schedule,
setup_game,
reset_game,
)
from .character import select_character, show_character
from .file_utils import import_data
from .genre import deactivate_genre, activate_genre
[docs]
class DiscordBot:
"""
DiscordBot class to create a discord bot with the given configuration. This is
necessary because of a own implementation with user configuration and
pydantic validation.
"""
def __init__(self, config: Configuration):
self.config = config
intents = discord.Intents.default()
intents.members = True
intents.message_content = True
# intents.reactions = True
self.bot = commands.Bot(command_prefix="!", intents=intents)
self.config.dc_bot = self.bot
@self.bot.event
async def on_ready():
await self.on_ready()
self.register_commands()
[docs]
async def start(self):
"""
Function to start the bot with the given token from the configuration.
This function is called in the main function to start the bot.
"""
await self.bot.start(self.config.env.dc.bot_token)
[docs]
async def on_ready(self):
"""
Event function to print a message when the bot is online.
"""
self.config.logger.info(f"{self.bot.user} ist online")
synced = await self.bot.tree.sync()
self.config.logger.info(f"Slash Commands synchronisiert: {len(synced)}")
await self.bot.change_presence(
status=discord.Status.online,
activity=discord.Activity(
type=discord.ActivityType.listening, name="storyteller"
),
)
[docs]
def register_commands(self):
"""
Function to register the commands for the bot. This function is called in the
constructor to register the commands.
"""
async def wrapped_keep_telling(interaction: discord.Interaction):
self.config.logger.trace(
f"User: {interaction.user.id} execute command to continue telling a story."
)
await keep_telling_schedule(interaction, self.config)
async def wrapped_import_data(interaction: discord.Interaction):
self.config.logger.trace(
f"User: {interaction.user.id} execute command import game data."
)
if not await check_permissions_historian(self.config, interaction):
return
await import_data(interaction, self.config)
self.bot.tree.command(
name="keep_telling",
description="Continue the story of a game.",
)(wrapped_keep_telling)
self.bot.tree.command(
name="import_data",
description="Import game data from a YAML file.",
)(wrapped_import_data)
game_group = app_commands.Group(name="game", description="Game administration")
async def wrapped_create_game(interaction: discord.Interaction):
self.config.logger.trace(
f"User: {interaction.user.id} execute command for game creation."
)
if not await check_permissions_historian(self.config, interaction):
return
await create_game(interaction, self.config)
async def wrapped_setup_game(interaction: discord.Interaction):
self.config.logger.trace(
f"User: {interaction.user.id} execute command for setup game."
)
if not await check_permissions_historian(self.config, interaction):
return
await setup_game(interaction, self.config)
async def wrapped_reset_game(interaction: discord.Interaction):
self.config.logger.trace(
f"User: {interaction.user.id} execute command for reset game."
)
if not await check_permissions_historian(self.config, interaction):
return
await reset_game(interaction, self.config)
game_group.command(
name="create", description="Create a new game and set the parameters."
)(wrapped_create_game)
game_group.command(
name="setup",
description="Switch game state to specific status like running, paused, etc.",
)(wrapped_setup_game)
game_group.command(
name="reset", description="Restart a Tale and create new start prompt."
)(wrapped_reset_game)
self.bot.tree.add_command(game_group)
genre_group = app_commands.Group(
name="genre", description="Genre administration"
)
async def wrapped_genre_deactivate(interaction: discord.Interaction):
self.config.logger.trace(
f"User: {interaction.user.id} execute sub-command for genre deactivation."
)
if not await check_permissions_historian(self.config, interaction):
return
await deactivate_genre(interaction, self.config)
async def wrapped_genre_activate(interaction: discord.Interaction):
self.config.logger.trace(
f"User: {interaction.user.id} execute sub-command for genre activation."
)
if not await check_permissions_historian(self.config, interaction):
return
await activate_genre(interaction, self.config)
genre_group.command(name="deactivate", description="Deactivate genre")(
wrapped_genre_deactivate
)
genre_group.command(name="activate", description="Activate genre")(
wrapped_genre_activate
)
self.bot.tree.add_command(genre_group)
character_group = app_commands.Group(
name="character", description="Character administration"
)
async def wrapped_character_select(interaction: discord.Interaction):
self.config.logger.trace(
f"User: {interaction.user.id} execute sub-command for character selection."
)
await select_character(interaction, self.config)
async def wrapped_character_show(interaction: discord.Interaction):
self.config.logger.trace(
f"User: {interaction.user.id} execute sub-command to show character."
)
await show_character(interaction, self.config)
character_group.command(
name="select", description="Select a character for a game."
)(wrapped_character_select)
character_group.command(
name="show",
description="Show available character and select one with background and traits.",
)(wrapped_character_show)
self.bot.tree.add_command(character_group)