// Package config manages the local mapping between playlist folders and // Kreativ-Tonies. Credentials are never stored here. package config import ( "fmt" "os" "path/filepath" "gopkg.in/yaml.v3" ) // Mapping maps a local folder (e.g. an exported Deezer playlist) to a Kreativ-Tonie. type Mapping struct { Name string `yaml:"name"` HouseholdID string `yaml:"household_id"` TonieID string `yaml:"tonie_id"` TonieName string `yaml:"tonie_name,omitempty"` Folder string `yaml:"folder"` PlaylistRef string `yaml:"playlist_ref,omitempty"` Prune bool `yaml:"prune"` } // Config is the full toni-sync configuration. type Config struct { Mappings []Mapping `yaml:"mappings"` } // Get returns the mapping with the given name, if present. func (c *Config) Get(name string) *Mapping { for i := range c.Mappings { if c.Mappings[i].Name == name { return &c.Mappings[i] } } return nil } // Upsert adds a new mapping or replaces an existing one with the same name. func (c *Config) Upsert(m Mapping) { for i := range c.Mappings { if c.Mappings[i].Name == m.Name { c.Mappings[i] = m return } } c.Mappings = append(c.Mappings, m) } // Remove deletes the mapping with the given name. Returns false if it was not found. func (c *Config) Remove(name string) bool { for i := range c.Mappings { if c.Mappings[i].Name == name { c.Mappings = append(c.Mappings[:i], c.Mappings[i+1:]...) return true } } return false } // DefaultPath returns the default config file location, honoring TONI_SYNC_CONFIG. func DefaultPath() string { if p := os.Getenv("TONI_SYNC_CONFIG"); p != "" { return p } home, err := os.UserHomeDir() if err != nil { home = "." } return filepath.Join(home, ".config", "toni-sync", "config.yaml") } // Load reads the config from path, or returns an empty Config if it doesn't exist yet. func Load(path string) (*Config, error) { data, err := os.ReadFile(path) if err != nil { if os.IsNotExist(err) { return &Config{}, nil } return nil, fmt.Errorf("reading config %s: %w", path, err) } var cfg Config if err := yaml.Unmarshal(data, &cfg); err != nil { return nil, fmt.Errorf("parsing config %s: %w", path, err) } return &cfg, nil } // Save writes the config to path, creating parent directories as needed. func Save(cfg *Config, path string) error { if err := os.MkdirAll(filepath.Dir(path), 0o755); err != nil { return fmt.Errorf("creating config dir: %w", err) } data, err := yaml.Marshal(cfg) if err != nil { return fmt.Errorf("encoding config: %w", err) } if err := os.WriteFile(path, data, 0o644); err != nil { return fmt.Errorf("writing config %s: %w", path, err) } return nil }