first commit
This commit is contained in:
171
internal/config/config.go
Normal file
171
internal/config/config.go
Normal file
@@ -0,0 +1,171 @@
|
||||
package config
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"github.com/joho/godotenv"
|
||||
)
|
||||
|
||||
type LightningConfig struct {
|
||||
Enabled bool
|
||||
LNbitsURL string
|
||||
LNbitsInvoiceKey string
|
||||
PriceYearlySats int64
|
||||
PriceLifetimeSats int64
|
||||
InvoiceExpiryMins int
|
||||
}
|
||||
|
||||
type NostrConfig struct {
|
||||
Relays []string
|
||||
UsernameSyncEnabled bool
|
||||
SyncIntervalMins int
|
||||
}
|
||||
|
||||
type DMConfig struct {
|
||||
Enabled bool
|
||||
Nsec string
|
||||
Kind int
|
||||
MessagesFile string
|
||||
}
|
||||
|
||||
type ExpiryConfig struct {
|
||||
ReminderDays []int
|
||||
GraceDays int
|
||||
CronHourUTC int
|
||||
}
|
||||
|
||||
type WebhookConfig struct {
|
||||
URL string
|
||||
Secret string
|
||||
TimeoutSecs int
|
||||
MaxRetries int
|
||||
}
|
||||
|
||||
type Config struct {
|
||||
Domain string
|
||||
Port int
|
||||
AdminAPIKey string
|
||||
FrontendURL string
|
||||
DatabasePath string
|
||||
|
||||
Lightning LightningConfig
|
||||
Nostr NostrConfig
|
||||
DM DMConfig
|
||||
Expiry ExpiryConfig
|
||||
Webhook WebhookConfig
|
||||
|
||||
LogLevel string
|
||||
RateLimitPerMin int
|
||||
ReservedUsernames []string
|
||||
}
|
||||
|
||||
func Load() (*Config, error) {
|
||||
_ = godotenv.Load()
|
||||
|
||||
c := &Config{
|
||||
Domain: env("DOMAIN", ""),
|
||||
Port: envInt("PORT", 8080),
|
||||
AdminAPIKey: env("ADMIN_API_KEY", ""),
|
||||
FrontendURL: env("FRONTEND_URL", ""),
|
||||
DatabasePath: env("DATABASE_PATH", ".data/nip05.db"),
|
||||
Lightning: LightningConfig{
|
||||
Enabled: envBool("LIGHTNING_ENABLED", true),
|
||||
LNbitsURL: env("LNBITS_URL", ""),
|
||||
LNbitsInvoiceKey: env("LNBITS_INVOICE_KEY", ""),
|
||||
PriceYearlySats: int64(envInt("PRICE_YEARLY_SATS", 1000)),
|
||||
PriceLifetimeSats: int64(envInt("PRICE_LIFETIME_SATS", 10000)),
|
||||
InvoiceExpiryMins: envInt("INVOICE_EXPIRY_MINUTES", 30),
|
||||
},
|
||||
Nostr: NostrConfig{
|
||||
Relays: csv(env("RELAYS", "")),
|
||||
UsernameSyncEnabled: envBool("USERNAME_SYNC_ENABLED", true),
|
||||
SyncIntervalMins: envInt("SYNC_INTERVAL_MINUTES", 15),
|
||||
},
|
||||
DM: DMConfig{
|
||||
Enabled: envBool("DM_ENABLED", true),
|
||||
Nsec: env("DM_NSEC", ""),
|
||||
Kind: envInt("DM_KIND", 1059),
|
||||
MessagesFile: env("MESSAGES_FILE", "messages.yaml"),
|
||||
},
|
||||
Expiry: ExpiryConfig{
|
||||
ReminderDays: csvInt(env("EXPIRY_REMINDER_DAYS", "7")),
|
||||
GraceDays: envInt("USERNAME_GRACE_DAYS", 30),
|
||||
CronHourUTC: envInt("EXPIRY_CRON_HOUR_UTC", 9),
|
||||
},
|
||||
Webhook: WebhookConfig{
|
||||
URL: env("WEBHOOK_URL", ""),
|
||||
Secret: env("WEBHOOK_SECRET", ""),
|
||||
TimeoutSecs: envInt("WEBHOOK_TIMEOUT_SECONDS", 10),
|
||||
MaxRetries: envInt("WEBHOOK_MAX_RETRIES", 5),
|
||||
},
|
||||
LogLevel: env("LOG_LEVEL", "info"),
|
||||
RateLimitPerMin: envInt("RATE_LIMIT_PER_MIN", 30),
|
||||
ReservedUsernames: csv(env("RESERVED_USERNAMES", "")),
|
||||
}
|
||||
|
||||
if err := Validate(c); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return c, nil
|
||||
}
|
||||
|
||||
func env(key, def string) string {
|
||||
if v, ok := os.LookupEnv(key); ok && v != "" {
|
||||
return v
|
||||
}
|
||||
return def
|
||||
}
|
||||
|
||||
func envInt(key string, def int) int {
|
||||
if v, ok := os.LookupEnv(key); ok && v != "" {
|
||||
if n, err := strconv.Atoi(v); err == nil {
|
||||
return n
|
||||
}
|
||||
}
|
||||
return def
|
||||
}
|
||||
|
||||
func envBool(key string, def bool) bool {
|
||||
if v, ok := os.LookupEnv(key); ok && v != "" {
|
||||
switch strings.ToLower(v) {
|
||||
case "1", "true", "yes", "on":
|
||||
return true
|
||||
case "0", "false", "no", "off":
|
||||
return false
|
||||
}
|
||||
}
|
||||
return def
|
||||
}
|
||||
|
||||
func csv(v string) []string {
|
||||
if v == "" {
|
||||
return nil
|
||||
}
|
||||
parts := strings.Split(v, ",")
|
||||
out := make([]string, 0, len(parts))
|
||||
for _, p := range parts {
|
||||
p = strings.TrimSpace(p)
|
||||
if p != "" {
|
||||
out = append(out, p)
|
||||
}
|
||||
}
|
||||
return out
|
||||
}
|
||||
|
||||
func csvInt(v string) []int {
|
||||
parts := csv(v)
|
||||
out := make([]int, 0, len(parts))
|
||||
for _, p := range parts {
|
||||
n, err := strconv.Atoi(p)
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
out = append(out, n)
|
||||
}
|
||||
return out
|
||||
}
|
||||
|
||||
func (c *Config) Addr() string { return fmt.Sprintf(":%d", c.Port) }
|
||||
Reference in New Issue
Block a user