Skip to content

Commit

Permalink
[feature] Support feed item images (#41)
Browse files Browse the repository at this point in the history
* Add support for podcast-centered tags
* Adding proper support for Enclosure and and Image tags, which didn't seem to generate properly (might have been a bug on my end but I'm not sure).
* Enclosure.Length from string to int
* Revert change from string to int for Enclosure length
* Accidently changed err == to != for enclosure & author
* Update README to reflect fork goals
* List of tags to implement
* fix RSS image when no Image is mentioned in the Feed
* do not assume that a Link with a field Type is an Enclosure
* expected tests
* better handling of enclosures
* fix package
* Fixes as requested
* Fix travis build error
  • Loading branch information
gmemstr authored and elithrar committed Nov 8, 2017
1 parent b78e02c commit 4b936b5
Show file tree
Hide file tree
Showing 7 changed files with 66 additions and 19 deletions.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -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.
Expand Down
17 changes: 9 additions & 8 deletions atom.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ import (
"encoding/xml"
"fmt"
"net/url"
"strconv"
"time"
)

Expand Down Expand Up @@ -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 <link rel="enclosure" type="audio/mpeg" title="MP3" href="http://www.example.org/myaudiofile.mp3" length="1234" />
XMLName xml.Name `xml:"link"`
Expand Down Expand Up @@ -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 {
Expand Down
11 changes: 11 additions & 0 deletions feed.go
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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 {
Expand All @@ -37,6 +47,7 @@ type Feed struct {
Subtitle string
Items []*Item
Copyright string
Image *Image
}

// add a new Item to a Feed
Expand Down
16 changes: 11 additions & 5 deletions feed_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ var atomOutput = `<?xml version="1.0" encoding="UTF-8"?><feed xmlns="http://www.
<updated>2013-01-16T21:52:35-05:00</updated>
<id>tag:jmoiron.net,2013-01-16:/blog/limiting-concurrency-in-go/</id>
<content type="html">A discussion on controlled parallelism in golang</content>
<link href="http://jmoiron.net/blog/limiting-concurrency-in-go/"></link>
<link href="http://jmoiron.net/blog/limiting-concurrency-in-go/" rel="alternate"></link>
<author>
<name>Jason Moiron</name>
<email>[email protected]</email>
Expand All @@ -33,28 +33,30 @@ var atomOutput = `<?xml version="1.0" encoding="UTF-8"?><feed xmlns="http://www.
<updated>2013-01-16T21:52:35-05:00</updated>
<id>tag:jmoiron.net,2013-01-16:/blog/logicless-template-redux/</id>
<content type="html">More thoughts on logicless templates</content>
<link href="http://jmoiron.net/blog/logicless-template-redux/"></link>
<link href="http://jmoiron.net/blog/logicless-template-redux/" rel="alternate"></link>
</entry>
<entry>
<title>Idiomatic Code Reuse in Go</title>
<updated>2013-01-16T21:52:35-05:00</updated>
<id>tag:jmoiron.net,2013-01-16:/blog/idiomatic-code-reuse-in-go/</id>
<content type="html">How to use interfaces &lt;em&gt;effectively&lt;/em&gt;</content>
<link href="http://jmoiron.net/blog/idiomatic-code-reuse-in-go/"></link>
<link href="http://jmoiron.net/blog/idiomatic-code-reuse-in-go/" rel="alternate"></link>
<link href="http://example.com/cover.jpg" rel="enclosure" type="image/jpg" length="123456"></link>
</entry>
<entry>
<title>Never Gonna Give You Up Mp3</title>
<updated>2013-01-16T21:52:35-05:00</updated>
<id>tag:example.com,2013-01-16:/RickRoll.mp3</id>
<content type="html">Never gonna give you up - Never gonna let you down.</content>
<link href="http://example.com/RickRoll.mp3" rel="alternate"></link>
<link href="http://example.com/RickRoll.mp3" rel="enclosure" type="audio/mpeg" length="123456"></link>
</entry>
<entry>
<title>String formatting in Go</title>
<updated>2013-01-16T21:52:35-05:00</updated>
<id>tag:example.com,2013-01-16:/strings</id>
<content type="html">How to use things like %s, %v, %d, etc.</content>
<link href="http://example.com/strings"></link>
<link href="http://example.com/strings" rel="alternate"></link>
</entry>
</feed>`

Expand Down Expand Up @@ -83,6 +85,7 @@ var rssOutput = `<?xml version="1.0" encoding="UTF-8"?><rss version="2.0">
<title>Idiomatic Code Reuse in Go</title>
<link>http://jmoiron.net/blog/idiomatic-code-reuse-in-go/</link>
<description>How to use interfaces &lt;em&gt;effectively&lt;/em&gt;</description>
<enclosure url="http://example.com/cover.jpg" length="123456" type="image/jpg"></enclosure>
<pubDate>Wed, 16 Jan 2013 21:52:35 -0500</pubDate>
</item>
<item>
Expand Down Expand Up @@ -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"
},
{
Expand Down Expand Up @@ -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 <em>effectively</em>",
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,
},
Expand Down
4 changes: 4 additions & 0 deletions json.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package feeds

import (
"encoding/json"
"strings"
"time"
)

Expand Down Expand Up @@ -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
}
15 changes: 10 additions & 5 deletions rss.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@ package feeds
import (
"encoding/xml"
"fmt"
"strconv"
"time"
)

Expand Down Expand Up @@ -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
}
Expand All @@ -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,
Expand All @@ -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))
Expand Down
20 changes: 20 additions & 0 deletions to-implement.md
Original file line number Diff line number Diff line change
@@ -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)

```
<itunes:author>
<itunes:block>
<itunes:catergory>
<itunes:image>
<itunes:duration>
<itunes:explicit>
<itunes:isClosedCaptioned>
<itunes:order>
<itunes:complete>
<itunes:new-feed-url>
<itunes:owner>
<itunes:subtitle>
<itunes:summary>
<language>
```

1 comment on commit 4b936b5

@gavinbains
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

does this enable functionality to add an image per item in feed?

Please sign in to comment.