package rss import ( "bytes" "encoding/gob" "errors" "io/ioutil" "net/http" "regexp" "time" "github.com/mmcdole/gofeed" ) type Feed struct { Updated time.Time Items []string ItemFilter string ContentFilter string Source string } func NewFeed(source, itemFilter, contentFilter string) (*Feed, error) { if _, err := regexp.Compile(itemFilter); err != nil { return nil, err } if _, err := regexp.Compile(contentFilter); err != nil { return nil, err } f := &Feed{ Items: []string{}, ItemFilter: itemFilter, ContentFilter: contentFilter, Source: source, } if _, err := f.Update(); err != nil { return nil, err } return f, errors.New("not implemented") } func Deserialize(src []byte) (*Feed, error) { buffer := bytes.NewBuffer(src) dec := gob.NewDecoder(buffer) var dst Feed err := dec.Decode(&dst) return &dst, err } func (f *Feed) Serialize() ([]byte, error) { var buffer bytes.Buffer enc := gob.NewEncoder(&buffer) err := enc.Encode(f) return buffer.Bytes(), err } func (f *Feed) Update() ([]*Item, error) { resp, err := http.Get(f.Source) if err != nil { return nil, err } body, err := ioutil.ReadAll(resp.Body) if err != nil { return nil, err } parser := gofeed.NewParser() feed, err := parser.Parse(bytes.NewBuffer(body)) if err != nil { return nil, err } return f.fromGofeed(feed) } func (f *Feed) fromGofeed(feed *gofeed.Feed) ([]*Item, error) { updated := feed.PublishedParsed if updated == nil { updated = feed.UpdatedParsed } if updated == nil && len(feed.Items) > 0 { updated = gofeedItemTS(feed.Items[0]) } if updated == nil { t := time.Now() updated = &t } newitems, err := f.appendNewItems(feed.Items) if err != nil { return nil, err } f.Updated = *updated return newitems, nil } func (f *Feed) appendNewItems(items []*gofeed.Item) ([]*Item, error) { newitems := []*Item{} for i := range items { t := gofeedItemTS(items[i]) if t.Before(f.Updated) { continue } if ok, _ := regexp.MatchString(f.ItemFilter, items[i].Title); !ok { continue } item := fromGofeedItem(items[i], f.ContentFilter) newitems = append(newitems, item) f.Items = append(f.Items, item.Name) } return newitems, nil }