Files
mal/internal/config/config.go

86 lines
2.3 KiB
Go

package config
import (
"errors"
"fmt"
"os"
"strings"
)
type EpisodeAvailabilityMode string
const (
EpisodeAvailabilityModeAuto EpisodeAvailabilityMode = "auto"
EpisodeAvailabilityModeLegacy EpisodeAvailabilityMode = "legacy"
EpisodeAvailabilityModeJikan EpisodeAvailabilityMode = "jikan"
)
type Config struct {
Port string
// GinMode maps to gin.SetMode. When empty, the server uses release mode by default.
GinMode string
DatabaseFile string
// Allow any Origin for CORS. Intended for local dev / reverse proxy setups only.
CORSAllowAll bool
EpisodeAvailabilityMode EpisodeAvailabilityMode
// Optional. When empty, proxy token signing is disabled.
PlaybackProxySecret string
// Optional debug toggle for Jikan client tracing.
JikanTrace bool
}
func Load() (Config, error) {
cfg := Config{
Port: firstNonEmpty(strings.TrimSpace(os.Getenv("PORT")), "3000"),
GinMode: strings.TrimSpace(os.Getenv("GIN_MODE")),
DatabaseFile: firstNonEmpty(strings.TrimSpace(os.Getenv("DATABASE_FILE")), "mal.db"),
CORSAllowAll: strings.TrimSpace(os.Getenv("MAL_CORS_ALLOW_ALL")) == "1",
PlaybackProxySecret: strings.TrimSpace(os.Getenv("PLAYBACK_PROXY_SECRET")),
JikanTrace: truthy(strings.TrimSpace(os.Getenv("MAL_JIKAN_TRACE"))),
EpisodeAvailabilityMode: EpisodeAvailabilityModeAuto,
}
if raw := strings.ToLower(strings.TrimSpace(os.Getenv("EPISODE_AVAILABILITY_MODE"))); raw != "" {
switch EpisodeAvailabilityMode(raw) {
case EpisodeAvailabilityModeAuto, EpisodeAvailabilityModeLegacy, EpisodeAvailabilityModeJikan:
cfg.EpisodeAvailabilityMode = EpisodeAvailabilityMode(raw)
default:
return Config{}, fmt.Errorf("invalid EPISODE_AVAILABILITY_MODE: %q (expected auto|legacy|jikan)", raw)
}
}
if strings.TrimSpace(cfg.Port) == "" {
return Config{}, errors.New("PORT must not be empty")
}
if strings.TrimSpace(cfg.DatabaseFile) == "" {
return Config{}, errors.New("DATABASE_FILE must not be empty")
}
return cfg, nil
}
func firstNonEmpty(values ...string) string {
for _, v := range values {
if strings.TrimSpace(v) != "" {
return v
}
}
return ""
}
func truthy(v string) bool {
switch strings.ToLower(strings.TrimSpace(v)) {
case "1", "true", "yes", "y", "on":
return true
default:
return false
}
}