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)