76 lines
2.0 KiB
Go
76 lines
2.0 KiB
Go
// config.go loads and validates the cwd config.toml file for the new CLI.
|
|
// It currently owns streamer list parsing, normalization, and the default
|
|
// config path behavior used by application startup.
|
|
package config
|
|
|
|
import (
|
|
"errors"
|
|
"fmt"
|
|
"os"
|
|
"strings"
|
|
|
|
"github.com/BurntSushi/toml"
|
|
)
|
|
|
|
const configFileName = "config.toml"
|
|
|
|
// Config is the user-owned TOML configuration for parasocial.
|
|
type Config struct {
|
|
Streamers []string `toml:"streamers"`
|
|
}
|
|
|
|
// DefaultPath returns the config file path relative to the current working directory.
|
|
func DefaultPath() string {
|
|
return configFileName
|
|
}
|
|
|
|
// LoadDefault reads config from the current working directory.
|
|
func LoadDefault() (Config, error) {
|
|
return Load(DefaultPath())
|
|
}
|
|
|
|
// Load reads, normalizes, and validates a TOML config file.
|
|
func Load(path string) (Config, error) {
|
|
var cfg Config
|
|
if _, err := toml.DecodeFile(path, &cfg); err != nil {
|
|
if errors.Is(err, os.ErrNotExist) {
|
|
return Config{}, fmt.Errorf("config file not found at %s", path)
|
|
}
|
|
return Config{}, fmt.Errorf("load config %s: %w", path, err)
|
|
}
|
|
|
|
cfg.Streamers = normalizeStreamers(cfg.Streamers)
|
|
if len(cfg.Streamers) == 0 {
|
|
return Config{}, fmt.Errorf("config %s must define at least one streamer", path)
|
|
}
|
|
|
|
return cfg, nil
|
|
}
|
|
|
|
// normalizeStreamers deduplicates streamer names after applying input cleanup rules.
|
|
func normalizeStreamers(streamers []string) []string {
|
|
seen := make(map[string]struct{}, len(streamers))
|
|
normalized := make([]string, 0, len(streamers))
|
|
|
|
for _, streamer := range streamers {
|
|
streamer = normalizeStreamer(streamer)
|
|
if streamer == "" {
|
|
continue
|
|
}
|
|
if _, ok := seen[streamer]; ok {
|
|
continue
|
|
}
|
|
seen[streamer] = struct{}{}
|
|
normalized = append(normalized, streamer)
|
|
}
|
|
|
|
return normalized
|
|
}
|
|
|
|
// normalizeStreamer trims formatting noise and canonicalizes a single streamer name.
|
|
func normalizeStreamer(streamer string) string {
|
|
streamer = strings.TrimSpace(streamer)
|
|
streamer = strings.TrimPrefix(streamer, "#")
|
|
return strings.ToLower(strings.TrimSpace(streamer))
|
|
}
|