package proxy import ( "context" "fmt" "log/slog" "math/rand" "os" "time" "gitea.timerzz.com/timerzz/proxy-detector/config" "gitea.timerzz.com/timerzz/proxy-detector/pkg/getter" "gitea.timerzz.com/timerzz/proxy-detector/pkg/proxy/structs" "github.com/golang/glog" ) type Pool struct { proxies structs.Proxies cfg *Option updated time.Time } func InitDefaultProxyPool() (*Pool, error) { path := os.Getenv(ProxyConfigEnv) if path == "" { path = DefaultProxyConfigPath } cfg, err := LoadProxyConfig(path) if err != nil { return nil, fmt.Errorf("获取代理池配置失败:%v", err) } return NewProxyPool(cfg), nil } func NewProxyPool(cfg *Option) *Pool { var p = &Pool{} p.cfg = cfg p.Update() return p } func (p *Pool) Status() ([]structs.Proxy, time.Time) { return p.proxies.Get(), p.updated } // Update 更新代理池 func (p *Pool) Update() { var list = make([]structs.Proxy, 0, p.proxies.Len()) var getters = make([]getter.Getter, 0, len(p.cfg.Clash)+len(p.cfg.Subscribes)) for _, url := range p.cfg.Subscribes { gtr, err := getter.NewSubscribeGetter(config.CrawOption{ Url: url, }) if err != nil { slog.Warn(fmt.Sprintf("创建Subscribe Getter失败:%v", err)) continue } getters = append(getters, gtr) } for _, url := range p.cfg.Clash { gtr, err := getter.NewClashGetter(config.CrawOption{Url: url}) if err != nil { slog.Warn(fmt.Sprintf("创建Clash Getter失败:%v", err)) continue } getters = append(getters, gtr) } for _, gtr := range getters { list = append(list, gtr.Get()...) } glog.Infof("代理源共 %d 个: %v", len(p.cfg.Subscribes), p.cfg.Subscribes) glog.Infof("获取代理共 %d 个", len(list)) p.proxies.Replace(list) p.updated = time.Now() } // CronUpdate 定时更新 func (p *Pool) CronUpdate(ctx context.Context) { if p.cfg.Interval == 0 { p.cfg.Interval = time.Minute * 30 } ticker := time.NewTicker(p.cfg.Interval) defer ticker.Stop() for { select { case <-ctx.Done(): return case <-ticker.C: p.Update() } } } // RandomIterator 获取随机代理的迭代器 func (p *Pool) RandomIterator() func() *structs.Proxy { proxies := p.proxies.Get() return func() (proxy *structs.Proxy) { if len(proxies) == 0 { return nil } curIndex := rand.Intn(len(proxies)) return &proxies[curIndex] } }