diff --git a/config.example.yaml b/config.example.yaml index 00896f4..c9161f6 100644 --- a/config.example.yaml +++ b/config.example.yaml @@ -86,3 +86,10 @@ ai: model: gpt-4o-mini timeout: 30 max_concurrent: 3 + +# FlareSolverr 配置(用于绕过 Cloudflare/WAF 保护) +flaresolverr: + enabled: false + url: "http://localhost:8191" # FlareSolverr 服务地址 + session: "mediastation" # 会话名称(可选,保持 cookie 持久化) + timeout: 60 # 请求超时(秒) diff --git a/internal/config/config.go b/internal/config/config.go index 0aac54c..e7ffcc5 100644 --- a/internal/config/config.go +++ b/internal/config/config.go @@ -31,6 +31,7 @@ type Config struct { Media MediaConfig `mapstructure:"media"` Transcoder TranscoderConfig `mapstructure:"transcoder"` AI AIConfig `mapstructure:"ai"` + FlareSolverr FlareSolverrConfig `mapstructure:"flaresolverr"` ApiConfig ApiConfigConfig `mapstructure:"api_config"` } @@ -129,6 +130,14 @@ type AIConfig struct { MaxConcurrent int `mapstructure:"max_concurrent"` } +// FlareSolverrConfig 配置 FlareSolverr 服务(用于绕过 Cloudflare/WAF)。 +type FlareSolverrConfig struct { + Enabled bool `mapstructure:"enabled"` + URL string `mapstructure:"url"` + Session string `mapstructure:"session"` + Timeout int `mapstructure:"timeout"` +} + // Load 从默认值 / 文件 / 环境读取配置。 // // 即使没有文件也始终返回可用的 Config。 @@ -212,6 +221,11 @@ func setDefaults(v *viper.Viper) { v.SetDefault("ai.timeout", 30) v.SetDefault("ai.max_concurrent", 3) + v.SetDefault("flaresolverr.enabled", false) + v.SetDefault("flaresolverr.url", "http://localhost:8191") + v.SetDefault("flaresolverr.session", "mediastation") + v.SetDefault("flaresolverr.timeout", 60) + v.SetDefault("transcoder.encoder", "") v.SetDefault("transcoder.preset", "veryfast") v.SetDefault("transcoder.video_bitrate", "1500k") diff --git a/internal/service/service.go b/internal/service/service.go index 34027a3..1341e02 100644 --- a/internal/service/service.go +++ b/internal/service/service.go @@ -118,7 +118,13 @@ func New(cfg *config.Config, log *zap.Logger, repos *repository.Container) *Cont apiConfigSvc := NewApiConfigService(cfg, log, repos, crypto) downloadMgr := NewDownloadManager(log, repos, crypto) notifySvc := NewNotifyService(log, repos, crypto) - siteSvc := NewSiteService(log, repos) + + // 构建 FlareSolverr URL(如果启用) + flareSolverrURL := "" + if cfg.FlareSolverr.Enabled && cfg.FlareSolverr.URL != "" { + flareSolverrURL = cfg.FlareSolverr.URL + } + siteSvc := NewSiteService(log, repos, flareSolverrURL) ctx, cancel := context.WithCancel(context.Background()) diff --git a/internal/service/site.go b/internal/service/site.go index 3363ad0..ecbb3ae 100644 --- a/internal/service/site.go +++ b/internal/service/site.go @@ -21,13 +21,14 @@ import ( // SiteService manages PT/BT site configurations. type SiteService struct { - log *zap.Logger - repo *repository.Container + log *zap.Logger + repo *repository.Container + flareSolverrURL string } // NewSiteService is the constructor. -func NewSiteService(log *zap.Logger, repo *repository.Container) *SiteService { - return &SiteService{log: log, repo: repo} +func NewSiteService(log *zap.Logger, repo *repository.Container, flareSolverrURL string) *SiteService { + return &SiteService{log: log, repo: repo, flareSolverrURL: flareSolverrURL} } // Create persists a new site. @@ -88,9 +89,8 @@ func (s *SiteService) TestConnection(ctx context.Context, id string) (bool, stri timeout = 15 } - // TODO: Get flareSolverrURL from config (e.g. from config.yaml) - // For now, pass empty string to skip FlareSolverr - flareSolverrURL := "" // TODO: load from config + // Use configured FlareSolverr URL (may be empty if not configured) + flareSolverrURL := s.flareSolverrURL ok, msg, err := helper.TestSiteConnectivity(site, flareSolverrURL, timeout, s.log) if err != nil {