diff --git a/README.md b/README.md index 21f6cf8..de9cb6d 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,5 @@ ## gorilla/feeds -[![GoDoc](https://godoc.org/github.com/gorilla/feeds?status.svg)](https://godoc.org/github.com/gorilla/feeds) [![Build Status](https://travis-ci.org/gorilla/feeds.png?branch=master)](https://travis-ci.org/gorilla/feeds) +[![GoDoc](https://godoc.org/github.com/gorilla/feeds?status.svg)](https://godoc.org/github.com/gorilla/feeds) feeds is a web feed generator library for generating RSS, Atom and JSON feeds from Go applications. diff --git a/atom.go b/atom.go index 512976b..6b0ddcb 100644 --- a/atom.go +++ b/atom.go @@ -4,7 +4,6 @@ import ( "encoding/xml" "fmt" "net/url" - "strconv" "time" ) @@ -52,11 +51,12 @@ type AtomEntry struct { Source string `xml:"source,omitempty"` Published string `xml:"published,omitempty"` Contributor *AtomContributor - Link *AtomLink // required if no child 'content' elements + Links []AtomLink // required if no child 'content' elements Summary *AtomSummary // required if content has src or content is base64 Author *AtomAuthor // required if feed lacks an author } +// Multiple links with different rel can coexist type AtomLink struct { //Atom 1.0 XMLName xml.Name `xml:"link"` @@ -110,19 +110,20 @@ func newAtomEntry(i *Item) *AtomEntry { name, email = i.Author.Name, i.Author.Email } + link_rel := i.Link.Rel + if link_rel == "" { + link_rel = "alternate" + } x := &AtomEntry{ Title: i.Title, - Link: &AtomLink{Href: i.Link.Href, Rel: i.Link.Rel, Type: i.Link.Type}, + Links: []AtomLink{{Href: i.Link.Href, Rel: link_rel, Type: i.Link.Type}}, Content: c, Id: id, Updated: anyTimeFormat(time.RFC3339, i.Updated, i.Created), } - intLength, err := strconv.ParseInt(i.Link.Length, 10, 64) - - if err == nil && (intLength > 0 || i.Link.Type != "") { - i.Link.Rel = "enclosure" - x.Link = &AtomLink{Href: i.Link.Href, Rel: i.Link.Rel, Type: i.Link.Type, Length: i.Link.Length} + if i.Enclosure != nil && link_rel != "enclosure" { + x.Links = append(x.Links, AtomLink{Href: i.Enclosure.Url, Rel: "enclosure", Type: i.Enclosure.Type, Length: i.Enclosure.Length}) } if len(name) > 0 || len(email) > 0 { diff --git a/feed.go b/feed.go index dc685c7..f756abf 100644 --- a/feed.go +++ b/feed.go @@ -15,6 +15,15 @@ type Author struct { Name, Email string } +type Image struct { + Url, Title, Link string + Width, Height int +} + +type Enclosure struct { + Url, Length, Type string +} + type Item struct { Title string Link *Link @@ -24,6 +33,7 @@ type Item struct { Id string // used as guid in rss, id in atom Updated time.Time Created time.Time + Enclosure *Enclosure } type Feed struct { @@ -37,6 +47,7 @@ type Feed struct { Subtitle string Items []*Item Copyright string + Image *Image } // add a new Item to a Feed diff --git a/feed_test.go b/feed_test.go index e7ed38c..afd00bb 100644 --- a/feed_test.go +++ b/feed_test.go @@ -22,7 +22,7 @@ var atomOutput = `A discussion on controlled parallelism in golang - + Jason Moiron jmoiron@jmoiron.net @@ -33,20 +33,22 @@ var atomOutput = `More thoughts on logicless templates - + Idiomatic Code Reuse in Go 2013-01-16T21:52:35-05:00 tag:jmoiron.net,2013-01-16:/blog/idiomatic-code-reuse-in-go/ How to use interfaces <em>effectively</em> - + + Never Gonna Give You Up Mp3 2013-01-16T21:52:35-05:00 tag:example.com,2013-01-16:/RickRoll.mp3 Never gonna give you up - Never gonna let you down. + @@ -54,7 +56,7 @@ var atomOutput = `How to use things like %s, %v, %d, etc. - + ` @@ -83,6 +85,7 @@ var rssOutput = ` Idiomatic Code Reuse in Go http://jmoiron.net/blog/idiomatic-code-reuse-in-go/ How to use interfaces <em>effectively</em> + Wed, 16 Jan 2013 21:52:35 -0500 @@ -132,6 +135,7 @@ var jsonOutput = `{ "url": "http://jmoiron.net/blog/idiomatic-code-reuse-in-go/", "title": "Idiomatic Code Reuse in Go", "summary": "How to use interfaces \u003cem\u003eeffectively\u003c/em\u003e", + "image": "http://example.com/cover.jpg", "date_published": "2013-01-16T21:52:35-05:00" }, { @@ -186,11 +190,13 @@ func TestFeed(t *testing.T) { Title: "Idiomatic Code Reuse in Go", Link: &Link{Href: "http://jmoiron.net/blog/idiomatic-code-reuse-in-go/"}, Description: "How to use interfaces effectively", + Enclosure: &Enclosure{Url: "http://example.com/cover.jpg", Length: "123456", Type: "image/jpg"}, Created: now, }, { Title: "Never Gonna Give You Up Mp3", - Link: &Link{Href: "http://example.com/RickRoll.mp3", Length: "123456", Type: "audio/mpeg"}, + Link: &Link{Href: "http://example.com/RickRoll.mp3"}, + Enclosure: &Enclosure{Url: "http://example.com/RickRoll.mp3", Length: "123456", Type: "audio/mpeg"}, Description: "Never gonna give you up - Never gonna let you down.", Created: now, }, diff --git a/json.go b/json.go index 8fbb535..e262e4e 100644 --- a/json.go +++ b/json.go @@ -2,6 +2,7 @@ package feeds import ( "encoding/json" + "strings" "time" ) @@ -172,6 +173,9 @@ func newJSONItem(i *Item) *JSONItem { if !i.Updated.IsZero() { item.ModifiedDate = &i.Created } + if i.Enclosure != nil && strings.HasPrefix(i.Enclosure.Type, "image/") { + item.Image = i.Enclosure.Url + } return item } diff --git a/rss.go b/rss.go index ec65e8f..fec5915 100644 --- a/rss.go +++ b/rss.go @@ -7,7 +7,6 @@ package feeds import ( "encoding/xml" "fmt" - "strconv" "time" ) @@ -98,11 +97,11 @@ func newRssItem(i *Item) *RssItem { item.Source = i.Source.Href } - intLength, err := strconv.ParseInt(i.Link.Length, 10, 64) - - if err == nil && (intLength > 0 || i.Link.Type != "") { - item.Enclosure = &RssEnclosure{Url: i.Link.Href, Type: i.Link.Type, Length: i.Link.Length} + // Define a closure + if i.Enclosure != nil && i.Enclosure.Type != "" && i.Enclosure.Length != "" { + item.Enclosure = &RssEnclosure{Url: i.Enclosure.Url, Type: i.Enclosure.Type, Length: i.Enclosure.Length} } + if i.Author != nil { item.Author = i.Author.Name } @@ -121,6 +120,11 @@ func (r *Rss) RssFeed() *RssFeed { } } + var image *RssImage + if r.Image != nil { + image = &RssImage{Url: r.Image.Url, Title: r.Image.Title, Link: r.Image.Link, Width: r.Image.Width, Height: r.Image.Height} + } + channel := &RssFeed{ Title: r.Title, Link: r.Link.Href, @@ -129,6 +133,7 @@ func (r *Rss) RssFeed() *RssFeed { PubDate: pub, LastBuildDate: build, Copyright: r.Copyright, + Image: image, } for _, i := range r.Items { channel.Items = append(channel.Items, newRssItem(i)) diff --git a/to-implement.md b/to-implement.md new file mode 100644 index 0000000..45fd1e7 --- /dev/null +++ b/to-implement.md @@ -0,0 +1,20 @@ +[Full iTunes list](https://help.apple.com/itc/podcasts_connect/#/itcb54353390) + +[Example of ideal iTunes RSS feed](https://help.apple.com/itc/podcasts_connect/#/itcbaf351599) + +``` + + + + + + + + + + + + + + +``` \ No newline at end of file