2025-08-22 12:57:33 +02:00
|
|
|
package config
|
|
|
|
|
|
|
|
|
|
import (
|
|
|
|
|
"fmt"
|
|
|
|
|
"os"
|
2025-11-18 15:20:14 +01:00
|
|
|
"os/exec"
|
2025-08-22 12:57:33 +02:00
|
|
|
"path/filepath"
|
|
|
|
|
"strconv"
|
|
|
|
|
"sync"
|
|
|
|
|
|
|
|
|
|
"github.com/joho/godotenv"
|
2025-11-18 15:20:14 +01:00
|
|
|
"github.com/labstack/gommon/log"
|
2025-08-22 12:57:33 +02:00
|
|
|
)
|
|
|
|
|
|
|
|
|
|
// Config holds all application configuration
|
|
|
|
|
type Config struct {
|
|
|
|
|
Database struct {
|
|
|
|
|
Host string
|
|
|
|
|
Port int
|
|
|
|
|
User string
|
|
|
|
|
Password string
|
|
|
|
|
DBName string
|
|
|
|
|
SSLMode string
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Images struct {
|
|
|
|
|
Enabled bool
|
|
|
|
|
ConcurrentLimit int
|
|
|
|
|
Path string
|
|
|
|
|
}
|
2025-11-18 15:20:14 +01:00
|
|
|
Videos struct {
|
|
|
|
|
Enabled bool
|
|
|
|
|
ConcurrentLimit int
|
|
|
|
|
Path string
|
|
|
|
|
}
|
2025-08-22 12:57:33 +02:00
|
|
|
Storage struct {
|
2025-10-27 17:58:42 +01:00
|
|
|
Endpoint string
|
2025-10-29 09:23:13 +01:00
|
|
|
Token string
|
2025-08-22 12:57:33 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Server struct {
|
|
|
|
|
Port int
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
var (
|
|
|
|
|
Cfg Config
|
|
|
|
|
once sync.Once
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
// Load initializes configuration once
|
|
|
|
|
func Load() *Config {
|
|
|
|
|
|
|
|
|
|
once.Do(func() {
|
|
|
|
|
// Try loading from .env file first
|
|
|
|
|
_ = godotenv.Load()
|
|
|
|
|
|
|
|
|
|
pwd, err := os.Getwd()
|
|
|
|
|
if err != nil {
|
|
|
|
|
fmt.Println(err)
|
|
|
|
|
os.Exit(1)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Database config
|
|
|
|
|
Cfg.Database.Host = getEnv("PGHOST", "localhost")
|
|
|
|
|
Cfg.Database.Port = getEnvAsInt("PGPORT", 5432)
|
|
|
|
|
Cfg.Database.User = getEnv("POSTGRES_USER", "postgres")
|
|
|
|
|
Cfg.Database.Password = getEnv("POSTGRES_PASSWORD", "")
|
|
|
|
|
Cfg.Database.DBName = getEnv("POSTGRES_DB", "postgres")
|
|
|
|
|
Cfg.Database.SSLMode = getEnv("PGSSLMODE", "true")
|
|
|
|
|
|
|
|
|
|
// Image processing config
|
|
|
|
|
Cfg.Images.Enabled = getEnvAsBool("IMAGEOPTION", true)
|
|
|
|
|
Cfg.Images.ConcurrentLimit = getEnvAsInt("CONCURRENT_IMAGES", 5)
|
|
|
|
|
Cfg.Images.Path = filepath.Join(pwd, "images")
|
|
|
|
|
|
2025-11-18 15:20:14 +01:00
|
|
|
// Video processing config
|
|
|
|
|
Cfg.Videos.Enabled = getEnvAsBool("VIDEOOPTION", true)
|
|
|
|
|
Cfg.Videos.ConcurrentLimit = getEnvAsInt("CONCURRENT_VIDEOS", 2)
|
|
|
|
|
Cfg.Videos.Path = filepath.Join(pwd, "videos")
|
|
|
|
|
|
2025-08-22 12:57:33 +02:00
|
|
|
// Storage config
|
2025-10-29 10:08:37 +01:00
|
|
|
Cfg.Storage.Endpoint = getEnv("STORAGE_URL", "")
|
|
|
|
|
Cfg.Storage.Token = getEnv("STORAGE_TOKEN", "")
|
2025-08-22 12:57:33 +02:00
|
|
|
|
|
|
|
|
// Server config
|
|
|
|
|
Cfg.Server.Port = getEnvAsInt("PORT", 1323)
|
|
|
|
|
|
|
|
|
|
// Validate required config
|
|
|
|
|
if Cfg.Database.Password == "" {
|
|
|
|
|
fmt.Printf("required environment variable POSTGRES_PASSWORD not set\n")
|
|
|
|
|
}
|
|
|
|
|
})
|
|
|
|
|
|
2025-11-18 15:20:14 +01:00
|
|
|
if err := exec.Command("ffmpeg", "-version").Run(); err != nil {
|
|
|
|
|
log.Errorf("FFmpeg not found: %w", err)
|
|
|
|
|
Cfg.Videos.Enabled = false
|
|
|
|
|
}
|
|
|
|
|
|
2025-08-22 12:57:33 +02:00
|
|
|
return &Cfg
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Helper functions
|
|
|
|
|
func getEnv(key, fallback string) string {
|
|
|
|
|
if value, exists := os.LookupEnv(key); exists {
|
|
|
|
|
return value
|
|
|
|
|
}
|
|
|
|
|
return fallback
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func getEnvAsInt(key string, fallback int) int {
|
|
|
|
|
if strValue := getEnv(key, ""); strValue != "" {
|
|
|
|
|
if value, err := strconv.Atoi(strValue); err == nil {
|
|
|
|
|
return value
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return fallback
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func getEnvAsBool(key string, fallback bool) bool {
|
|
|
|
|
if strValue := getEnv(key, ""); strValue != "" {
|
|
|
|
|
if value, err := strconv.ParseBool(strValue); err == nil {
|
|
|
|
|
return value
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return fallback
|
|
|
|
|
}
|