package config import ( "fmt" "log" "strings" "github.com/caarlos0/env/v10" ) // Config содержит всю конфигурацию приложения, получаемую из переменных окружения. type Config struct { TelegramBotToken string `env:"TELEGRAM_BOT_TOKEN,required"` TelegramAdminIDsRaw string `env:"TELEGRAM_ADMIN_IDS,required"` TelegramCacheChatID int64 `env:"TELEGRAM_CACHE_CHAT_ID,required"` YandexMusicToken string `env:"YANDEX_MUSIC_TOKEN"` DatabasePath string `env:"DATABASE_PATH" envDefault:"/data/bot.db"` LogLevel string `env:"LOG_LEVEL" envDefault:"info"` ProcessorWorkers int `env:"PROCESSOR_WORKERS" envDefault:"4"` YandexAPIRateLimit int `env:"YANDEX_API_RATE_LIMIT" envDefault:"5"` TelegramAdminIDs []int64 `env:"-"` // Это поле будет заполнено после парсинга } // New загружает конфигурацию из переменных окружения и парсит необходимые поля. func New() *Config { cfg := &Config{} if err := env.Parse(cfg); err != nil { log.Fatalf("failed to parse config: %+v", err) } // Парсим ID администраторов из строки if cfg.TelegramAdminIDsRaw != "" { ids := strings.Split(cfg.TelegramAdminIDsRaw, ",") cfg.TelegramAdminIDs = make([]int64, 0, len(ids)) for _, idStr := range ids { var id int64 if _, err := Sscanf(strings.TrimSpace(idStr), "%d", &id); err == nil { cfg.TelegramAdminIDs = append(cfg.TelegramAdminIDs, id) } else { log.Printf("warning: could not parse admin ID: %s", idStr) } } } if len(cfg.TelegramAdminIDs) == 0 { log.Fatalf("no valid admin IDs provided in TELEGRAM_ADMIN_IDS") } return cfg } // Sscanf - простая реализация для парсинга, чтобы избежать лишних зависимостей. // В стандартной библиотеке fmt.Sscanf требует, чтобы вся строка была разобрана. func Sscanf(str, format string, a ...interface{}) (int, error) { return fmt.Sscanf(str, format, a...) }