// Package config loads daemon configuration from flags and environment // variables (flags take precedence; env provides defaults). package config import ( "flag" "fmt" "os" "strconv" "time" "git.mkz.me/mycroft/root-me-api/internal/anubis" ) // Config holds all daemon settings. type Config struct { HTTPAddr string GRPCAddr string RefreshInterval time.Duration Pages int UserAgent string RequestTimeout time.Duration LogLevel string } // Load parses configuration from the given args, falling back to environment // variables and then built-in defaults. func Load(args []string) (*Config, error) { c := &Config{} fs := flag.NewFlagSet("scoreboard-apid", flag.ContinueOnError) fs.StringVar(&c.HTTPAddr, "http-addr", env("HTTP_ADDR", ":8080"), "HTTP/JSON listen address") fs.StringVar(&c.GRPCAddr, "grpc-addr", env("GRPC_ADDR", ":9090"), "gRPC listen address") fs.DurationVar(&c.RefreshInterval, "refresh-interval", envDuration("REFRESH_INTERVAL", 10*time.Minute), "scoreboard refresh interval") fs.IntVar(&c.Pages, "pages", envInt("SCOREBOARD_PAGES", 4), "number of scoreboard pages to scrape (50 rows each)") fs.StringVar(&c.UserAgent, "user-agent", env("USER_AGENT", anubis.DefaultUserAgent), "User-Agent for root-me requests") fs.DurationVar(&c.RequestTimeout, "request-timeout", envDuration("REQUEST_TIMEOUT", 30*time.Second), "per-request HTTP timeout") fs.StringVar(&c.LogLevel, "log-level", env("LOG_LEVEL", "info"), "log level: debug, info, warn, error") if err := fs.Parse(args); err != nil { return nil, err } if c.Pages <= 0 { return nil, fmt.Errorf("pages must be > 0") } if c.RefreshInterval <= 0 { return nil, fmt.Errorf("refresh-interval must be > 0") } return c, nil } func env(key, def string) string { if v, ok := os.LookupEnv(key); ok { return v } return def } func envInt(key string, def int) int { if v, ok := os.LookupEnv(key); ok { if n, err := strconv.Atoi(v); err == nil { return n } } return def } func envDuration(key string, def time.Duration) time.Duration { if v, ok := os.LookupEnv(key); ok { if d, err := time.ParseDuration(v); err == nil { return d } } return def }