Implement GuardDen Discord moderation bot

Features:
- Core moderation: warn, kick, ban, timeout, strike system
- Automod: banned words filter, scam detection, anti-spam, link filtering
- AI moderation: Claude/OpenAI integration, NSFW detection, phishing analysis
- Verification system: button, captcha, math, emoji challenges
- Rate limiting system with configurable scopes
- Event logging: joins, leaves, message edits/deletes, voice activity
- Per-guild configuration with caching
- Docker deployment support

Bug fixes applied:
- Fixed await on session.delete() in guild_config.py
- Fixed memory leak in AI moderation message tracking (use deque)
- Added error handling to bot shutdown
- Added error handling to timeout command
- Removed unused Literal import
- Added prefix validation
- Added image analysis limit (3 per message)
- Fixed test mock for SQLAlchemy model
This commit is contained in:
2026-01-16 19:27:48 +01:00
parent ffe42b6d51
commit 4e16777f25
45 changed files with 5802 additions and 1 deletions

50
src/guardden/config.py Normal file
View File

@@ -0,0 +1,50 @@
"""Configuration management for GuardDen."""
from pathlib import Path
from typing import Literal
from pydantic import Field, SecretStr
from pydantic_settings import BaseSettings, SettingsConfigDict
class Settings(BaseSettings):
"""Application settings loaded from environment variables."""
model_config = SettingsConfigDict(
env_file=".env",
env_file_encoding="utf-8",
case_sensitive=False,
env_prefix="GUARDDEN_",
)
# Discord settings
discord_token: SecretStr = Field(..., description="Discord bot token")
discord_prefix: str = Field(default="!", description="Default command prefix")
# Database settings
database_url: SecretStr = Field(
default=SecretStr("postgresql://guardden:guardden@localhost:5432/guardden"),
description="PostgreSQL connection URL",
)
database_pool_min: int = Field(default=5, description="Minimum database pool size")
database_pool_max: int = Field(default=20, description="Maximum database pool size")
# AI settings (optional)
ai_provider: Literal["anthropic", "openai", "none"] = Field(
default="none", description="AI provider for content moderation"
)
anthropic_api_key: SecretStr | None = Field(default=None, description="Anthropic API key")
openai_api_key: SecretStr | None = Field(default=None, description="OpenAI API key")
# Logging
log_level: Literal["DEBUG", "INFO", "WARNING", "ERROR"] = Field(
default="INFO", description="Logging level"
)
# Paths
data_dir: Path = Field(default=Path("data"), description="Data directory for persistent files")
def get_settings() -> Settings:
"""Get application settings instance."""
return Settings()