2012-03-24 20:11:38 +00:00
|
|
|
/*
|
|
|
|
Simple RSS parser, tested with Wordpress feeds.
|
|
|
|
*/
|
|
|
|
package rss
|
|
|
|
|
|
|
|
import (
|
|
|
|
"encoding/xml"
|
|
|
|
"net/http"
|
|
|
|
"time"
|
2013-12-17 16:44:03 +00:00
|
|
|
|
2013-03-14 23:25:13 +00:00
|
|
|
"code.google.com/p/go-charset/charset"
|
2013-03-14 23:32:01 +00:00
|
|
|
_ "code.google.com/p/go-charset/data"
|
2012-03-24 20:11:38 +00:00
|
|
|
)
|
|
|
|
|
2012-03-28 15:35:35 +00:00
|
|
|
type Channel struct {
|
|
|
|
Title string `xml:"title"`
|
|
|
|
Link string `xml:"link"`
|
|
|
|
Description string `xml:"description"`
|
|
|
|
Language string `xml:"language"`
|
|
|
|
LastBuildDate Date `xml:"lastBuildDate"`
|
|
|
|
Item []Item `xml:"item"`
|
|
|
|
}
|
|
|
|
|
|
|
|
type ItemEnclosure struct {
|
|
|
|
URL string `xml:"url,attr"`
|
|
|
|
Type string `xml:"type,attr"`
|
2012-03-24 20:11:38 +00:00
|
|
|
}
|
|
|
|
|
2013-12-17 16:44:03 +00:00
|
|
|
type AtomLink struct {
|
|
|
|
Href string `xml:"href,attr"`
|
|
|
|
Rel string `xml:"rel,attr"`
|
|
|
|
Type string `xml:"type,attr"`
|
|
|
|
}
|
|
|
|
|
2012-03-24 20:11:38 +00:00
|
|
|
type Item struct {
|
2012-03-28 15:35:35 +00:00
|
|
|
Title string `xml:"title"`
|
|
|
|
Link string `xml:"link"`
|
2013-12-17 16:44:03 +00:00
|
|
|
AtomLink AtomLink `xml:"http://www.w3.org/2005/Atom/ link"`
|
2012-03-28 15:35:35 +00:00
|
|
|
Comments string `xml:"comments"`
|
|
|
|
PubDate Date `xml:"pubDate"`
|
|
|
|
GUID string `xml:"guid"`
|
|
|
|
Category []string `xml:"category"`
|
|
|
|
Enclosure ItemEnclosure `xml:"enclosure"`
|
|
|
|
Description string `xml:"description"`
|
|
|
|
Content string `xml:"content"`
|
2012-03-24 20:11:38 +00:00
|
|
|
}
|
|
|
|
|
2012-03-28 15:35:35 +00:00
|
|
|
type Date string
|
|
|
|
|
|
|
|
func (self Date) Parse() (time.Time, error) {
|
2013-03-14 23:25:13 +00:00
|
|
|
// Wordpress format
|
2013-12-17 16:44:03 +00:00
|
|
|
t, err := time.Parse("Mon, 02 Jan 2006 15:04:05 -0700", string(self))
|
2012-03-24 20:11:38 +00:00
|
|
|
if err != nil {
|
2012-03-28 15:35:35 +00:00
|
|
|
t, err = time.Parse(time.RFC822, string(self)) // RSS 2.0 spec
|
2012-03-24 20:11:38 +00:00
|
|
|
}
|
|
|
|
return t, err
|
|
|
|
}
|
|
|
|
|
2012-03-28 15:35:35 +00:00
|
|
|
func (self Date) Format(format string) (string, error) {
|
|
|
|
t, err := self.Parse()
|
2012-03-24 20:11:38 +00:00
|
|
|
if err != nil {
|
|
|
|
return "", err
|
|
|
|
}
|
|
|
|
return t.Format(format), nil
|
|
|
|
}
|
|
|
|
|
2012-03-28 15:35:35 +00:00
|
|
|
func (self Date) MustFormat(format string) string {
|
|
|
|
s, err := self.Format(format)
|
2012-03-24 20:11:38 +00:00
|
|
|
if err != nil {
|
|
|
|
return err.Error()
|
|
|
|
}
|
|
|
|
return s
|
|
|
|
}
|
|
|
|
|
2012-03-28 15:35:35 +00:00
|
|
|
func Read(url string) (*Channel, error) {
|
2012-03-24 20:11:38 +00:00
|
|
|
response, err := http.Get(url)
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
defer response.Body.Close()
|
2013-03-14 23:25:13 +00:00
|
|
|
xmlDecoder := xml.NewDecoder(response.Body)
|
|
|
|
xmlDecoder.CharsetReader = charset.NewReader
|
2012-03-28 15:35:35 +00:00
|
|
|
|
2012-03-24 20:11:38 +00:00
|
|
|
var rss struct {
|
2012-03-28 15:35:35 +00:00
|
|
|
Channel Channel `xml:"channel"`
|
2012-03-24 20:11:38 +00:00
|
|
|
}
|
2013-03-14 23:25:13 +00:00
|
|
|
err = xmlDecoder.Decode(&rss)
|
2012-03-24 20:11:38 +00:00
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
return &rss.Channel, nil
|
|
|
|
}
|