package rss import ( "bytes" "encoding/gob" "fmt" "io/ioutil" "net/http" "regexp" "strings" "time" "github.com/mmcdole/gofeed" ) type Feed struct { Updated time.Time Items []string ItemFilter string ContentFilter string Link string } func (feed *Feed) String() string { return fmt.Sprintf("Updated: %v, Items: %v, ItemFilter: %q, ContentFilter: %q, Link; %v", feed.Updated.Local(), feed.Items, feed.ItemFilter, feed.ContentFilter, feed.Link, ) } func (feed *Feed) ID() string { return strings.Join(regexp.MustCompile("[a-zA-Z0-9]*").FindAllString(feed.Link, -1), "_") } func NewFeed(source, itemFilter, contentFilter string) (*Feed, []*Item, error) { if _, err := regexp.Compile(itemFilter); err != nil { return nil, nil, err } if _, err := regexp.Compile(contentFilter); err != nil { return nil, nil, err } f := &Feed{ Items: []string{}, ItemFilter: itemFilter, ContentFilter: contentFilter, Link: source, } items, err := f.Update() if err != nil { return nil, nil, err } return f, items, nil } 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 (feed *Feed) Serialize() ([]byte, error) { var buffer bytes.Buffer enc := gob.NewEncoder(&buffer) err := enc.Encode(feed) return buffer.Bytes(), err } func (feed *Feed) Update() ([]*Item, error) { resp, err := http.Get(feed.Link) if err != nil { return nil, err } body, err := ioutil.ReadAll(resp.Body) if err != nil { return nil, err } parser := gofeed.NewParser() gofeed, err := parser.Parse(bytes.NewBuffer(body)) if err != nil { return nil, err } return feed.fromGofeed(gofeed) } func (feed *Feed) fromGofeed(gofeed *gofeed.Feed) ([]*Item, error) { updated := gofeed.PublishedParsed if updated == nil { updated = gofeed.UpdatedParsed } if updated == nil && len(gofeed.Items) > 0 { updated = gofeedItemTS(gofeed.Items[0]) } if updated == nil { t := time.Now() updated = &t } newitems, err := feed.appendNewItems(gofeed.Items) if err != nil { return nil, err } feed.Updated = *updated return newitems, nil } func (feed *Feed) appendNewItems(items []*gofeed.Item) ([]*Item, error) { newitems := []*Item{} for i := range items { t := gofeedItemTS(items[i]) if t.Before(feed.Updated) { continue } if ok, _ := regexp.MatchString(feed.ItemFilter, items[i].Title); !ok { continue } item := fromGofeedItem(items[i], feed.ContentFilter) newitems = append(newitems, item) feed.Items = append(feed.Items, item.Name) } return newitems, nil }