feat: initial commit
build / test (push) Successful in 9s
build / build (push) Successful in 10s
build / build-image (push) Successful in 1m4s

This commit is contained in:
2026-06-04 14:19:37 +02:00
commit cf961ab94f
28 changed files with 3036 additions and 0 deletions
+75
View File
@@ -0,0 +1,75 @@
// 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
}