2765c464bd
After gallery-dl returns, parse stdout for written file paths and run
the magic-byte validator on each. Files that fail are moved to
{download_path}/_quarantine/{subscription}/{platform}/ with a sidecar
JSON capturing the source URL, validation reason, and original path —
enough for an operator to redownload-from-source or delete.
Adds ErrorType.VALIDATION_FAILED. A successful gallery-dl run that
produced quarantined files is now a soft failure (success=False,
error_message names the dominant failure reason and count) so the
source's error_count ticks up and the dashboard surfaces it. Gated
by download.validate_files setting (default True).
files_quarantined and quarantined_paths are persisted into download
metadata for the UI/API to consume.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
58 lines
1.6 KiB
Python
58 lines
1.6 KiB
Python
"""Setting model - key-value application settings."""
|
|
|
|
import secrets
|
|
from datetime import datetime
|
|
from sqlalchemy import String, func
|
|
from sqlalchemy.dialects.postgresql import JSONB
|
|
from sqlalchemy.orm import Mapped, mapped_column
|
|
|
|
from app.models.base import Base
|
|
|
|
|
|
def generate_api_key() -> str:
|
|
"""Generate a secure random API key."""
|
|
return secrets.token_urlsafe(32)
|
|
|
|
|
|
class Setting(Base):
|
|
"""Key-value setting storage."""
|
|
|
|
__tablename__ = "settings"
|
|
|
|
key: Mapped[str] = mapped_column(String(100), primary_key=True)
|
|
value: Mapped[dict] = mapped_column(JSONB, nullable=False)
|
|
updated_at: Mapped[datetime] = mapped_column(default=func.now(), onupdate=func.now())
|
|
|
|
def __repr__(self) -> str:
|
|
return f"<Setting {self.key}>"
|
|
|
|
def to_dict(self) -> dict:
|
|
"""Convert to dictionary for API responses."""
|
|
return {
|
|
"key": self.key,
|
|
"value": self.value,
|
|
"updated_at": self.updated_at.isoformat() if self.updated_at else None,
|
|
}
|
|
|
|
|
|
# Default settings that should exist
|
|
DEFAULT_SETTINGS = {
|
|
"download.parallel_limit": 3,
|
|
"download.rate_limit": 3.0,
|
|
"download.retry_count": 3,
|
|
"download.schedule_interval": 28800, # 8 hours
|
|
"download.validate_files": True,
|
|
"notification.enabled": False,
|
|
"notification.webhook_url": None,
|
|
"dashboard.failure_threshold": 5,
|
|
}
|
|
|
|
# Key for the extension API key setting
|
|
EXTENSION_API_KEY_SETTING = "security.extension_api_key"
|
|
|
|
# Key for cached storage stats
|
|
STORAGE_STATS_SETTING = "cache.storage_stats"
|
|
|
|
# Key for cached library-validation report (last sweep)
|
|
LIBRARY_VALIDATION_REPORT_SETTING = "cache.library_validation_report"
|