mirror of
https://github.com/Dvorinka/SEEN.git
synced 2026-06-04 20:43:03 +00:00
195 lines
4.5 KiB
Go
195 lines
4.5 KiB
Go
package config
|
|
|
|
import (
|
|
"fmt"
|
|
"os"
|
|
"slices"
|
|
"strconv"
|
|
"strings"
|
|
"time"
|
|
|
|
"github.com/joho/godotenv"
|
|
)
|
|
|
|
type Config struct {
|
|
Env string
|
|
AppName string
|
|
HTTP HTTPConfig
|
|
CORS CORSConfig
|
|
Postgres PostgresConfig
|
|
Cache CacheConfig
|
|
Auth AuthConfig
|
|
TMDB TMDBConfig
|
|
IGDB IGDBConfig
|
|
}
|
|
|
|
type HTTPConfig struct {
|
|
Host string
|
|
Port int
|
|
ReadTimeout time.Duration
|
|
WriteTimeout time.Duration
|
|
}
|
|
|
|
type CORSConfig struct {
|
|
AllowedOrigins []string
|
|
AllowedMethods []string
|
|
AllowedHeaders []string
|
|
ExposedHeaders []string
|
|
AllowCredentials bool
|
|
MaxAge time.Duration
|
|
}
|
|
|
|
type PostgresConfig struct {
|
|
URL string
|
|
MaxConns int32
|
|
MinConns int32
|
|
}
|
|
|
|
type CacheConfig struct {
|
|
Addr string
|
|
Password string
|
|
DB int
|
|
}
|
|
|
|
type AuthConfig struct {
|
|
AccessTokenTTLMinutes int
|
|
RefreshTokenTTLHours int
|
|
JWTSecret string
|
|
}
|
|
|
|
type TMDBConfig struct {
|
|
APIKey string
|
|
BaseURL string
|
|
}
|
|
|
|
type IGDBConfig struct {
|
|
ClientID string
|
|
ClientSecret string
|
|
BaseURL string
|
|
TokenURL string
|
|
}
|
|
|
|
func Load() Config {
|
|
_ = godotenv.Load()
|
|
|
|
return Config{
|
|
Env: getString("SEEN_ENV", "development"),
|
|
AppName: getString("SEEN_APP_NAME", "seen"),
|
|
HTTP: HTTPConfig{
|
|
Host: getString("SEEN_HTTP_HOST", "0.0.0.0"),
|
|
Port: getInt("SEEN_HTTP_PORT", 8081),
|
|
ReadTimeout: getDuration("SEEN_HTTP_READ_TIMEOUT", 15*time.Second),
|
|
WriteTimeout: getDuration("SEEN_HTTP_WRITE_TIMEOUT", 15*time.Second),
|
|
},
|
|
CORS: CORSConfig{
|
|
AllowedOrigins: getCSV("SEEN_CORS_ALLOWED_ORIGINS", []string{}),
|
|
AllowedMethods: getCSV("SEEN_CORS_ALLOWED_METHODS", []string{"GET", "POST", "PUT", "PATCH", "DELETE", "OPTIONS"}),
|
|
AllowedHeaders: getCSV("SEEN_CORS_ALLOWED_HEADERS", []string{"Accept", "Authorization", "Content-Type", "X-Request-ID"}),
|
|
ExposedHeaders: getCSV("SEEN_CORS_EXPOSED_HEADERS", []string{"X-Request-ID"}),
|
|
AllowCredentials: getBool("SEEN_CORS_ALLOW_CREDENTIALS", false),
|
|
MaxAge: getDuration("SEEN_CORS_MAX_AGE", 24*time.Hour),
|
|
},
|
|
Postgres: PostgresConfig{
|
|
URL: getString("SEEN_POSTGRES_URL", "postgres://seen:seen@localhost:5432/seen?sslmode=disable"),
|
|
MaxConns: int32(getInt("SEEN_POSTGRES_MAX_CONNS", 10)),
|
|
MinConns: int32(getInt("SEEN_POSTGRES_MIN_CONNS", 2)),
|
|
},
|
|
Cache: CacheConfig{
|
|
Addr: getString("SEEN_CACHE_ADDR", "localhost:6379"),
|
|
Password: getString("SEEN_CACHE_PASSWORD", ""),
|
|
DB: getInt("SEEN_CACHE_DB", 0),
|
|
},
|
|
Auth: AuthConfig{
|
|
AccessTokenTTLMinutes: getInt("SEEN_AUTH_ACCESS_TOKEN_TTL_MINUTES", 30),
|
|
RefreshTokenTTLHours: getInt("SEEN_AUTH_REFRESH_TOKEN_TTL_HOURS", 24*30),
|
|
JWTSecret: getString("SEEN_AUTH_JWT_SECRET", "replace-in-production"),
|
|
},
|
|
TMDB: TMDBConfig{
|
|
APIKey: getString("SEEN_TMDB_API_KEY", ""),
|
|
BaseURL: getString("SEEN_TMDB_BASE_URL", "https://api.themoviedb.org/3"),
|
|
},
|
|
IGDB: IGDBConfig{
|
|
ClientID: getString("SEEN_IGDB_CLIENT_ID", ""),
|
|
ClientSecret: getString("SEEN_IGDB_CLIENT_SECRET", ""),
|
|
BaseURL: getString("SEEN_IGDB_BASE_URL", "https://api.igdb.com/v4"),
|
|
TokenURL: getString("SEEN_IGDB_TOKEN_URL", "https://id.twitch.tv/oauth2/token"),
|
|
},
|
|
}
|
|
}
|
|
|
|
func (c HTTPConfig) Addr() string {
|
|
return fmt.Sprintf("%s:%d", c.Host, c.Port)
|
|
}
|
|
|
|
func getString(key string, fallback string) string {
|
|
if value, ok := os.LookupEnv(key); ok {
|
|
return value
|
|
}
|
|
return fallback
|
|
}
|
|
|
|
func getInt(key string, fallback int) int {
|
|
value, ok := os.LookupEnv(key)
|
|
if !ok {
|
|
return fallback
|
|
}
|
|
|
|
parsed, err := strconv.Atoi(value)
|
|
if err != nil {
|
|
return fallback
|
|
}
|
|
return parsed
|
|
}
|
|
|
|
func getDuration(key string, fallback time.Duration) time.Duration {
|
|
value, ok := os.LookupEnv(key)
|
|
if !ok {
|
|
return fallback
|
|
}
|
|
|
|
parsed, err := time.ParseDuration(value)
|
|
if err != nil {
|
|
return fallback
|
|
}
|
|
return parsed
|
|
}
|
|
|
|
func getBool(key string, fallback bool) bool {
|
|
value, ok := os.LookupEnv(key)
|
|
if !ok {
|
|
return fallback
|
|
}
|
|
|
|
switch strings.ToLower(strings.TrimSpace(value)) {
|
|
case "1", "true", "yes", "on":
|
|
return true
|
|
case "0", "false", "no", "off":
|
|
return false
|
|
default:
|
|
return fallback
|
|
}
|
|
}
|
|
|
|
func getCSV(key string, fallback []string) []string {
|
|
value, ok := os.LookupEnv(key)
|
|
if !ok {
|
|
return slices.Clone(fallback)
|
|
}
|
|
|
|
parts := strings.Split(value, ",")
|
|
items := make([]string, 0, len(parts))
|
|
for _, part := range parts {
|
|
trimmed := strings.TrimSpace(part)
|
|
if trimmed == "" {
|
|
continue
|
|
}
|
|
items = append(items, trimmed)
|
|
}
|
|
|
|
if len(items) == 0 {
|
|
return slices.Clone(fallback)
|
|
}
|
|
|
|
return items
|
|
}
|