package config import ( "bufio" "os" "strconv" "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 ماندگار) AvatarsDir string // پوشه‌ی دیسکیِ تصاویرِ شخصیتِ آواتار (روی volume ماندگار) PublicURL string // مبدأِ عمومیِ سرور (برای ساختِ URL کاملِ تصاویر مثلِ آواتار) TelescopeSize int // تعدادِ درخواستی که بازرسِ حافظه نگه می‌دارد // خرید درون‌برنامه‌ای (IAP) IAPPackage string // نامِ بسته‌ی اپ (برای مایکت/کافه) MyketAccessToken string // access token مایکت (تأیید سمت‌سرور) MyketRSAKey string // کلیدِ عمومیِ RSA مایکت (تأیید امضای آفلاین) BazaarRSAKey string // کلیدِ عمومیِ RSA کافه‌بازار (تأیید امضای آفلاین) } // 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", ""), // خالی ⇒ پیامکِ متنیِ ساده (بدونِ تمپلیت) 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"), AvatarsDir: env("AVATARS_DIR", "avatardata"), PublicURL: strings.TrimRight(env("PUBLIC_URL", "https://hakem.approagency.ir"), "/"), TelescopeSize: envInt("TELESCOPE_SIZE", 200), IAPPackage: env("IAP_PACKAGE", ""), MyketAccessToken: env("MYKET_ACCESS_TOKEN", ""), MyketRSAKey: env("MYKET_RSA_KEY", ""), BazaarRSAKey: env("BAZAAR_RSA_KEY", ""), } } // 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 } func envInt(key string, def int) int { if v := os.Getenv(key); v != "" { if n, err := strconv.Atoi(v); err == nil { return n } } return def }