diff --git a/AUTHORS b/AUTHORS index b60ef9b..3f68614 100644 --- a/AUTHORS +++ b/AUTHORS @@ -1,5 +1,2 @@ Daniel Walton - - - - +Josh Beckman \ No newline at end of file diff --git a/README.markdown b/README.markdown index 60b5beb..a328617 100644 --- a/README.markdown +++ b/README.markdown @@ -1,12 +1,12 @@ About ===== -This is a library implementing an RSS feed generator for the Go programming +This is a library implementing an RSS/Podcast feed generator for the Go programming language (http://golang.org/). RSS (Rich Site Summary, or Really Simple Syndication) is a data format used to publish frequently updated works - such as blog entries, news headlines, audio -and video - in a standardized format. +and video - in a standardized format. Podcasts utilize this format to deliver audio and video files and assiciated metadata. An RSS document (which is called a "feed", "web feed", or "channel") includes full or summarized text, plus metadata such as publishing dates and authorship. @@ -20,63 +20,11 @@ Installing Example ======= -```go -package main - -import ( - "fmt" - "github.com/baliw/moverss" - "time" -) - -func main() { - c := moverss.ChannelFactory("Daniel's Channel", "http://RubyDeveloper.com/", "My Blog") - c.SetPubDate(time.Now().UTC()) - - c.AddItem(&moverss.Item{ - Title: "Ruby Developer", - Link: "http://RubyDeveloper.com/", - Description: "Ruby Developer", - PubDate: time.Now().UTC().Format(time.RFC1123), - }) - c.AddItem(&moverss.Item{ - Title: "Stack Overflow", - Link: "http://stackoverflow.com/users/1305696/daniel", - Description: "Stack Overflow", - PubDate: time.Now().UTC().Format(time.RFC1123), - }) - - // Example: Using an item's SetPubDate method - i := &moverss.Item{ - Title: "LinkedIn", - Link: "http://www.linkedin.com/in/dangogh", - Description: "My LinkedIn", - } - i.SetPubDate(time.Now().Unix()) - c.AddItem(i) - - fmt.Printf("%s\n\n", c.Publish()) - fmt.Printf("%s\n\n", c.PublishIndent()) -} -``` - -Full documentation -================== - -Read it [online](http://go.pkgdoc.org/github.com/baliw/moverss) or run - - $ go doc github.com/baliw/moverss - -Other Details -===================== - -A few of the more obscure data points aren't implemented yet. -I haven't seen feeds that implement them yet and I just want to make sure my implementation is good. - -If you find this package useful and want to give back, I'd greatly appreciate a link to my [Ruby developer](http://RubyDeveloper.com/) site. - - +The best example is in [the test file](https://github.com/baliw/moverss/blob/master/gopod_test.go) +Docs +======= +[http://godoc.org/github.com/baliw/moverss](http://godoc.org/github.com/baliw/moverss) diff --git a/moverss.go b/moverss.go index 746b7e4..f31460e 100644 --- a/moverss.go +++ b/moverss.go @@ -1,14 +1,10 @@ -// Copyright 2012 Daniel Walton - All rights reserved. -// Author: Daniel Walton -// https://github.com/baliw -// @dan_gogh - -// Package moverss implements a rss 2.0 feed generator +// Package moverss implements a RSS/Podcast 2.0 feed generator // // // RSS (Rich Site Summary, or Really Simple Syndication) is a data format used // to publish frequently updated works - such as blog entries, news headlines, -// audio and video - in a standardized format. +// audio and video - in a standardized format. Podcasts utilize this format +// to deliver audio and video files and assiciated metadata. // // An RSS document (which is called a "feed", "web feed", or "channel") includes // full or summarized text, plus metadata such as publishing dates and @@ -18,7 +14,7 @@ // // Example Usage // -// c := moverss.ChannelFavtory("Ruby Developer", "http://RubyDeveloper.com/", "Ruby Developer Blog") +// c := moverss.ChannelFavtory("Ruby Developer", "http://RubyDeveloper.com/", "Ruby Developer Blog", "http://example.com/image.png") // c.AddItem(&moverss.Item{ // Title:"Ruby Developer", // Link:"http://RubyDeveloper.com/", @@ -75,8 +71,15 @@ type Channel struct { TTL string `xml:"ttl,omitempty"` SkipHours string `xml:"skiphours,omitempty"` SkipDays string `xml:"skipdays,omitempty"` + TunesAuthor string `xml:"itunes:author,omitempty"` + TunesSubtitle string `xml:"itunes:subtitle,omitempty"` + TunesSummary string `xml:"itunes:summary,omitempty"` + TunesExplicit string `xml:"itunes:explicit,omitempty"` - Items []*Item + TunesOwner []*TunesOwner + TunesImage []*TunesImage + AtomLink []*AtomLink + Items []*Item // [Fields to be implemented] // Cloud @@ -88,6 +91,27 @@ type Channel struct { XMLName xml.Name `xml:"channel"` } +type TunesOwner struct { + Name string `xml:"itunes:name,omitempty"` + Email string `xml:"itunes:email,omitempty"` + + XMLName xml.Name `xml:"itunes:owner"` +} + +type TunesImage struct { + Href string `xml:"href,attr"` + + XMLName xml.Name `xml:"itunes:image"` +} + +type AtomLink struct { + Href string `xml:"href,attr"` + Rel string `xml:"rel,attr"` + Type string `xml:"type,attr"` + + XMLName xml.Name `xml:"atom:link"` +} + type Item struct { //The URL of the item. Link string `xml:"link"` @@ -114,15 +138,27 @@ type Item struct { // http://cyber.law.harvard.edu/rss/rss.html#ltcommentsgtSubelementOfLtitemgt Comments string `xml:"comments,omitempty"` - // [Fields to be implemented] - // Category - // Enclosure - // Source + Creator string `xml:"dc:creator,omitempty"` + TunesAuthor string `xml:"itunes:author,omitempty"` + TunesSubtitle string `xml:"itunes:subtitle,omitempty"` + TunesSummary string `xml:"itunes:summary,omitempty"` + TunesExplicit string `xml:"itunes:explicit,omitempty"` + TunesDuration string `xml:"itunes:duration,omitempty"` + + Enclosure []*Enclosure // Stub member just for the xml generator. XMLName xml.Name `xml:"item"` } +type Enclosure struct { + Url string `xml:"url,attr"` + Length string `xml:"length,attr"` + Type string `xml:"type,attr"` + + XMLName xml.Name `xml:"enclosure"` +} + // Use this to create the base channel of the rss feed. // The Title is the name of the channel. It's how people refer to your // service. If you have an HTML website that contains the same information @@ -130,12 +166,23 @@ type Item struct { // title of your website. // The Link is the URL to the HTML website corresponding to the channel. // The Description is the phrase or sentence describing the channel. +// The Image is the image to be displayed with the podcast. func ChannelFactory(Title string, Link string, Description string) *Channel { c := &Channel{Title: Title, Link: Link, Description: Description} - c.Generator = "Moverrs - http://github.com/baliw/moverss" + c.Generator = "moverss - http://github.com/baliw/moverss" + c.AtomLink = append(c.AtomLink, &AtomLink{ + Href: Link, + Rel: "self", + Type: "application/rss+xml", + }) return c } +// Add an image struct to the feed +func (c *Channel) SetTunesImage(i *TunesImage) { + c.TunesImage = append(c.TunesImage, i) +} + // Add an item to the feed list func (c *Channel) AddItem(i *Item) { c.Items = append(c.Items, i) @@ -148,8 +195,8 @@ func (c *Channel) Publish() []byte { panic(err) } return bytes.Join([][]byte{ - []byte(``), - []byte(``), + []byte(``), + []byte(``), output, []byte(``), }, []byte("")) @@ -162,8 +209,8 @@ func (c *Channel) PublishIndent() []byte { panic(err) } return bytes.Join([][]byte{ - []byte(``), - []byte(``), + []byte(``), + []byte(``), output, []byte(``), }, []byte("\n")) @@ -283,13 +330,33 @@ func (c *Channel) SetSkipDays(skipdays string) { c.SkipDays = skipdays } -// (Not implemented) Set the cloud field. The cloud field allows processes to -// register with a cloud to be notified of updates to the channel, implementing -// a lightweight publish-subscribe protocol for RSS feeds. More Info: -// http://cyber.law.harvard.edu/rss/rss.html#ltcloudgtSubelementOfLtchannelgt -//func (c *Channel) SetCloud(cloud string) { -// return -//} +// (optional) Set the channel's iTunes Explicit field. +func (c *Channel) SetiTunesExplicit(explicit string) { + c.TunesExplicit = explicit +} + +// (optional) Set the channel's iTunes Author field. +func (c *Channel) SetiTunesAuthor(author string) { + c.TunesAuthor = author +} + +// (optional) Set the channel's iTunes Subtitle field. +func (c *Channel) SetiTunesSubtitle(subtitle string) { + c.TunesSubtitle = subtitle +} + +// (optional) Set the channel's iTunes Summary field. +func (c *Channel) SetiTunesSummary(summary string) { + c.TunesSummary = summary +} + +// (optional) Set the channel's iTunes Owner struct. +func (c *Channel) SetiTunesOwner(name string, email string) { + c.TunesOwner = append(c.TunesOwner, &TunesOwner{ + Name: name, + Email: email, + }) +} // (optional) Set the item's pubDate field. This method can take an instance // of time.Time, a unix timestamp (int64) or a raw string to use for the date. @@ -312,3 +379,12 @@ func (i *Item) SetPubDate(t interface{}) { } panic("moverss.Item.SetPubDate() error: Invalid date type") } + +// (optional) Set the item's iTunes Enclosure struct. +func (i *Item) SetEnclosure(url string, length string, eType string) { + i.Enclosure = append(i.Enclosure, &Enclosure{ + Url: url, + Length: length, + Type: eType, + }) +} diff --git a/moverss_test.go b/moverss_test.go index 7dd37bf..e9b93fb 100644 --- a/moverss_test.go +++ b/moverss_test.go @@ -1,11 +1,5 @@ -// Copyright 2012 Daniel Walton - All rights reserved. -// Author: Daniel Walton -// https://github.com/baliw -// @dan_gogh - // -// This package implements a rss 2.0 feed generator based on the spec -// located at: http://cyber.law.harvard.edu/rss/rss.html +// This package implements a RSS/Podcast 2.0 feed generator // // Test code for moverss. // @@ -22,30 +16,33 @@ import ( ) func Test1(*testing.T) { - fmt.Printf("Testing Moverss...\n") + fmt.Printf("Testing moverss...\n") c := ChannelFactory("Daniel's Channel", "http://RubyDeveloper.com/", "My Blog") c.SetPubDate(time.Now().UTC()) + c.SetiTunesExplicit("No") - c.AddItem(&Item{ - Title: "Ruby Developer", - Link: "http://RubyDeveloper.com/", - Description: "Ruby Developer", - PubDate: time.Now().UTC().Format(time.RFC1123), - }) c.AddItem(&Item{ Title: "Stack Overflow", - Link: "http://stackoverflow.com/users/1305696/daniel", + Link: "http://stackoverflow.com", Description: "Stack Overflow", PubDate: time.Now().UTC().Format(time.RFC1123), }) - // Example: Using an item's SetPubDate method + // Example: Using an item's methods + t := "My title" + l := "http://linkedin.com" i := &Item{ - Title: "LinkedIn", - Link: "http://www.linkedin.com/in/dangogh", - Description: "My LinkedIn", + Title: t, + TunesSubtitle: t, + Link: l, + Description: "My LinkedIn", + TunesDuration: "600", + TunesSummary: "I asked myself that question more than a decade ago and it changed my...", + Guid: l, + Creator: "Daniel's Channel", } + i.SetEnclosure("http://example.com/sound.mp3", "600", "audio/mpeg") i.SetPubDate(time.Now().Unix()) c.AddItem(i)