2024-03-05 15:00:09 +01:00
|
|
|
package rss
|
|
|
|
|
|
|
|
import (
|
2024-03-05 15:46:51 +01:00
|
|
|
"encoding/gob"
|
2024-03-05 15:00:09 +01:00
|
|
|
"encoding/xml"
|
|
|
|
"fmt"
|
2024-03-05 15:46:51 +01:00
|
|
|
"os"
|
2024-03-05 15:00:09 +01:00
|
|
|
"sync"
|
|
|
|
)
|
|
|
|
|
|
|
|
type Feed struct {
|
|
|
|
addChannel chan *Channel
|
|
|
|
XMLName xml.Name `xml:"rss"`
|
|
|
|
Version string `xml:"version,attr"`
|
|
|
|
ContentNamespace string `xml:"xmlns:content,attr"`
|
|
|
|
Channels []*Channel
|
|
|
|
wg sync.WaitGroup
|
|
|
|
}
|
|
|
|
|
|
|
|
func (f *Feed) start() {
|
|
|
|
f.wg.Done()
|
|
|
|
|
|
|
|
for channel := range f.addChannel {
|
|
|
|
f.Channels = append(f.Channels, channel)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func initFeed() *Feed {
|
|
|
|
feed := &Feed{
|
|
|
|
addChannel: make(chan *Channel),
|
|
|
|
Version: "2.0",
|
|
|
|
ContentNamespace: "http://purl.org/rss/1.0/modules/content/",
|
|
|
|
}
|
|
|
|
|
|
|
|
return feed
|
|
|
|
}
|
|
|
|
|
|
|
|
func (f *Feed) check() error {
|
|
|
|
if f.Channels == nil {
|
|
|
|
return fmt.Errorf("error: feed has no channels")
|
|
|
|
}
|
|
|
|
|
|
|
|
for _, channel := range f.Channels {
|
|
|
|
if err := channel.check(); err != nil {
|
|
|
|
return fmt.Errorf("error checking channel: %v", err)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
|
|
|
func NewFeed() *Feed {
|
2024-03-05 15:46:51 +01:00
|
|
|
feed := initFeed()
|
|
|
|
|
|
|
|
feed.wg.Add(1)
|
|
|
|
go feed.start()
|
|
|
|
feed.wg.Wait()
|
|
|
|
|
|
|
|
return feed
|
2024-03-05 15:00:09 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
func (f *Feed) AddChannel(c *Channel) {
|
|
|
|
f.addChannel <- c
|
|
|
|
}
|
2024-03-05 15:46:51 +01:00
|
|
|
|
|
|
|
func (f *Feed) Save(filename string) error {
|
|
|
|
file, err := os.Create(filename)
|
|
|
|
if err != nil {
|
|
|
|
return fmt.Errorf("error creating file %v: %v", filename, err)
|
|
|
|
}
|
|
|
|
defer file.Close()
|
|
|
|
|
|
|
|
if err := gob.NewEncoder(file).Encode(f); err != nil {
|
|
|
|
return fmt.Errorf("error encoding feed in file %v: %v", filename, err)
|
|
|
|
}
|
|
|
|
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
|
|
|
func OpenFeed(filename string) (*Feed, error) {
|
|
|
|
file, err := os.Open(filename)
|
|
|
|
if err != nil {
|
|
|
|
return nil, fmt.Errorf("error opening file %v: %v", filename, err)
|
|
|
|
}
|
|
|
|
defer file.Close()
|
|
|
|
|
|
|
|
feed := initFeed()
|
|
|
|
feed.wg.Add(1)
|
|
|
|
go feed.start()
|
|
|
|
feed.wg.Wait()
|
|
|
|
|
|
|
|
if err := gob.NewDecoder(file).Decode(feed); err != nil {
|
|
|
|
return nil, fmt.Errorf("error decoding file %v: %v", filename, err)
|
|
|
|
}
|
|
|
|
|
|
|
|
return nil, nil
|
|
|
|
}
|