Files
ai-mailer/config/config.go

134 lines
4.4 KiB
Go

package config
import (
"os"
"paraclub-ai-mailer/internal/logger"
"strings"
"time"
"github.com/sirupsen/logrus"
"gopkg.in/yaml.v3"
)
type Config struct {
IMAP IMAPConfig `yaml:"imap"`
AI AIConfig `yaml:"ai"`
Context ContextConfig `yaml:"context"`
Polling PollingConfig `yaml:"polling"`
Logging LoggingConfig `yaml:"logging"`
Processing ProcessingConfig `yaml:"processing"`
}
type IMAPConfig struct {
Server string `yaml:"server"`
Port int `yaml:"port"`
Username string `yaml:"username"`
Password string `yaml:"password"`
MailboxIn string `yaml:"mailbox_in"`
DraftBox string `yaml:"draft_box"`
ProcessedBox string `yaml:"processed_box"`
UseTLS bool `yaml:"use_tls"`
}
type AIConfig struct {
OpenRouterAPIKey string `yaml:"openrouter_api_key"`
Model string `yaml:"model"`
Temperature float32 `yaml:"temperature"`
MaxTokens int `yaml:"max_tokens"`
}
type ContextConfig struct {
URLs []string `yaml:"urls"`
}
type PollingConfig struct {
Interval time.Duration `yaml:"interval"`
}
type LoggingConfig struct {
Level string `yaml:"level"`
FilePath string `yaml:"file_path"`
}
type ProcessingConfig struct {
MaxTokens int `yaml:"max_tokens"` // Maximum total tokens for API request (0 = no limit)
SkipJunkEmails bool `yaml:"skip_junk_emails"` // Skip emails marked as junk/spam
}
func readFileContent(path string) (string, error) {
content, err := os.ReadFile(path)
if err != nil {
return "", err
}
return strings.TrimSpace(string(content)), nil
}
func Load(path string) (*Config, error) {
logger.WithField("path", path).Debug("Loading configuration file")
data, err := os.ReadFile(path)
if err != nil {
logger.WithError(err).Error("Failed to read configuration file")
return nil, err
}
logger.WithField("bytes", len(data)).Debug("Read configuration file")
var config Config
if err := yaml.Unmarshal(data, &config); err != nil {
logger.WithError(err).Error("Failed to parse YAML configuration")
return nil, err
}
// Handle IMAP password from environment or file
if strings.HasPrefix(config.IMAP.Password, "${") && strings.HasSuffix(config.IMAP.Password, "}") {
envVar := strings.TrimSuffix(strings.TrimPrefix(config.IMAP.Password, "${"), "}")
config.IMAP.Password = os.Getenv(envVar)
logger.WithField("envVar", envVar).Debug("Resolved IMAP password from environment")
} else if strings.HasPrefix(config.IMAP.Password, "file://") {
filePath := strings.TrimPrefix(config.IMAP.Password, "file://")
password, err := readFileContent(filePath)
if err != nil {
logger.WithError(err).Error("Failed to read IMAP password from file")
return nil, err
}
config.IMAP.Password = password
logger.WithField("path", filePath).Debug("Read IMAP password from file")
}
// Handle OpenRouter API key from environment or file
if strings.HasPrefix(config.AI.OpenRouterAPIKey, "${") && strings.HasSuffix(config.AI.OpenRouterAPIKey, "}") {
envVar := strings.TrimSuffix(strings.TrimPrefix(config.AI.OpenRouterAPIKey, "${"), "}")
config.AI.OpenRouterAPIKey = os.Getenv(envVar)
logger.WithField("envVar", envVar).Debug("Resolved OpenRouter API key from environment")
} else if strings.HasPrefix(config.AI.OpenRouterAPIKey, "file://") {
filePath := strings.TrimPrefix(config.AI.OpenRouterAPIKey, "file://")
apiKey, err := readFileContent(filePath)
if err != nil {
logger.WithError(err).Error("Failed to read OpenRouter API key from file")
return nil, err
}
config.AI.OpenRouterAPIKey = apiKey
logger.WithField("path", filePath).Debug("Read OpenRouter API key from file")
}
logger.WithFields(logrus.Fields{
"imapServer": config.IMAP.Server,
"imapPort": config.IMAP.Port,
"imapUsername": config.IMAP.Username,
"imapMailboxIn": config.IMAP.MailboxIn,
"imapDraftBox": config.IMAP.DraftBox,
"imapUseTLS": config.IMAP.UseTLS,
"aiModel": config.AI.Model,
"aiTemperature": config.AI.Temperature,
"aiMaxTokens": config.AI.MaxTokens,
"contextUrlCount": len(config.Context.URLs),
"pollingInterval": config.Polling.Interval,
"loggingLevel": config.Logging.Level,
"loggingFilePath": config.Logging.FilePath,
"maxTokens": config.Processing.MaxTokens,
"skipJunkEmails": config.Processing.SkipJunkEmails,
}).Debug("Configuration loaded successfully")
return &config, nil
}