Diffstat (limited to 'config')
| -rw-r--r-- | config/config.go | 154 |
1 files changed, 154 insertions, 0 deletions
diff --git a/config/config.go b/config/config.go new file mode 100644 index 0000000..64d2e76 --- /dev/null +++ b/config/config.go @@ -0,0 +1,154 @@ +package config + +import ( + "encoding/json" + "fmt" + "log/slog" + "os" + + "github.com/go-playground/validator/v10" +) + +type Config struct { + LogLevel slog.Level `json:"LogLevel" validate:"required"` + MaxConcurrentJobs int `json:"MaxConcurrentJobs" validate:"required,min=1"` + DraftDir string `json:"DraftDir" validate:"required"` + DraftSuffix string `json:"DraftSuffix" validate:"required"` + Transcoders []TranscoderConfig `json:"Transcoders" validate:"required,min=1,dive"` +} + +type TranscoderConfig struct { + Type string `json:"Type" validate:"required,oneof=sayauz telegram"` + Config any `json:"Config" validate:"required"` +} + +func (tc *TranscoderConfig) UnmarshalJSON(data []byte) error { + var tmp struct { + Type string `json:"Type"` + Config json.RawMessage `json:"Config"` + } + + if err := json.Unmarshal(data, &tmp); err != nil { + return err + } + + tc.Type = tmp.Type + + switch tmp.Type { + case "sayauz": + var sayauzConfig SayauzConfig + if err := json.Unmarshal(tmp.Config, &sayauzConfig); err != nil { + return fmt.Errorf("unmarshal SayauzConfig: %w", err) + } + tc.Config = &sayauzConfig + case "telegram": + var telegramConfig TelegramConfig + if err := json.Unmarshal(tmp.Config, &telegramConfig); err != nil { + return fmt.Errorf("unmarshal TelegramConfig: %w", err) + } + tc.Config = &telegramConfig + default: + return fmt.Errorf("unsupported transcoder type: %s", tmp.Type) + } + + return nil +} + +type SayauzConfig struct { + Category string `json:"Category" validate:"required,min=1"` + Storage StorageConfig `json:"Storage" validate:"required"` +} + +type TelegramConfig struct { + BotToken string `json:"BotToken" validate:"required,min=1"` + ChannelID int `json:"ChannelID" validate:"required,ne=0"` + GroupID int `json:"GroupID"` + ImageBaseURL string `json:"ImageBaseURL" validate:"required,min=1"` + PreviewBaseURL string `json:"PreviewBaseURL"` + PreviewExtension string `json:"PreviewExtension"` + StateDir string `json:"StateDir" validate:"required,min=1"` +} + +type StorageConfig struct { + Type string `json:"Type" validate:"required,oneof=b2 s3"` + Config any `json:"Config" validate:"required"` +} + +func (sc *StorageConfig) UnmarshalJSON(data []byte) error { + var tmp struct { + Type string `json:"Type"` + Config json.RawMessage `json:"Config"` + } + + if err := json.Unmarshal(data, &tmp); err != nil { + return err + } + + sc.Type = tmp.Type + + switch tmp.Type { + case "b2": + var b2Config B2Config + if err := json.Unmarshal(tmp.Config, &b2Config); err != nil { + return fmt.Errorf("unmarshal B2Config: %w", err) + } + sc.Config = &b2Config + case "s3": + var s3Config S3Config + if err := json.Unmarshal(tmp.Config, &s3Config); err != nil { + return fmt.Errorf("unmarshal S3Config: %w", err) + } + sc.Config = &s3Config + default: + return fmt.Errorf("unsupported storage type: %s", tmp.Type) + } + + return nil +} + +type B2Config struct { + BucketName string `json:"BucketName" validate:"required,min=1"` + Region string `json:"Region" validate:"required,min=1"` + Prefix string `json:"Prefix"` + KeyID string `json:"KeyID"` + ApplicationKey string `json:"ApplicationKey"` +} + +type S3Config struct { + BucketName string `json:"BucketName" validate:"required,min=1"` + Region string `json:"Region" validate:"required,min=1"` + Prefix string `json:"Prefix"` + Endpoint string `json:"Endpoint"` + UsePathStyle bool `json:"UsePathStyle"` + AccessKeyID string `json:"AccessKeyID"` + SecretAccessKey string `json:"SecretAccessKey"` +} + +func LoadConfig(path string, config *Config) error { + fileBytes, err := os.ReadFile(path) + if err != nil { + return err + } + + expandedFileBytes := []byte(os.ExpandEnv(string(fileBytes))) + + if err = json.Unmarshal(expandedFileBytes, config); err != nil { + return err + } + + return nil +} + +func InitConfig(path string) (*Config, error) { + config := &Config{} + if err := LoadConfig(path, config); err != nil { + return nil, err + } + + validate := validator.New(validator.WithRequiredStructEnabled()) + if err := validate.Struct(config); err != nil { + return nil, err + } + + return config, nil +} |