Files
ai_wht_wechat/go_backend/config/config.go

160 lines
5.7 KiB
Go
Raw Normal View History

2025-12-19 22:36:48 +08:00
package config
import (
"fmt"
"log"
"os"
"github.com/spf13/viper"
)
type Config struct {
Server ServerConfig `mapstructure:"server"`
Database DatabaseConfig `mapstructure:"database"`
JWT JWTConfig `mapstructure:"jwt"`
Wechat WechatConfig `mapstructure:"wechat"`
XHS XHSConfig `mapstructure:"xhs"`
Scheduler SchedulerConfig `mapstructure:"scheduler"`
}
type ServerConfig struct {
Port int `mapstructure:"port"`
Mode string `mapstructure:"mode"`
}
type DatabaseConfig struct {
Host string `mapstructure:"host"`
Port int `mapstructure:"port"`
Username string `mapstructure:"username"`
Password string `mapstructure:"password"`
DBName string `mapstructure:"dbname"`
Charset string `mapstructure:"charset"`
ParseTime bool `mapstructure:"parse_time"`
Loc string `mapstructure:"loc"`
MaxIdleConns int `mapstructure:"max_idle_conns"`
MaxOpenConns int `mapstructure:"max_open_conns"`
ConnMaxLifetime int `mapstructure:"conn_max_lifetime"`
}
type JWTConfig struct {
Secret string `mapstructure:"secret"`
ExpireHours int `mapstructure:"expire_hours"`
}
type WechatConfig struct {
AppID string `mapstructure:"app_id"`
AppSecret string `mapstructure:"app_secret"`
}
type XHSConfig struct {
PythonServiceURL string `mapstructure:"python_service_url"`
}
type SchedulerConfig struct {
Enabled bool `mapstructure:"enabled"` // 是否启用定时任务
PublishCron string `mapstructure:"publish_cron"` // 发布任务的Cron表达式
MaxConcurrent int `mapstructure:"max_concurrent"` // 最大并发发布数
PublishTimeout int `mapstructure:"publish_timeout"` // 发布超时时间(秒)
MaxArticlesPerUserPerRun int `mapstructure:"max_articles_per_user_per_run"` // 每轮每个用户最大发文数
MaxFailuresPerUserPerRun int `mapstructure:"max_failures_per_user_per_run"` // 每轮每个用户最大失败次数
MaxDailyArticlesPerUser int `mapstructure:"max_daily_articles_per_user"` // 每个用户每日最大发文数
MaxHourlyArticlesPerUser int `mapstructure:"max_hourly_articles_per_user"` // 每个用户每小时最大发文数
Proxy string `mapstructure:"proxy"` // 全局代理地址(可选)
UserAgent string `mapstructure:"user_agent"` // 全局User-Agent可选
ProxyFetchURL string `mapstructure:"proxy_fetch_url"` // 动态获取代理的接口地址(可选)
}
var AppConfig *Config
// LoadConfig 加载配置文件
// 优先级: 环境变量 > 配置文件
func LoadConfig(env string) error {
// 1. 优先从环境变量 APP_ENV 获取环境配置
if envFromEnv := os.Getenv("APP_ENV"); envFromEnv != "" {
env = envFromEnv
log.Printf("从环境变量 APP_ENV 读取环境: %s", env)
}
if env == "" {
env = "dev"
}
// 2. 加载配置文件
viper.SetConfigName(fmt.Sprintf("config.%s", env))
viper.SetConfigType("yaml")
viper.AddConfigPath("./config")
viper.AddConfigPath("../config")
if err := viper.ReadInConfig(); err != nil {
return fmt.Errorf("读取配置文件失败: %w", err)
}
// 3. 绑定环境变量(自动读取环境变量覆盖配置)
viper.AutomaticEnv()
// 绑定特定的环境变量到配置项
bindEnvVariables()
AppConfig = &Config{}
if err := viper.Unmarshal(AppConfig); err != nil {
return fmt.Errorf("解析配置文件失败: %w", err)
}
log.Printf("配置加载成功: %s 环境", env)
log.Printf("数据库配置: %s@%s:%d/%s", AppConfig.Database.Username, AppConfig.Database.Host, AppConfig.Database.Port, AppConfig.Database.DBName)
return nil
}
// bindEnvVariables 绑定环境变量到配置项
func bindEnvVariables() {
// Server 配置
viper.BindEnv("server.port", "SERVER_PORT")
viper.BindEnv("server.mode", "SERVER_MODE")
// Database 配置
viper.BindEnv("database.host", "DB_HOST")
viper.BindEnv("database.port", "DB_PORT")
viper.BindEnv("database.username", "DB_USERNAME")
viper.BindEnv("database.password", "DB_PASSWORD")
viper.BindEnv("database.dbname", "DB_NAME")
viper.BindEnv("database.charset", "DB_CHARSET")
// JWT 配置
viper.BindEnv("jwt.secret", "JWT_SECRET")
viper.BindEnv("jwt.expire_hours", "JWT_EXPIRE_HOURS")
// Wechat 配置
viper.BindEnv("wechat.app_id", "WECHAT_APP_ID")
viper.BindEnv("wechat.app_secret", "WECHAT_APP_SECRET")
// XHS 配置
viper.BindEnv("xhs.python_service_url", "XHS_PYTHON_SERVICE_URL")
// Scheduler 配置
viper.BindEnv("scheduler.enabled", "SCHEDULER_ENABLED")
viper.BindEnv("scheduler.publish_cron", "SCHEDULER_PUBLISH_CRON")
viper.BindEnv("scheduler.max_concurrent", "SCHEDULER_MAX_CONCURRENT")
viper.BindEnv("scheduler.publish_timeout", "SCHEDULER_PUBLISH_TIMEOUT")
viper.BindEnv("scheduler.max_articles_per_user_per_run", "SCHEDULER_MAX_ARTICLES_PER_USER_PER_RUN")
viper.BindEnv("scheduler.max_failures_per_user_per_run", "SCHEDULER_MAX_FAILURES_PER_USER_PER_RUN")
viper.BindEnv("scheduler.max_daily_articles_per_user", "SCHEDULER_MAX_DAILY_ARTICLES_PER_USER")
viper.BindEnv("scheduler.max_hourly_articles_per_user", "SCHEDULER_MAX_HOURLY_ARTICLES_PER_USER")
viper.BindEnv("scheduler.proxy", "SCHEDULER_PROXY")
viper.BindEnv("scheduler.user_agent", "SCHEDULER_USER_AGENT")
viper.BindEnv("scheduler.proxy_fetch_url", "SCHEDULER_PROXY_FETCH_URL")
}
// GetDSN 获取数据库连接字符串
func (c *DatabaseConfig) GetDSN() string {
return fmt.Sprintf("%s:%s@tcp(%s:%d)/%s?charset=%s&parseTime=%t&loc=%s",
c.Username,
c.Password,
c.Host,
c.Port,
c.DBName,
c.Charset,
c.ParseTime,
c.Loc,
)
}