Skip to content

Commit

Permalink
Fixes issue gorillaGH-25 for RSS feeds.
Browse files Browse the repository at this point in the history
Adds the ability to add custom fields with a namespace to the RSS feed.
  • Loading branch information
artktec committed Jun 14, 2018
1 parent ffafbe1 commit 3989cde
Show file tree
Hide file tree
Showing 3 changed files with 152 additions and 18 deletions.
53 changes: 53 additions & 0 deletions feed.go
Original file line number Diff line number Diff line change
Expand Up @@ -35,9 +35,11 @@ type Item struct {
Created time.Time
Enclosure *Enclosure
Content string
Extension []interface{}
}

type Feed struct {
Attrs []xml.Attr
Title string
Link *Link
Description string
Expand All @@ -56,6 +58,57 @@ func (f *Feed) Add(item *Item) {
f.Items = append(f.Items, item)
}

func (f *Feed) AddAttribute(name, nsURI string) {
f.Attrs = append(f.Attrs, xml.Attr{
Name: xml.Name{Local: name},
Value: nsURI,
})
}

func (i *Item) AddExtension(extend interface{}) {
i.Extension = append(i.Extension, extend)
}

func (i *Item) AddExtensionString(name string, nsURI string, value string) {
i.Extension = append(i.Extension, struct {
XMLName xml.Name
Text string `xml:",chardata"`
}{
XMLName: xml.Name{Local: name, Space: nsURI},
Text: value,
})
}

func (i *Item) AddExtensionInt(name string, nsURI string, value int) {
i.Extension = append(i.Extension, struct {
XMLName xml.Name
Number int `xml:",chardata"`
}{
XMLName: xml.Name{Local: name, Space: nsURI},
Number: value,
})
}

func (i *Item) AddExtensionUint(name string, nsURI string, value uint) {
i.Extension = append(i.Extension, struct {
XMLName xml.Name
Number uint `xml:",chardata"`
}{
XMLName: xml.Name{Local: name, Space: nsURI},
Number: value,
})
}

func (i *Item) AddExtensionFloat64(name string, nsURI string, value float64) {
i.Extension = append(i.Extension, struct {
XMLName xml.Name
Number float64 `xml:",chardata"`
}{
XMLName: xml.Name{Local: name, Space: nsURI},
Number: value,
})
}

// returns the first non-zero time formatted as a string or ""
func anyTimeFormat(format string, times ...time.Time) string {
for _, t := range times {
Expand Down
40 changes: 22 additions & 18 deletions rss.go
Original file line number Diff line number Diff line change
Expand Up @@ -41,24 +41,25 @@ type RssTextInput struct {
}

type RssFeed struct {
XMLName xml.Name `xml:"channel"`
Title string `xml:"title"` // required
Link string `xml:"link"` // required
Description string `xml:"description"` // required
Language string `xml:"language,omitempty"`
Copyright string `xml:"copyright,omitempty"`
ManagingEditor string `xml:"managingEditor,omitempty"` // Author used
WebMaster string `xml:"webMaster,omitempty"`
PubDate string `xml:"pubDate,omitempty"` // created or updated
LastBuildDate string `xml:"lastBuildDate,omitempty"` // updated used
Category string `xml:"category,omitempty"`
Generator string `xml:"generator,omitempty"`
Docs string `xml:"docs,omitempty"`
Cloud string `xml:"cloud,omitempty"`
Ttl int `xml:"ttl,omitempty"`
Rating string `xml:"rating,omitempty"`
SkipHours string `xml:"skipHours,omitempty"`
SkipDays string `xml:"skipDays,omitempty"`
XMLName xml.Name `xml:"channel"`
Attrs []xml.Attr `xml:",attr"`
Title string `xml:"title"` // required
Link string `xml:"link"` // required
Description string `xml:"description"` // required
Language string `xml:"language,omitempty"`
Copyright string `xml:"copyright,omitempty"`
ManagingEditor string `xml:"managingEditor,omitempty"` // Author used
WebMaster string `xml:"webMaster,omitempty"`
PubDate string `xml:"pubDate,omitempty"` // created or updated
LastBuildDate string `xml:"lastBuildDate,omitempty"` // updated used
Category string `xml:"category,omitempty"`
Generator string `xml:"generator,omitempty"`
Docs string `xml:"docs,omitempty"`
Cloud string `xml:"cloud,omitempty"`
Ttl int `xml:"ttl,omitempty"`
Rating string `xml:"rating,omitempty"`
SkipHours string `xml:"skipHours,omitempty"`
SkipDays string `xml:"skipDays,omitempty"`
Image *RssImage
TextInput *RssTextInput
Items []*RssItem
Expand All @@ -77,6 +78,7 @@ type RssItem struct {
Guid string `xml:"guid,omitempty"` // Id used
PubDate string `xml:"pubDate,omitempty"` // created or updated
Source string `xml:"source,omitempty"`
Extensions interface{}
}

type RssEnclosure struct {
Expand All @@ -99,6 +101,7 @@ func newRssItem(i *Item) *RssItem {
Description: i.Description,
Guid: i.Id,
PubDate: anyTimeFormat(time.RFC1123Z, i.Created, i.Updated),
Extensions: i.Extension,
}
if len(i.Content) > 0 {
item.Content = &RssContent{Content: i.Content}
Expand Down Expand Up @@ -136,6 +139,7 @@ func (r *Rss) RssFeed() *RssFeed {
}

channel := &RssFeed{
Attrs: r.Attrs,
Title: r.Title,
Link: r.Link.Href,
Description: r.Description,
Expand Down
77 changes: 77 additions & 0 deletions rss_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
package feeds

import (
"bytes"
"testing"
"time"
)

func TestRssFeedExtensions(t *testing.T) {
var rssOutput = `<?xml version="1.0" encoding="UTF-8"?><rss version="2.0" xmlns:content="http://purl.org/rss/1.0/modules/content/">
<channel test="https://example.com/test/uri">
<title>Example</title>
<link>https://rss.example.com</link>
<description>Example Example</description>
<copyright>copyright © Example</copyright>
<managingEditor>Example (Example)</managingEditor>
<pubDate>Wed, 16 Jan 2013 21:52:35 -0500</pubDate>
<item>
<title>Example example</title>
<link>https://example.com/link</link>
<description>example</description>
<content:encoded><![CDATA[Example example example, example example...]]></content:encoded>
<author>Jason Moiron</author>
<pubDate>Wed, 16 Jan 2013 21:52:35 -0500</pubDate>
<test:version>v1</test:version>
<test:example>1234567890</test:example>
</item>
</channel>
</rss>`

now, err := time.Parse(time.RFC3339, "2013-01-16T21:52:35-05:00")
if err != nil {
t.Error(err)
}
tz := time.FixedZone("EST", -5*60*60)
now = now.In(tz)

feed := &Feed{
Title: "Example",
Link: &Link{Href: "https://rss.example.com"},
Description: "Example Example",
Author: &Author{Name: "Example", Email: "Example"},
Created: now,
Copyright: "copyright © Example",
}

feed.Items = []*Item{
{
Title: "Example example",
Link: &Link{Href: "https://example.com/link"},
Description: "example",
Author: &Author{Name: "Jason Moiron", Email: "[email protected]"},
Created: now,
Content: "Example example example, example example...",
},
}

feed.AddAttribute("test", "https://example.com/test/uri")
feed.Items[0].AddExtensionString("test:version", "", "v1")
feed.Items[0].AddExtensionInt("test:example", "", 1234567890)

rss, err := feed.ToRss()
if err != nil {
t.Errorf("unexpected error encoding RSS: %v", err)
}
if rss != rssOutput {
t.Errorf("Rss not what was expected. Got:\n%s\n\nExpected:\n%s\n", rss, rssOutput)
}

var buf = new(bytes.Buffer)
if err := feed.WriteRss(buf); err != nil {
t.Errorf("unexpected error writing RSS: %v", err)
}
if got := buf.String(); got != rssOutput {
t.Errorf("Rss not what was expected. Got:\n%s\n\nExpected:\n%s\n", got, rssOutput)
}
}

0 comments on commit 3989cde

Please sign in to comment.