package config import ( "encoding/json" "os" ) // Config represents the application configuration type Config struct { Server ServerConfig `json:"server"` WhatsApp []WhatsAppConfig `json:"whatsapp"` Hooks []Hook `json:"hooks"` Database DatabaseConfig `json:"database,omitempty"` Media MediaConfig `json:"media"` EventLogger EventLoggerConfig `json:"event_logger,omitempty"` MessageCache MessageCacheConfig `json:"message_cache,omitempty"` LogLevel string `json:"log_level"` } // ServerConfig holds server-specific configuration type ServerConfig struct { Host string `json:"host"` Port int `json:"port"` DefaultCountryCode string `json:"default_country_code,omitempty"` Username string `json:"username,omitempty"` Password string `json:"password,omitempty"` AuthKey string `json:"auth_key,omitempty"` TLS TLSConfig `json:"tls,omitempty"` } // TLSConfig holds TLS/HTTPS configuration type TLSConfig struct { Enabled bool `json:"enabled"` // Enable HTTPS Mode string `json:"mode"` // "self-signed", "custom", or "autocert" CertFile string `json:"cert_file,omitempty"` // Path to certificate file (for custom mode) KeyFile string `json:"key_file,omitempty"` // Path to key file (for custom mode) // Self-signed certificate options CertDir string `json:"cert_dir,omitempty"` // Directory to store generated certificates // Let's Encrypt / autocert options Domain string `json:"domain,omitempty"` // Domain name for Let's Encrypt Email string `json:"email,omitempty"` // Email for Let's Encrypt notifications CacheDir string `json:"cache_dir,omitempty"` // Cache directory for autocert Production bool `json:"production,omitempty"` // Use Let's Encrypt production (default: staging) } // WhatsAppConfig holds configuration for a WhatsApp account type WhatsAppConfig struct { ID string `json:"id"` Type string `json:"type"` // "whatsmeow" or "business-api" PhoneNumber string `json:"phone_number"` SessionPath string `json:"session_path,omitempty"` ShowQR bool `json:"show_qr,omitempty"` BusinessAPI *BusinessAPIConfig `json:"business_api,omitempty"` } // BusinessAPIConfig holds configuration for WhatsApp Business API type BusinessAPIConfig struct { PhoneNumberID string `json:"phone_number_id"` AccessToken string `json:"access_token"` BusinessAccountID string `json:"business_account_id,omitempty"` APIVersion string `json:"api_version,omitempty"` // Default: v21.0 WebhookPath string `json:"webhook_path,omitempty"` VerifyToken string `json:"verify_token,omitempty"` } // Hook represents a registered webhook type Hook struct { ID string `json:"id"` Name string `json:"name"` URL string `json:"url"` Method string `json:"method"` Headers map[string]string `json:"headers,omitempty"` Active bool `json:"active"` Events []string `json:"events,omitempty"` Description string `json:"description,omitempty"` } // DatabaseConfig holds database connection information type DatabaseConfig struct { Type string `json:"type"` Host string `json:"host"` Port int `json:"port"` Username string `json:"username"` Password string `json:"password"` Database string `json:"database"` SQLitePath string `json:"sqlite_path,omitempty"` // Path to SQLite database file } // MediaConfig holds media storage and delivery configuration type MediaConfig struct { DataPath string `json:"data_path"` Mode string `json:"mode"` // "base64", "link", or "both" BaseURL string `json:"base_url,omitempty"` // Base URL for media links } // EventLoggerConfig holds event logging configuration type EventLoggerConfig struct { Enabled bool `json:"enabled"` Targets []string `json:"targets"` // "file", "sqlite", "postgres", "mqtt" // File-based logging FileDir string `json:"file_dir,omitempty"` // Base directory for event files // Database logging (uses main Database config for connection) TableName string `json:"table_name,omitempty"` // Table name for event logs (default: "event_logs") // MQTT logging MQTT MQTTConfig `json:"mqtt,omitempty"` // MQTT broker configuration } // MQTTConfig holds MQTT broker configuration type MQTTConfig struct { Broker string `json:"broker"` // MQTT broker URL (e.g., "tcp://localhost:1883") ClientID string `json:"client_id,omitempty"` // Client ID (auto-generated if empty) Username string `json:"username,omitempty"` // Username for authentication Password string `json:"password,omitempty"` // Password for authentication TopicPrefix string `json:"topic_prefix,omitempty"` // Topic prefix (default: "whatshooked") QoS int `json:"qos,omitempty"` // Quality of Service (0, 1, or 2; default: 1) Retained bool `json:"retained,omitempty"` // Retain messages on broker Events []string `json:"events,omitempty"` // Events to publish (empty = all events) Subscribe bool `json:"subscribe,omitempty"` // Enable subscription for sending messages } // MessageCacheConfig holds message cache configuration type MessageCacheConfig struct { Enabled bool `json:"enabled"` // Enable message caching DataPath string `json:"data_path,omitempty"` // Directory to store cached events MaxAgeDays int `json:"max_age_days,omitempty"` // Maximum age in days before purging (default: 7) MaxEvents int `json:"max_events,omitempty"` // Maximum number of events to cache (default: 10000) } // Load reads configuration from a file func Load(path string) (*Config, error) { data, err := os.ReadFile(path) if err != nil { return nil, err } var cfg Config if err := json.Unmarshal(data, &cfg); err != nil { return nil, err } // Set defaults if cfg.LogLevel == "" { cfg.LogLevel = "info" } if cfg.Server.Host == "" { cfg.Server.Host = "localhost" } if cfg.Server.Port == 0 { cfg.Server.Port = 8080 } if cfg.Media.DataPath == "" { cfg.Media.DataPath = "./data/media" } if cfg.Media.Mode == "" { cfg.Media.Mode = "link" } if cfg.EventLogger.FileDir == "" { cfg.EventLogger.FileDir = "./data/events" } if cfg.EventLogger.TableName == "" { cfg.EventLogger.TableName = "event_logs" } if cfg.Database.SQLitePath == "" { cfg.Database.SQLitePath = "./data/events.db" } // Default WhatsApp account type to whatsmeow for backwards compatibility for i := range cfg.WhatsApp { if cfg.WhatsApp[i].Type == "" { cfg.WhatsApp[i].Type = "whatsmeow" } // Set default API version for Business API if cfg.WhatsApp[i].Type == "business-api" && cfg.WhatsApp[i].BusinessAPI != nil { if cfg.WhatsApp[i].BusinessAPI.APIVersion == "" { cfg.WhatsApp[i].BusinessAPI.APIVersion = "v21.0" } } } // Set TLS defaults if enabled if cfg.Server.TLS.Enabled { if cfg.Server.TLS.Mode == "" { cfg.Server.TLS.Mode = "self-signed" } if cfg.Server.TLS.CertDir == "" { cfg.Server.TLS.CertDir = "./data/certs" } if cfg.Server.TLS.CacheDir == "" { cfg.Server.TLS.CacheDir = "./data/autocert" } } // Set message cache defaults if cfg.MessageCache.DataPath == "" { cfg.MessageCache.DataPath = "./data/message_cache" } if cfg.MessageCache.MaxAgeDays == 0 { cfg.MessageCache.MaxAgeDays = 7 } if cfg.MessageCache.MaxEvents == 0 { cfg.MessageCache.MaxEvents = 10000 } return &cfg, nil } // Save writes configuration to a file func Save(path string, cfg *Config) error { data, err := json.MarshalIndent(cfg, "", " ") if err != nil { return err } return os.WriteFile(path, data, 0644) }