package config import ( "errors" "fmt" "path/filepath" "time" "ddc/internal/preferences" ) const ( minPasswordLength = 12 defaultLibraryRoots = "/media/blob/TeaNet/Plex;/media/blob/ChaiNet/Plex" ) type Settings struct { ListenAddr string Username string Password string CookieSecure bool SessionTTL time.Duration TrustProxyHeaders bool DownloadDir string LibraryRoots []string LogLevel string LogFormat string Defaults preferences.Preferences } func Load() (Settings, error) { reader := &envReader{} settings := Settings{ ListenAddr: reader.text("LISTEN_ADDR", ":8080"), Username: reader.text("AUTH_USERNAME", ""), Password: reader.text("AUTH_PASSWORD", ""), CookieSecure: reader.boolean("COOKIE_SECURE", true), SessionTTL: time.Duration(reader.integer("SESSION_TTL_HOURS", 12)) * time.Hour, TrustProxyHeaders: reader.boolean("TRUST_PROXY_HEADERS", false), DownloadDir: filepath.Clean(reader.text("DOWNLOAD_DIR", "/data/downloads")), LogLevel: reader.text("LOG_LEVEL", "info"), LogFormat: reader.text("LOG_FORMAT", "text"), Defaults: preferences.Preferences{ MaxConcurrentDownloads: reader.integer("MAX_CONCURRENT_DOWNLOADS", 2), ConnectionsPerDownload: reader.integer("CONNECTIONS_PER_DOWNLOAD", 4), MinFreeGB: reader.integer("MIN_FREE_GB", 10), AllowedPorts: reader.ports("ALLOWED_PORTS", "80,443"), AutoExtract: true, CleanupAfterMove: true, }, } rawRoots := reader.text("LIBRARY_ROOTS", defaultLibraryRoots) if reader.err != nil { return Settings{}, reader.err } roots, err := parseLibraryRoots(rawRoots) if err != nil { return Settings{}, err } settings.LibraryRoots = roots return settings, settings.validate() } func (settings Settings) validate() error { switch { case settings.Username == "": return errors.New("AUTH_USERNAME is required") case len(settings.Password) < minPasswordLength: return fmt.Errorf("AUTH_PASSWORD must be at least %d characters", minPasswordLength) case !filepath.IsAbs(settings.DownloadDir): return errors.New("DOWNLOAD_DIR must be an absolute path") case settings.SessionTTL <= 0: return errors.New("SESSION_TTL_HOURS must be greater than zero") } return settings.Defaults.Validate() }