Source code for chatom.discord.config

"""Discord backend configuration.

This module provides configuration classes for the Discord backend.
"""

from pathlib import Path

from pydantic import Field, SecretStr, field_validator

from ..backend import BackendConfig

__all__ = ("DiscordConfig",)


[docs] class DiscordConfig(BackendConfig): """Configuration for Discord backend. This configuration is used to connect to Discord using the discord.py library. You need a bot token from the Discord Developer Portal. Attributes: bot_token: Discord bot token (can be a file path). application_id: Discord application ID. guild_id: Default guild/server ID (optional). intents: Discord gateway intents to request. command_prefix: Prefix for bot commands (if using commands extension). Example: >>> config = DiscordConfig( ... bot_token="your-bot-token", ... application_id="123456789", ... intents=["guilds", "messages", "message_content"], ... ) >>> backend = DiscordBackend(config=config) """ token: str | SecretStr = Field( default=SecretStr(""), description="Discord bot token from Developer Portal (can be a file path).", ) application_id: str = Field( default="", description="Discord application ID.", ) guild_id: str = Field( default="", description="Default guild/server ID (optional).", ) intents: list = Field( default_factory=lambda: ["guilds", "messages"], description="Discord gateway intents to request.", ) command_prefix: str = Field( default="!", description="Prefix for bot commands.", ) shard_id: int | None = Field( default=None, description="Shard ID for sharded bots.", ) shard_count: int | None = Field( default=None, description="Total number of shards.", ) @field_validator("token", mode="before") @classmethod def validate_token(cls, v): """Validate and load bot token, supporting file paths.""" if v is None or v == "": return SecretStr("") # Handle SecretStr input if isinstance(v, SecretStr): v = v.get_secret_value() # Check for empty string after extracting from SecretStr if not v: return SecretStr("") # Check if it's a file path (but not a directory or special path) path = Path(v) if path.exists() and path.is_file(): v = path.read_text().strip() # Accept any non-empty token (don't validate length for flexibility in testing) if v: return SecretStr(v) raise ValueError("Token must be a valid Discord bot token or a file path containing one") @property def bot_token_str(self) -> str: """Get the bot token as a plain string. Returns: The bot token string. """ return self.token.get_secret_value() if isinstance(self.token, SecretStr) else self.token @property def has_token(self) -> bool: """Check if a bot token is configured. Returns: True if a bot token is set. """ return bool(self.token.get_secret_value() if isinstance(self.token, SecretStr) else self.token)