package notifier import ( "bytes" "log" "net/http" "time" "mediawatcher/internal/classifier" "mediawatcher/internal/config" ) type Notifier struct { cfg *config.NotifierConfig cli *http.Client } func New(cfg *config.NotifierConfig) *Notifier { if cfg == nil || !cfg.Enabled { return nil } return &Notifier{ cfg: cfg, cli: &http.Client{Timeout: 10 * time.Second}, } } func (n *Notifier) Notify(res classifier.Result) { if n == nil || !n.cfg.Enabled { return } for _, ep := range n.cfg.Endpoints { if err := n.callEndpoint(ep, res); err != nil { log.Printf("[notify] %s error: %v", ep.Name, err) } } } func (n *Notifier) callEndpoint(ep config.NotifierEndpoint, res classifier.Result) error { if ep.URL == "" { return nil } method := ep.Method if method == "" { method = http.MethodPost } body := []byte(ep.Body) req, err := http.NewRequest(method, ep.URL, bytes.NewReader(body)) if err != nil { return err } for k, v := range ep.Headers { req.Header.Set(k, v) } if req.Header.Get("Content-Type") == "" && len(body) > 0 { req.Header.Set("Content-Type", "application/json") } resp, err := n.cli.Do(req) if err != nil { return err } defer resp.Body.Close() if resp.StatusCode >= 300 { log.Printf("[notify] %s returned status %d", ep.Name, resp.StatusCode) } return nil }