package config import ( "bufio" "os" "strings" "time" ) // Config مقادیر محیطی برنامه را نگه می‌دارد. type Config struct { Addr string // آدرس گوش‌دادن HTTP مثل :8080 DBPath string // مسیر فایل SQLite JWTSecret string // کلید امضای JWT JWTTTL time.Duration // طول عمر توکن KaveAPIKey string // کلید کاوه‌نگار KaveTemple string // نام تمپلیت verify (loginotp) OTPTTL time.Duration // اعتبار کد OTP AdminMobile string // شماره ادمین برای تست بدون SMS AdminOTP string // کد ثابت ادمین AdminUser string // یوزرنیمِ پنل ادمین (Basic Auth) AdminPass string // پسوردِ پنل ادمین (Basic Auth) CardsDir string // پوشه‌ی دیسکیِ اسکین‌های آپلودی (روی volume ماندگار) CarpetsDir string // پوشه‌ی دیسکیِ تصاویرِ فرش (روی volume ماندگار) } // Load کانفیگ را از env با مقادیر پیش‌فرض معقول می‌خواند. func Load() Config { loadDotenv(".env") return Config{ Addr: env("ADDR", ":8080"), DBPath: env("DB_PATH", "hakemsho.db"), JWTSecret: env("JWT_SECRET", "change-me-in-production"), JWTTTL: 30 * 24 * time.Hour, KaveAPIKey: env("KAVE_API_KEY", ""), KaveTemple: env("KAVE_TEMPLATE", "loginotp"), OTPTTL: 15 * time.Minute, AdminMobile: env("ADMIN_MOBILE", ""), AdminOTP: env("ADMIN_OTP", ""), AdminUser: env("ADMIN_PANEL_USER", "admin"), AdminPass: env("ADMIN_PANEL_PASS", "admin"), CardsDir: env("CARDS_DIR", "carddata"), CarpetsDir: env("CARPETS_DIR", "carpetdata"), } } // loadDotenv فایل .env را در صورت وجود می‌خواند و متغیرهایی را که // از قبل در محیط ست نشده‌اند مقداردهی می‌کند. بدون وابستگی خارجی. func loadDotenv(path string) { f, err := os.Open(path) if err != nil { return // .env اختیاری است } defer f.Close() sc := bufio.NewScanner(f) for sc.Scan() { line := strings.TrimSpace(sc.Text()) if line == "" || strings.HasPrefix(line, "#") { continue } key, val, ok := strings.Cut(line, "=") if !ok { continue } key = strings.TrimSpace(key) val = strings.Trim(strings.TrimSpace(val), `"'`) if _, exists := os.LookupEnv(key); !exists { _ = os.Setenv(key, val) } } } func env(key, def string) string { if v := os.Getenv(key); v != "" { return v } return def }