82 lines
2.0 KiB
Go
82 lines
2.0 KiB
Go
package spc
|
|
|
|
import (
|
|
"encoding/xml"
|
|
"fmt"
|
|
"strings"
|
|
"time"
|
|
)
|
|
|
|
// RSSFeed is a minimal view of the optional SPC RSS feed.
|
|
type RSSFeed struct {
|
|
Title string
|
|
Link string
|
|
Description string
|
|
LastBuildDate *time.Time
|
|
Items []RSSItem
|
|
}
|
|
|
|
// RSSItem is a minimal view of one optional SPC RSS item.
|
|
type RSSItem struct {
|
|
Title string
|
|
Link string
|
|
Description string
|
|
PubDate string
|
|
GUID string
|
|
}
|
|
|
|
// ParseRSSFeed decodes supplemental SPC RSS metadata.
|
|
func ParseRSSFeed(raw string) (RSSFeed, error) {
|
|
var doc struct {
|
|
Channel struct {
|
|
Title string `xml:"title"`
|
|
Link string `xml:"link"`
|
|
Description string `xml:"description"`
|
|
LastBuildDate string `xml:"lastBuildDate"`
|
|
Items []struct {
|
|
Title string `xml:"title"`
|
|
Link string `xml:"link"`
|
|
Description string `xml:"description"`
|
|
PubDate string `xml:"pubDate"`
|
|
GUID string `xml:"guid"`
|
|
} `xml:"item"`
|
|
} `xml:"channel"`
|
|
}
|
|
if err := xml.Unmarshal([]byte(raw), &doc); err != nil {
|
|
return RSSFeed{}, fmt.Errorf("decode rss: %w", err)
|
|
}
|
|
|
|
feed := RSSFeed{
|
|
Title: strings.TrimSpace(doc.Channel.Title),
|
|
Link: strings.TrimSpace(doc.Channel.Link),
|
|
Description: strings.TrimSpace(doc.Channel.Description),
|
|
LastBuildDate: parseRSSDate(doc.Channel.LastBuildDate),
|
|
Items: make([]RSSItem, 0, len(doc.Channel.Items)),
|
|
}
|
|
for _, item := range doc.Channel.Items {
|
|
feed.Items = append(feed.Items, RSSItem{
|
|
Title: strings.TrimSpace(item.Title),
|
|
Link: strings.TrimSpace(item.Link),
|
|
Description: strings.TrimSpace(item.Description),
|
|
PubDate: strings.TrimSpace(item.PubDate),
|
|
GUID: strings.TrimSpace(item.GUID),
|
|
})
|
|
}
|
|
return feed, nil
|
|
}
|
|
|
|
func parseRSSDate(value string) *time.Time {
|
|
value = strings.TrimSpace(value)
|
|
if value == "" {
|
|
return nil
|
|
}
|
|
for _, layout := range []string{time.RFC1123Z, time.RFC1123} {
|
|
t, err := time.Parse(layout, value)
|
|
if err == nil {
|
|
tt := t.UTC()
|
|
return &tt
|
|
}
|
|
}
|
|
return nil
|
|
}
|