Skip to content

Commit 4b936b5

Browse files
gmemstrelithrar
authored andcommitted
[feature] Support feed item images (#41)
* 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
1 parent b78e02c commit 4b936b5

File tree

7 files changed

+66
-19
lines changed

7 files changed

+66
-19
lines changed

README.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
## gorilla/feeds
2-
[![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)
2+
[![GoDoc](https://godoc.org/github.com/gorilla/feeds?status.svg)](https://godoc.org/github.com/gorilla/feeds)
33

44
feeds is a web feed generator library for generating RSS, Atom and JSON feeds from Go
55
applications.

atom.go

+9-8
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@ import (
44
"encoding/xml"
55
"fmt"
66
"net/url"
7-
"strconv"
87
"time"
98
)
109

@@ -52,11 +51,12 @@ type AtomEntry struct {
5251
Source string `xml:"source,omitempty"`
5352
Published string `xml:"published,omitempty"`
5453
Contributor *AtomContributor
55-
Link *AtomLink // required if no child 'content' elements
54+
Links []AtomLink // required if no child 'content' elements
5655
Summary *AtomSummary // required if content has src or content is base64
5756
Author *AtomAuthor // required if feed lacks an author
5857
}
5958

59+
// Multiple links with different rel can coexist
6060
type AtomLink struct {
6161
//Atom 1.0 <link rel="enclosure" type="audio/mpeg" title="MP3" href="http://www.example.org/myaudiofile.mp3" length="1234" />
6262
XMLName xml.Name `xml:"link"`
@@ -110,19 +110,20 @@ func newAtomEntry(i *Item) *AtomEntry {
110110
name, email = i.Author.Name, i.Author.Email
111111
}
112112

113+
link_rel := i.Link.Rel
114+
if link_rel == "" {
115+
link_rel = "alternate"
116+
}
113117
x := &AtomEntry{
114118
Title: i.Title,
115-
Link: &AtomLink{Href: i.Link.Href, Rel: i.Link.Rel, Type: i.Link.Type},
119+
Links: []AtomLink{{Href: i.Link.Href, Rel: link_rel, Type: i.Link.Type}},
116120
Content: c,
117121
Id: id,
118122
Updated: anyTimeFormat(time.RFC3339, i.Updated, i.Created),
119123
}
120124

121-
intLength, err := strconv.ParseInt(i.Link.Length, 10, 64)
122-
123-
if err == nil && (intLength > 0 || i.Link.Type != "") {
124-
i.Link.Rel = "enclosure"
125-
x.Link = &AtomLink{Href: i.Link.Href, Rel: i.Link.Rel, Type: i.Link.Type, Length: i.Link.Length}
125+
if i.Enclosure != nil && link_rel != "enclosure" {
126+
x.Links = append(x.Links, AtomLink{Href: i.Enclosure.Url, Rel: "enclosure", Type: i.Enclosure.Type, Length: i.Enclosure.Length})
126127
}
127128

128129
if len(name) > 0 || len(email) > 0 {

feed.go

+11
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,15 @@ type Author struct {
1515
Name, Email string
1616
}
1717

18+
type Image struct {
19+
Url, Title, Link string
20+
Width, Height int
21+
}
22+
23+
type Enclosure struct {
24+
Url, Length, Type string
25+
}
26+
1827
type Item struct {
1928
Title string
2029
Link *Link
@@ -24,6 +33,7 @@ type Item struct {
2433
Id string // used as guid in rss, id in atom
2534
Updated time.Time
2635
Created time.Time
36+
Enclosure *Enclosure
2737
}
2838

2939
type Feed struct {
@@ -37,6 +47,7 @@ type Feed struct {
3747
Subtitle string
3848
Items []*Item
3949
Copyright string
50+
Image *Image
4051
}
4152

4253
// add a new Item to a Feed

feed_test.go

+11-5
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ var atomOutput = `<?xml version="1.0" encoding="UTF-8"?><feed xmlns="http://www.
2222
<updated>2013-01-16T21:52:35-05:00</updated>
2323
<id>tag:jmoiron.net,2013-01-16:/blog/limiting-concurrency-in-go/</id>
2424
<content type="html">A discussion on controlled parallelism in golang</content>
25-
<link href="http://jmoiron.net/blog/limiting-concurrency-in-go/"></link>
25+
<link href="http://jmoiron.net/blog/limiting-concurrency-in-go/" rel="alternate"></link>
2626
<author>
2727
<name>Jason Moiron</name>
2828
<email>jmoiron@jmoiron.net</email>
@@ -33,28 +33,30 @@ var atomOutput = `<?xml version="1.0" encoding="UTF-8"?><feed xmlns="http://www.
3333
<updated>2013-01-16T21:52:35-05:00</updated>
3434
<id>tag:jmoiron.net,2013-01-16:/blog/logicless-template-redux/</id>
3535
<content type="html">More thoughts on logicless templates</content>
36-
<link href="http://jmoiron.net/blog/logicless-template-redux/"></link>
36+
<link href="http://jmoiron.net/blog/logicless-template-redux/" rel="alternate"></link>
3737
</entry>
3838
<entry>
3939
<title>Idiomatic Code Reuse in Go</title>
4040
<updated>2013-01-16T21:52:35-05:00</updated>
4141
<id>tag:jmoiron.net,2013-01-16:/blog/idiomatic-code-reuse-in-go/</id>
4242
<content type="html">How to use interfaces &lt;em&gt;effectively&lt;/em&gt;</content>
43-
<link href="http://jmoiron.net/blog/idiomatic-code-reuse-in-go/"></link>
43+
<link href="http://jmoiron.net/blog/idiomatic-code-reuse-in-go/" rel="alternate"></link>
44+
<link href="http://example.com/cover.jpg" rel="enclosure" type="image/jpg" length="123456"></link>
4445
</entry>
4546
<entry>
4647
<title>Never Gonna Give You Up Mp3</title>
4748
<updated>2013-01-16T21:52:35-05:00</updated>
4849
<id>tag:example.com,2013-01-16:/RickRoll.mp3</id>
4950
<content type="html">Never gonna give you up - Never gonna let you down.</content>
51+
<link href="http://example.com/RickRoll.mp3" rel="alternate"></link>
5052
<link href="http://example.com/RickRoll.mp3" rel="enclosure" type="audio/mpeg" length="123456"></link>
5153
</entry>
5254
<entry>
5355
<title>String formatting in Go</title>
5456
<updated>2013-01-16T21:52:35-05:00</updated>
5557
<id>tag:example.com,2013-01-16:/strings</id>
5658
<content type="html">How to use things like %s, %v, %d, etc.</content>
57-
<link href="http://example.com/strings"></link>
59+
<link href="http://example.com/strings" rel="alternate"></link>
5860
</entry>
5961
</feed>`
6062

@@ -83,6 +85,7 @@ var rssOutput = `<?xml version="1.0" encoding="UTF-8"?><rss version="2.0">
8385
<title>Idiomatic Code Reuse in Go</title>
8486
<link>http://jmoiron.net/blog/idiomatic-code-reuse-in-go/</link>
8587
<description>How to use interfaces &lt;em&gt;effectively&lt;/em&gt;</description>
88+
<enclosure url="http://example.com/cover.jpg" length="123456" type="image/jpg"></enclosure>
8689
<pubDate>Wed, 16 Jan 2013 21:52:35 -0500</pubDate>
8790
</item>
8891
<item>
@@ -132,6 +135,7 @@ var jsonOutput = `{
132135
"url": "http://jmoiron.net/blog/idiomatic-code-reuse-in-go/",
133136
"title": "Idiomatic Code Reuse in Go",
134137
"summary": "How to use interfaces \u003cem\u003eeffectively\u003c/em\u003e",
138+
"image": "http://example.com/cover.jpg",
135139
"date_published": "2013-01-16T21:52:35-05:00"
136140
},
137141
{
@@ -186,11 +190,13 @@ func TestFeed(t *testing.T) {
186190
Title: "Idiomatic Code Reuse in Go",
187191
Link: &Link{Href: "http://jmoiron.net/blog/idiomatic-code-reuse-in-go/"},
188192
Description: "How to use interfaces <em>effectively</em>",
193+
Enclosure: &Enclosure{Url: "http://example.com/cover.jpg", Length: "123456", Type: "image/jpg"},
189194
Created: now,
190195
},
191196
{
192197
Title: "Never Gonna Give You Up Mp3",
193-
Link: &Link{Href: "http://example.com/RickRoll.mp3", Length: "123456", Type: "audio/mpeg"},
198+
Link: &Link{Href: "http://example.com/RickRoll.mp3"},
199+
Enclosure: &Enclosure{Url: "http://example.com/RickRoll.mp3", Length: "123456", Type: "audio/mpeg"},
194200
Description: "Never gonna give you up - Never gonna let you down.",
195201
Created: now,
196202
},

json.go

+4
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ package feeds
22

33
import (
44
"encoding/json"
5+
"strings"
56
"time"
67
)
78

@@ -172,6 +173,9 @@ func newJSONItem(i *Item) *JSONItem {
172173
if !i.Updated.IsZero() {
173174
item.ModifiedDate = &i.Created
174175
}
176+
if i.Enclosure != nil && strings.HasPrefix(i.Enclosure.Type, "image/") {
177+
item.Image = i.Enclosure.Url
178+
}
175179

176180
return item
177181
}

rss.go

+10-5
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,6 @@ package feeds
77
import (
88
"encoding/xml"
99
"fmt"
10-
"strconv"
1110
"time"
1211
)
1312

@@ -98,11 +97,11 @@ func newRssItem(i *Item) *RssItem {
9897
item.Source = i.Source.Href
9998
}
10099

101-
intLength, err := strconv.ParseInt(i.Link.Length, 10, 64)
102-
103-
if err == nil && (intLength > 0 || i.Link.Type != "") {
104-
item.Enclosure = &RssEnclosure{Url: i.Link.Href, Type: i.Link.Type, Length: i.Link.Length}
100+
// Define a closure
101+
if i.Enclosure != nil && i.Enclosure.Type != "" && i.Enclosure.Length != "" {
102+
item.Enclosure = &RssEnclosure{Url: i.Enclosure.Url, Type: i.Enclosure.Type, Length: i.Enclosure.Length}
105103
}
104+
106105
if i.Author != nil {
107106
item.Author = i.Author.Name
108107
}
@@ -121,6 +120,11 @@ func (r *Rss) RssFeed() *RssFeed {
121120
}
122121
}
123122

123+
var image *RssImage
124+
if r.Image != nil {
125+
image = &RssImage{Url: r.Image.Url, Title: r.Image.Title, Link: r.Image.Link, Width: r.Image.Width, Height: r.Image.Height}
126+
}
127+
124128
channel := &RssFeed{
125129
Title: r.Title,
126130
Link: r.Link.Href,
@@ -129,6 +133,7 @@ func (r *Rss) RssFeed() *RssFeed {
129133
PubDate: pub,
130134
LastBuildDate: build,
131135
Copyright: r.Copyright,
136+
Image: image,
132137
}
133138
for _, i := range r.Items {
134139
channel.Items = append(channel.Items, newRssItem(i))

to-implement.md

+20
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
[Full iTunes list](https://help.apple.com/itc/podcasts_connect/#/itcb54353390)
2+
3+
[Example of ideal iTunes RSS feed](https://help.apple.com/itc/podcasts_connect/#/itcbaf351599)
4+
5+
```
6+
<itunes:author>
7+
<itunes:block>
8+
<itunes:catergory>
9+
<itunes:image>
10+
<itunes:duration>
11+
<itunes:explicit>
12+
<itunes:isClosedCaptioned>
13+
<itunes:order>
14+
<itunes:complete>
15+
<itunes:new-feed-url>
16+
<itunes:owner>
17+
<itunes:subtitle>
18+
<itunes:summary>
19+
<language>
20+
```

0 commit comments

Comments
 (0)