from pydantic import Field, SecretStr, computed_field from pydantic_settings import BaseSettings, SettingsConfigDict class BotSettings(BaseSettings): token: SecretStr class MonitorSettings(BaseSettings): check_interval: int = 30 reminder_interval: int = 1800 request_timeout: int = 10 failure_threshold: int = 2 body_preview: int = 400 class KomodoSettings(BaseSettings): """Связь с Komodo. Всё опционально - без неё бот работает как раньше.""" url: str = "" key: SecretStr = SecretStr("") secret: SecretStr = SecretStr("") timeout: int = 20 @computed_field @property def enabled(self) -> bool: return bool(self.url and self.key.get_secret_value()) class WebSettings(BaseSettings): """Приёмник входящих алертов (Komodo Alerter с endpoint type Custom).""" enabled: bool = False host: str = "0.0.0.0" # noqa: S104 port: int = 8080 token: SecretStr = SecretStr("") class DbSettings(BaseSettings): path: str = "data/healthbot.db" class LogSettings(BaseSettings): level: str = "INFO" level_external: str = "WARNING" show_time: bool = False console_width: int = 150 class Settings(BaseSettings): admin_id: int = 0 admin_ids: list[int] = Field(default_factory=list) bot: BotSettings = Field(default_factory=BotSettings) monitor: MonitorSettings = Field(default_factory=MonitorSettings) komodo: KomodoSettings = Field(default_factory=KomodoSettings) web: WebSettings = Field(default_factory=WebSettings) db: DbSettings = Field(default_factory=DbSettings) log: LogSettings = Field(default_factory=LogSettings) model_config = SettingsConfigDict( case_sensitive=False, env_file=".env", env_nested_delimiter="__", extra="ignore" ) @computed_field @property def admins(self) -> set[int]: return {i for i in (self.admin_id, *self.admin_ids) if i} env = Settings()