package podcasts import "encoding/xml" // rssFeed is a pragmatic subset of RSS 2.0 (with the de facto iTunes // podcast extensions most feeds use) — enough to get channel metadata // and each episode's title, description, publish date, and audio // enclosure. Real podcast feeds vary a lot in which optional fields they // include, so every field here is best-effort. type rssFeed struct { Channel rssChannel `xml:"channel"` } type rssChannel struct { Title string `xml:"title"` Description string `xml:"description"` Image rssImage `xml:"image"` Items []rssItem `xml:"item"` } type rssImage struct { URL string `xml:"url"` } type rssItem struct { GUID rssGUID `xml:"guid"` Title string `xml:"title"` Description string `xml:"description"` PubDate string `xml:"pubDate"` Enclosure rssEnclosure `xml:"enclosure"` Duration string `xml:"http://www.itunes.com/dtds/podcast-1.0.dtd duration"` } type rssGUID struct { Value string `xml:",chardata"` } type rssEnclosure struct { URL string `xml:"url,attr"` } func parseRSS(data []byte) (*rssFeed, error) { var feed rssFeed if err := xml.Unmarshal(data, &feed); err != nil { return nil, err } return &feed, nil } // episodeGUID returns the item's GUID if present, falling back to its // enclosure URL — some minimal feeds omit entirely. func (i rssItem) episodeGUID() string { if i.GUID.Value != "" { return i.GUID.Value } return i.Enclosure.URL }