// Package feed generates RSS 2.0 / Atom feeds from blog posts. package feed import ( "encoding/xml" "time" "ridgwaysystems.org/website/internal/blog" ) // --- RSS 2.0 --- type rssChannel struct { XMLName xml.Name `xml:"channel"` Title string `xml:"title"` Link string `xml:"link"` Description string `xml:"description"` Language string `xml:"language"` LastBuildDate string `xml:"lastBuildDate"` AtomLink atomLink `xml:"atom:link"` Items []rssItem `xml:"item"` } type atomLink struct { Href string `xml:"href,attr"` Rel string `xml:"rel,attr"` Type string `xml:"type,attr"` } type rssItem struct { Title string `xml:"title"` Link string `xml:"link"` Description string `xml:"description"` PubDate string `xml:"pubDate"` GUID string `xml:"guid"` } type rssFeed struct { XMLName xml.Name `xml:"rss"` Version string `xml:"version,attr"` Atom string `xml:"xmlns:atom,attr"` Channel rssChannel `xml:"channel"` } // RSS generates RSS 2.0 XML for the given posts. func RSS(siteURL, siteTitle, siteDesc string, posts []*blog.Post) ([]byte, error) { var items []rssItem for _, p := range posts { postURL := siteURL + "/blog/" + p.Slug items = append(items, rssItem{ Title: p.Title, Link: postURL, Description: p.Description, PubDate: p.ParsedDate.Format(time.RFC1123Z), GUID: postURL, }) } feed := rssFeed{ Version: "2.0", Atom: "http://www.w3.org/2005/Atom", Channel: rssChannel{ Title: siteTitle, Link: siteURL, Description: siteDesc, Language: "en-us", LastBuildDate: time.Now().Format(time.RFC1123Z), AtomLink: atomLink{ Href: siteURL + "/blog/feed.xml", Rel: "self", Type: "application/rss+xml", }, Items: items, }, } out, err := xml.MarshalIndent(feed, "", " ") if err != nil { return nil, err } return append([]byte(xml.Header), out...), nil }