package config import ( "fmt" "os" "time" "gopkg.in/yaml.v3" ) const ( DefaultConfigPath = "/etc/media-node/config.yaml" DefaultDataDir = "/var/lib/media-node" DefaultCredentialsPath = "/etc/media-node/credentials/credentials.json" DefaultListen = "0.0.0.0:8080" ) type Config struct { Node NodeConfig `yaml:"node"` Master MasterConfig `yaml:"master"` Stream StreamConfig `yaml:"stream"` Media MediaConfig `yaml:"media"` Scanner ScannerConfig `yaml:"scanner"` Security SecurityConfig `yaml:"security"` } type NodeConfig struct { ID string `yaml:"id"` Name string `yaml:"name"` } type MasterConfig struct { URL string `yaml:"url"` } type StreamConfig struct { Listen string `yaml:"listen"` PublicURL string `yaml:"public_url"` } type MediaConfig struct { Movies []string `yaml:"movies"` Series []string `yaml:"series"` } type ScannerConfig struct { FullScanInterval string `yaml:"full_scan_interval"` } type SecurityConfig struct { SessionIdleTimeout string `yaml:"session_idle_timeout"` MaxConcurrentPerIP int `yaml:"max_concurrent_per_ip"` } type Credentials struct { NodeID string `json:"nodeId"` APIKey string `json:"apiKey"` Name string `json:"name"` } func Load(path string) (*Config, error) { data, err := os.ReadFile(path) if err != nil { return nil, fmt.Errorf("read config: %w", err) } var cfg Config if err := yaml.Unmarshal(data, &cfg); err != nil { return nil, fmt.Errorf("parse config: %w", err) } if cfg.Stream.Listen == "" { cfg.Stream.Listen = DefaultListen } if cfg.Scanner.FullScanInterval == "" { cfg.Scanner.FullScanInterval = "6h" } if cfg.Security.SessionIdleTimeout == "" { cfg.Security.SessionIdleTimeout = "20m" } if cfg.Security.MaxConcurrentPerIP == 0 { cfg.Security.MaxConcurrentPerIP = 8 } return &cfg, nil } func (c *Config) FullScanDuration() time.Duration { d, err := time.ParseDuration(c.Scanner.FullScanInterval) if err != nil { return 6 * time.Hour } return d } func Save(path string, cfg *Config) error { data, err := yaml.Marshal(cfg) if err != nil { return err } return os.WriteFile(path, data, 0o600) }