ribbit/model_feeds.go

282 lines
5.5 KiB
Go

package main
import (
"fmt"
"plugin"
"time"
)
type FeedSource struct {
Feeds []*Feed
// Plugin Functions
getSourceName func() string
refreshFeedList func() []map[string]string
getFeedUrl func(string, time.Time) (string, error)
getFeedDesc func(string, time.Time) (string, error)
}
func LoadFeedPlugin(p *plugin.Plugin) (*FeedSource, error) {
ret := new(FeedSource)
feedSourceSymbol, err := p.Lookup("GetSourceName")
if err != nil {
return nil, err
}
ret.getSourceName = feedSourceSymbol.(func() string)
feedListSymbol, err := p.Lookup("GetFeedList")
if err != nil {
return nil, err
}
ret.refreshFeedList = feedListSymbol.(func() []map[string]string)
feeds := ret.refreshFeedList()
// `feeds` is a []map, each map should contain keys: `slug`, `name`, `author`, `source`
for _, f := range feeds {
var slug, name, author, source string
var ok bool
if slug, ok = f["slug"]; !ok {
continue
}
if name, ok = f["name"]; !ok {
continue
}
if author, ok = f["author"]; !ok {
continue
}
if source, ok = f["source"]; !ok {
continue
}
ret.Feeds = append(ret.Feeds, NewFeed(slug, name, author, source))
}
feedUrlSymbol, err := p.Lookup("GetFeedUrl")
if err != nil {
return nil, err
}
ret.getFeedUrl = feedUrlSymbol.(func(string, time.Time) (string, error))
feedDescSymbol, err := p.Lookup("GetFeedDesc")
if err != nil {
return nil, err
}
ret.getFeedDesc = feedDescSymbol.(func(string, time.Time) (string, error))
return ret, nil
}
func (f *FeedSource) getFeed(slug string) *Feed {
for i := range f.Feeds {
if f.Feeds[i].Slug == slug {
return f.Feeds[i]
}
}
return nil
}
type Feed struct {
Name string
Author string
Slug string
Source string
Desc string
LastUpdate time.Time
}
func NewFeed(s, n, a, source string) *Feed {
return &Feed{
Name: n,
Author: a,
Slug: s,
Source: source,
}
}
func (f *Feed) GetBucket() []string {
return []string{"feeds", f.Source, f.Slug}
}
func (f *Feed) Update() error {
/*
dt := time.Now()
desc, err := getFeedDesc(f.Source, f.Slug, dt)
if err != nil {
return err
}
if desc == f.Desc {
return errors.New("Feed didn't change")
}
f.Desc = desc
f.LastUpdate = dt
*/
return nil
}
func (f *Feed) GetUrl(dt time.Time) string {
var v string
/*
var e error
if v, e = getFeedUrl(f.Source, f.Slug, dt); e != nil {
return ""
}
*/
return v
}
func (f *Feed) GetDesc(dt time.Time) string {
var v string
/*
var e error
if v, e = getFeedDesc(f.Source, f.Slug, dt); e != nil {
return ""
}
*/
return v
}
func (f *Feed) GetRssItem() string {
var v string
/*
var e error
if v, e = getRssItem(f.Source, f.Slug); e != nil {
return ""
}
*/
return v
}
// DB Function to save a feed
func (m *model) SaveFeed(f *Feed) error {
var err error
if err = m.openDB(); err != nil {
return err
}
defer m.closeDB()
bkt := f.GetBucket()
if err = m.bolt.MkBucketPath(bkt); err != nil {
return err
}
if err = m.bolt.SetValue(bkt, "name", f.Name); err != nil {
return err
}
if err = m.bolt.SetValue(bkt, "author", f.Author); err != nil {
return err
}
if err = m.bolt.SetValue(bkt, "desc", f.Desc); err != nil {
return err
}
if err = m.bolt.SetTimestamp(bkt, "lastupdate", f.LastUpdate); err != nil {
return err
}
// Add it to the cached list
for i, v := range m.Feeds {
if v.Source == f.Source && v.Slug == f.Slug {
m.Feeds[i] = *f
return nil
}
}
m.Feeds = append(m.Feeds, *f)
return nil
}
// DB Function to get a feed
func (m *model) GetFeed(source, slug string) (*Feed, error) {
var err error
if err = m.openDB(); err != nil {
return nil, err
}
defer m.closeDB()
ret := new(Feed)
ret.Source = source
ret.Slug = slug
bkt := ret.GetBucket()
if ret.Name, err = m.bolt.GetValue(bkt, "name"); err != nil {
return nil, err
}
if ret.Author, err = m.bolt.GetValue(bkt, "author"); err != nil {
return nil, err
}
if ret.Desc, err = m.bolt.GetValue(bkt, "desc"); err != nil {
return nil, err
}
if ret.LastUpdate, err = m.bolt.GetTimestamp(bkt, "lastupdate"); err != nil {
return nil, err
}
return ret, nil
}
// Load all feeds into the model
func (m *model) LoadFeeds() error {
m.Feeds = m.GetAllFeeds()
return nil
}
// Save all feeds to the DB
func (m *model) SaveAllFeeds(feedSources []FeedSource) {
var err error
if err = m.openDB(); err != nil {
return
}
defer m.closeDB()
for _, v := range feedSources {
for j := range v.Feeds {
fmt.Printf("Saving Feed to DB (%s;%s)\n", v.Feeds[j].Source, v.Feeds[j].Slug)
m.SaveFeed(v.Feeds[j])
}
}
}
// Get all feeds from the db
func (m *model) GetAllFeeds() []Feed {
var ret []Feed
var err error
if err = m.openDB(); err != nil {
return ret
}
defer m.closeDB()
var srcs []string
bkt := []string{"feeds"}
if srcs, err = m.bolt.GetBucketList(bkt); err != nil {
return ret
}
for _, src := range srcs {
srcBkt := append(bkt, src)
var slugs []string
if slugs, err = m.bolt.GetBucketList(srcBkt); err != nil {
return ret
}
for _, slg := range slugs {
c, err := m.GetFeed(src, slg)
if err == nil {
ret = append(ret, *c)
}
}
}
return ret
}
// Delete a feed from the DB
func (m *model) DeleteFeed(slug string) error {
var err error
if err = m.openDB(); err != nil {
return err
}
defer m.closeDB()
return m.bolt.DeleteBucket([]string{"feeds"}, slug)
}
func (m *model) RemoveMissingFeeds(feeds []Feed) {
for _, c := range m.Feeds {
var fnd bool
for _, nc := range feeds {
if nc.Slug == c.Slug {
fnd = true
break
}
}
if !fnd {
m.DeleteFeed(c.Slug)
}
}
}