from __future__ import annotations from datetime import datetime, timezone from typing import Optional from sqlmodel import Field, SQLModel def _now() -> datetime: return datetime.now(timezone.utc) # Notification event names ---------------------------------------------------- EVENT_UPDATE_AVAILABLE = "update_available" EVENT_STACK_START = "stack_start" EVENT_STACK_STOP = "stack_stop" EVENT_STACK_ERROR = "stack_error" EVENT_PULL_FAILED = "pull_failed" EVENT_BACKUP_FAILED = "backup_failed" ALL_EVENTS = [ EVENT_UPDATE_AVAILABLE, EVENT_STACK_START, EVENT_STACK_STOP, EVENT_STACK_ERROR, EVENT_PULL_FAILED, EVENT_BACKUP_FAILED, ] WEBHOOK_TYPES = ["ntfy", "discord", "slack", "gotify", "generic"] class Setting(SQLModel, table=True): """Simple key/value store for runtime-tunable settings (JSON-encoded value).""" key: str = Field(primary_key=True) value: str # JSON-encoded class Webhook(SQLModel, table=True): id: Optional[int] = Field(default=None, primary_key=True) name: str url: str type: str = "generic" # one of WEBHOOK_TYPES events: str = ",".join(ALL_EVENTS) # comma-separated subscribed events enabled: bool = True created_at: datetime = Field(default_factory=_now) # --- API schemas --- class WebhookCreate(SQLModel): name: str url: str type: str = "generic" events: list[str] = ALL_EVENTS enabled: bool = True class WebhookUpdate(SQLModel): name: Optional[str] = None url: Optional[str] = None type: Optional[str] = None events: Optional[list[str]] = None enabled: Optional[bool] = None class WebhookRead(SQLModel): id: int name: str url: str type: str events: list[str] enabled: bool created_at: datetime class SettingsRead(SQLModel): update_check_interval_minutes: int env_webhook_count: int available_events: list[str] webhook_types: list[str] class SettingsUpdate(SQLModel): update_check_interval_minutes: Optional[int] = None