package rss import ( "errors" "local/rssmon3/config" "log" "net/http" "regexp" "time" "github.com/mmcdole/gofeed" ) const NSFeeds = "NSFeeds" type Feed struct { Key string URL string Updated time.Time TitleFilter string ContentFilter string Tags []string } func newFeed(key string) *Feed { return &Feed{ Key: key, } } func (f *Feed) Encode() ([]byte, error) { return config.Encode(f) } func (f *Feed) Decode(b []byte) error { return config.Decode(b, f) } func (f *Feed) load() error { if f.Key == "" { return errors.New("cannot load nil feed") } db := config.Values().DB b, err := db.Get(f.Key, NSFeeds) if err != nil { return err } return f.Decode(b) } func (f *Feed) pull() error { if f.URL == "" { if err := f.load(); err != nil { return err } } resp, err := http.Get(f.URL) if err != nil { return err } defer resp.Body.Close() gofeed, err := gofeed.NewParser().Parse(resp.Body) if err != nil { return err } itemTSs := []*time.Time{} for _, i := range gofeed.Items { item, err := newItem(i, f.ContentFilter) if err != nil { log.Println(err) continue } itemTSs = append(itemTSs, &item.TS) if item.TS.Before(f.Updated) { log.Println("Skipping old item") continue } if ok := regexp.MustCompile(f.TitleFilter).MatchString(item.Title); !ok { log.Println("Skipping bad titled item") continue } if err := item.save(); err != nil { log.Println(err) continue } } f.Updated = latestTSPtr(gofeed.PublishedParsed, gofeed.UpdatedParsed) f.Updated = latestTSPtr(append(itemTSs, &f.Updated)...) return nil } func (f *Feed) save() error { b, err := f.Encode() if err != nil { return err } db := config.Values().DB return db.Set(f.Key, b, NSFeeds) } func latestTSPtr(times ...*time.Time) time.Time { var t time.Time for i := range times { if times[i] == nil { continue } if times[i].After(t) { t = *times[i] } } return t }