quick update
Some checks failed
CI/CD Pipeline / Code Quality Checks (push) Failing after 4m49s
CI/CD Pipeline / Security Scanning (push) Successful in 15s
CI/CD Pipeline / Tests (3.11) (push) Failing after 4m58s
CI/CD Pipeline / Tests (3.12) (push) Failing after 5m0s
CI/CD Pipeline / Build Docker Image (push) Has been skipped
Some checks failed
CI/CD Pipeline / Code Quality Checks (push) Failing after 4m49s
CI/CD Pipeline / Security Scanning (push) Successful in 15s
CI/CD Pipeline / Tests (3.11) (push) Failing after 4m58s
CI/CD Pipeline / Tests (3.12) (push) Failing after 5m0s
CI/CD Pipeline / Build Docker Image (push) Has been skipped
This commit is contained in:
@@ -90,7 +90,7 @@ class GuardDen(commands.Bot):
|
||||
# Initialize services
|
||||
from guardden.services.guild_config import GuildConfigService
|
||||
|
||||
self.guild_config = GuildConfigService(self.database)
|
||||
self.guild_config = GuildConfigService(self.database, settings=self.settings)
|
||||
from guardden.services.wordlist import WordlistService
|
||||
|
||||
self.wordlist_service = WordlistService(self.database, self.settings)
|
||||
|
||||
@@ -86,6 +86,43 @@ class WordlistSourceConfig(BaseModel):
|
||||
enabled: bool = True
|
||||
|
||||
|
||||
class GuildDefaults(BaseModel):
|
||||
"""Default values for new guild settings (configurable via env).
|
||||
|
||||
These values are used when creating a new guild configuration.
|
||||
Override via environment variables with GUARDDEN_GUILD_DEFAULT_ prefix.
|
||||
Example: GUARDDEN_GUILD_DEFAULT_PREFIX=? sets the default prefix to "?"
|
||||
"""
|
||||
|
||||
prefix: str = Field(default="!", min_length=1, max_length=10)
|
||||
locale: str = Field(default="en", min_length=2, max_length=10)
|
||||
automod_enabled: bool = True
|
||||
anti_spam_enabled: bool = True
|
||||
link_filter_enabled: bool = False
|
||||
message_rate_limit: int = Field(default=5, ge=1)
|
||||
message_rate_window: int = Field(default=5, ge=1)
|
||||
duplicate_threshold: int = Field(default=3, ge=1)
|
||||
mention_limit: int = Field(default=5, ge=1)
|
||||
mention_rate_limit: int = Field(default=10, ge=1)
|
||||
mention_rate_window: int = Field(default=60, ge=1)
|
||||
ai_moderation_enabled: bool = True
|
||||
ai_sensitivity: int = Field(default=80, ge=0, le=100)
|
||||
ai_confidence_threshold: float = Field(default=0.7, ge=0.0, le=1.0)
|
||||
ai_log_only: bool = False
|
||||
nsfw_detection_enabled: bool = True
|
||||
verification_enabled: bool = False
|
||||
verification_type: Literal["button", "captcha", "math", "emoji"] = "button"
|
||||
strike_actions: dict = Field(
|
||||
default_factory=lambda: {
|
||||
"1": {"action": "warn"},
|
||||
"3": {"action": "timeout", "duration": 3600},
|
||||
"5": {"action": "kick"},
|
||||
"7": {"action": "ban"},
|
||||
}
|
||||
)
|
||||
scam_allowlist: list[str] = Field(default_factory=list)
|
||||
|
||||
|
||||
class Settings(BaseSettings):
|
||||
"""Application settings loaded from environment variables."""
|
||||
|
||||
@@ -95,6 +132,7 @@ class Settings(BaseSettings):
|
||||
case_sensitive=False,
|
||||
env_prefix="GUARDDEN_",
|
||||
env_parse_none_str="",
|
||||
env_nested_delimiter="_",
|
||||
)
|
||||
|
||||
@classmethod
|
||||
@@ -164,6 +202,12 @@ class Settings(BaseSettings):
|
||||
description="Managed wordlist sources (JSON array via env overrides)",
|
||||
)
|
||||
|
||||
# Guild defaults (used when creating new guild configurations)
|
||||
guild_default: GuildDefaults = Field(
|
||||
default_factory=GuildDefaults,
|
||||
description="Default values for new guild settings",
|
||||
)
|
||||
|
||||
@field_validator("allowed_guilds", "owner_ids", mode="before")
|
||||
@classmethod
|
||||
def _validate_id_list(cls, value: Any) -> list[int]:
|
||||
|
||||
@@ -1,6 +1,9 @@
|
||||
"""Guild configuration service."""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import logging
|
||||
from typing import TYPE_CHECKING
|
||||
|
||||
import discord
|
||||
from sqlalchemy import select
|
||||
@@ -10,14 +13,23 @@ from guardden.models import BannedWord, Guild, GuildSettings
|
||||
from guardden.services.cache import CacheService, get_cache_service
|
||||
from guardden.services.database import Database
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from guardden.config import Settings
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class GuildConfigService:
|
||||
"""Manages guild configurations with multi-tier caching."""
|
||||
|
||||
def __init__(self, database: Database, cache: CacheService | None = None) -> None:
|
||||
def __init__(
|
||||
self,
|
||||
database: Database,
|
||||
settings: Settings | None = None,
|
||||
cache: CacheService | None = None,
|
||||
) -> None:
|
||||
self.database = database
|
||||
self.settings = settings
|
||||
self.cache = cache or get_cache_service()
|
||||
self._memory_cache: dict[int, GuildSettings] = {}
|
||||
self._cache_ttl = 300 # 5 minutes
|
||||
@@ -88,9 +100,35 @@ class GuildConfigService:
|
||||
session.add(db_guild)
|
||||
await session.flush()
|
||||
|
||||
# Create default settings
|
||||
settings = GuildSettings(guild_id=guild.id)
|
||||
session.add(settings)
|
||||
# Create settings with defaults from config (if available)
|
||||
if self.settings and self.settings.guild_default:
|
||||
defaults = self.settings.guild_default
|
||||
guild_settings = GuildSettings(
|
||||
guild_id=guild.id,
|
||||
prefix=defaults.prefix,
|
||||
locale=defaults.locale,
|
||||
automod_enabled=defaults.automod_enabled,
|
||||
anti_spam_enabled=defaults.anti_spam_enabled,
|
||||
link_filter_enabled=defaults.link_filter_enabled,
|
||||
message_rate_limit=defaults.message_rate_limit,
|
||||
message_rate_window=defaults.message_rate_window,
|
||||
duplicate_threshold=defaults.duplicate_threshold,
|
||||
mention_limit=defaults.mention_limit,
|
||||
mention_rate_limit=defaults.mention_rate_limit,
|
||||
mention_rate_window=defaults.mention_rate_window,
|
||||
ai_moderation_enabled=defaults.ai_moderation_enabled,
|
||||
ai_sensitivity=defaults.ai_sensitivity,
|
||||
ai_confidence_threshold=defaults.ai_confidence_threshold,
|
||||
ai_log_only=defaults.ai_log_only,
|
||||
nsfw_detection_enabled=defaults.nsfw_detection_enabled,
|
||||
verification_enabled=defaults.verification_enabled,
|
||||
verification_type=defaults.verification_type,
|
||||
strike_actions=defaults.strike_actions,
|
||||
scam_allowlist=defaults.scam_allowlist,
|
||||
)
|
||||
else:
|
||||
guild_settings = GuildSettings(guild_id=guild.id)
|
||||
session.add(guild_settings)
|
||||
|
||||
await session.commit()
|
||||
|
||||
@@ -115,7 +153,7 @@ class GuildConfigService:
|
||||
await session.commit()
|
||||
|
||||
# Invalidate cache
|
||||
self._cache.pop(guild_id, None)
|
||||
self._memory_cache.pop(guild_id, None)
|
||||
|
||||
return settings
|
||||
|
||||
|
||||
Reference in New Issue
Block a user