package config import ( "os" "strconv" "time" ) // Config holds all configuration for the application type Config struct { // Server configuration ServerPort string Environment string // MySQL Database configuration DBHost string DBPort string DBUser string DBPassword string DBName string DBCharset string // Data directory DataDir string // Redis configuration RedisAddr string RedisPassword string RedisDB int // YunAPI configuration (exchange rates) YunAPIURL string YunAPIKey string SyncInterval time.Duration CacheExpiration time.Duration MaxRetries int // JWT configuration JWTSecret string JWTAccessExpiry time.Duration JWTRefreshExpiry time.Duration // GitHub OAuth configuration GitHubClientID string GitHubClientSecret string GitHubRedirectURL string FrontendURL string // AI configuration (OpenAI compatible) OpenAIAPIKey string OpenAIBaseURL string WhisperModel string ChatModel string AISessionTimeout time.Duration // Image upload configuration ImageUploadDir string MaxImageSize int64 AllowedImageTypes string MaxImagesPerTx int } // Load loads configuration from environment variables func Load() *Config { cfg := &Config{ // Server ServerPort: getEnv("SERVER_PORT", "8080"), Environment: getEnv("ENVIRONMENT", "development"), // Data directory DataDir: getEnv("DATA_DIR", "./data"), // MySQL Database DBHost: getEnv("DB_HOST", ""), DBPort: getEnv("DB_PORT", "3306"), DBUser: getEnv("DB_USER", ""), DBPassword: getEnv("DB_PASSWORD", ""), DBName: getEnv("DB_NAME", ""), DBCharset: getEnv("DB_CHARSET", "utf8mb4"), // Redis RedisAddr: getEnv("REDIS_ADDR", ""), RedisPassword: getEnv("REDIS_PASSWORD", ""), RedisDB: getEnvInt("REDIS_DB", 0), // YunAPI (exchange rates) YunAPIURL: getEnv("YUNAPI_URL", ""), YunAPIKey: getEnv("YUNAPI_KEY", ""), SyncInterval: getEnvDuration("SYNC_INTERVAL", 10*time.Minute), CacheExpiration: getEnvDuration("CACHE_EXPIRATION", 10*time.Minute), MaxRetries: getEnvInt("MAX_RETRIES", 3), // JWT JWTSecret: getEnv("JWT_SECRET", ""), JWTAccessExpiry: getEnvDuration("JWT_ACCESS_EXPIRY", 15*time.Minute), JWTRefreshExpiry: getEnvDuration("JWT_REFRESH_EXPIRY", 168*time.Hour), // 7 days // GitHub OAuth GitHubClientID: getEnv("GITHUB_CLIENT_ID", ""), GitHubClientSecret: getEnv("GITHUB_CLIENT_SECRET", ""), GitHubRedirectURL: getEnv("GITHUB_REDIRECT_URL", ""), FrontendURL: getEnv("FRONTEND_URL", "http://localhost:5173"), // AI (OpenAI compatible) OpenAIAPIKey: getEnv("OPENAI_API_KEY", ""), OpenAIBaseURL: getEnv("OPENAI_BASE_URL", ""), WhisperModel: getEnv("WHISPER_MODEL", "whisper-1"), ChatModel: getEnv("CHAT_MODEL", "gpt-3.5-turbo"), AISessionTimeout: getEnvDuration("AI_SESSION_TIMEOUT", 30*time.Minute), // Image upload ImageUploadDir: getEnv("IMAGE_UPLOAD_DIR", "./uploads/images"), MaxImageSize: getEnvInt64("MAX_IMAGE_SIZE", 10*1024*1024), // 10MB AllowedImageTypes: getEnv("ALLOWED_IMAGE_TYPES", "image/jpeg,image/png,image/heic"), MaxImagesPerTx: getEnvInt("MAX_IMAGES_PER_TX", 9), } // Ensure data directory exists if cfg.DataDir != "" { _ = os.MkdirAll(cfg.DataDir, 0755) } // Ensure image upload directory exists if cfg.ImageUploadDir != "" { _ = os.MkdirAll(cfg.ImageUploadDir, 0755) } return cfg } // IsDevelopment returns true if running in development mode func (c *Config) IsDevelopment() bool { return c.Environment == "development" } // IsProduction returns true if running in production mode func (c *Config) IsProduction() bool { return c.Environment == "production" } // getEnv gets an environment variable or returns a default value func getEnv(key, defaultValue string) string { if value := os.Getenv(key); value != "" { return value } return defaultValue } // getEnvInt gets an environment variable as int or returns a default value func getEnvInt(key string, defaultValue int) int { if value := os.Getenv(key); value != "" { if intValue, err := strconv.Atoi(value); err == nil { return intValue } } return defaultValue } // getEnvInt64 gets an environment variable as int64 or returns a default value func getEnvInt64(key string, defaultValue int64) int64 { if value := os.Getenv(key); value != "" { if intValue, err := strconv.ParseInt(value, 10, 64); err == nil { return intValue } } return defaultValue } // getEnvDuration gets an environment variable as duration or returns a default value func getEnvDuration(key string, defaultValue time.Duration) time.Duration { if value := os.Getenv(key); value != "" { if duration, err := time.ParseDuration(value); err == nil { return duration } } return defaultValue }