package main import ( "log" "os" "strconv" "strings" "time" ) type Config struct { Token string AppID string GuildID string PublicOrderChannelID string InternalOrderChannelID string AuditChannelID string AdminRoleIDs []string TeamRoleIDs []string DatabasePath string ThreadDeleteAfter time.Duration } func loadConfig() Config { cfg := Config{ Token: os.Getenv("DISCORD_TOKEN"), AppID: os.Getenv("DISCORD_APP_ID"), GuildID: os.Getenv("DISCORD_GUILD_ID"), PublicOrderChannelID: getenv("DISCORD_PUBLIC_ORDER_CHANNEL_ID", os.Getenv("DISCORD_ORDER_CHANNEL_ID")), InternalOrderChannelID: getenv("DISCORD_INTERNAL_ORDER_CHANNEL_ID", getenv("DISCORD_ORDER_CHANNEL_ID", "")), AuditChannelID: os.Getenv("DISCORD_AUDIT_CHANNEL_ID"), AdminRoleIDs: splitCSV(os.Getenv("DISCORD_ADMIN_ROLE_IDS")), TeamRoleIDs: splitCSV(os.Getenv("DISCORD_TEAM_ROLE_IDS")), DatabasePath: getenv("DATABASE_PATH", "orders.db"), ThreadDeleteAfter: durationHoursEnv("THREAD_DELETE_AFTER_HOURS", 72), } if cfg.Token == "" || cfg.AppID == "" || cfg.InternalOrderChannelID == "" { log.Fatal("Bitte DISCORD_TOKEN, DISCORD_APP_ID und DISCORD_INTERNAL_ORDER_CHANNEL_ID setzen") } if len(cfg.AdminRoleIDs) == 0 { log.Println("WARNUNG: DISCORD_ADMIN_ROLE_IDS ist leer. Admin-Kommandos sind nur fuer Server-Administratoren verfuegbar.") } return cfg } func getenv(key, fallback string) string { if v := os.Getenv(key); v != "" { return v } return fallback } func splitCSV(v string) []string { var out []string for _, p := range strings.Split(v, ",") { p = strings.TrimSpace(p) if p != "" { out = append(out, p) } } return out } func durationHoursEnv(key string, fallbackHours int) time.Duration { v := strings.TrimSpace(os.Getenv(key)) if v == "" { return time.Duration(fallbackHours) * time.Hour } hours, err := strconv.Atoi(v) if err != nil || hours < 0 { log.Printf("WARNUNG: %s ist ungültig, verwende %d Stunden", key, fallbackHours) return time.Duration(fallbackHours) * time.Hour } return time.Duration(hours) * time.Hour }