diff options
author | 6543 <6543@obermui.de> | 2021-10-16 16:21:16 +0200 |
---|---|---|
committer | GitHub <noreply@github.com> | 2021-10-16 16:21:16 +0200 |
commit | 3728f1daa08e4c228db212844612555e9e2904df (patch) | |
tree | a47302aa3106ee33643ebcdaa4b2c5fe52349596 /vendor | |
parent | 8edda8b446200545b36432b57d00cd1972a5cb7e (diff) | |
download | gitea-3728f1daa08e4c228db212844612555e9e2904df.tar.gz gitea-3728f1daa08e4c228db212844612555e9e2904df.zip |
Add RSS/Atom feed support for user actions (#16002)
Return rss/atom feed for user based on rss url suffix or Content-Type header.
Diffstat (limited to 'vendor')
-rw-r--r-- | vendor/github.com/gorilla/feeds/.travis.yml | 16 | ||||
-rw-r--r-- | vendor/github.com/gorilla/feeds/AUTHORS | 29 | ||||
-rw-r--r-- | vendor/github.com/gorilla/feeds/LICENSE | 22 | ||||
-rw-r--r-- | vendor/github.com/gorilla/feeds/README.md | 185 | ||||
-rw-r--r-- | vendor/github.com/gorilla/feeds/atom.go | 169 | ||||
-rw-r--r-- | vendor/github.com/gorilla/feeds/doc.go | 73 | ||||
-rw-r--r-- | vendor/github.com/gorilla/feeds/feed.go | 145 | ||||
-rw-r--r-- | vendor/github.com/gorilla/feeds/json.go | 183 | ||||
-rw-r--r-- | vendor/github.com/gorilla/feeds/rss.go | 168 | ||||
-rw-r--r-- | vendor/github.com/gorilla/feeds/test.atom | 92 | ||||
-rw-r--r-- | vendor/github.com/gorilla/feeds/test.rss | 96 | ||||
-rw-r--r-- | vendor/github.com/gorilla/feeds/to-implement.md | 20 | ||||
-rw-r--r-- | vendor/github.com/gorilla/feeds/uuid.go | 27 | ||||
-rw-r--r-- | vendor/modules.txt | 3 |
14 files changed, 1228 insertions, 0 deletions
diff --git a/vendor/github.com/gorilla/feeds/.travis.yml b/vendor/github.com/gorilla/feeds/.travis.yml new file mode 100644 index 0000000000..7939a21866 --- /dev/null +++ b/vendor/github.com/gorilla/feeds/.travis.yml @@ -0,0 +1,16 @@ +language: go +sudo: false +matrix: + include: + - go: 1.8 + - go: 1.9 + - go: "1.10" + - go: 1.x + - go: tip + allow_failures: + - go: tip +script: + - go get -t -v ./... + - diff -u <(echo -n) <(gofmt -d -s .) + - go vet . + - go test -v -race ./... diff --git a/vendor/github.com/gorilla/feeds/AUTHORS b/vendor/github.com/gorilla/feeds/AUTHORS new file mode 100644 index 0000000000..2c28cf943a --- /dev/null +++ b/vendor/github.com/gorilla/feeds/AUTHORS @@ -0,0 +1,29 @@ +# This is the official list of gorilla/feeds authors for copyright purposes. +# Please keep the list sorted. + +Dmitry Chestnykh <dmitry@codingrobots.com> +Eddie Scholtz <eascholtz@gmail.com> +Gabriel Simmer <bladesimmer@gmail.com> +Google LLC (https://opensource.google.com/) +honky <honky@defendtheplanet.net> +James Gregory <james@jagregory.com> +Jason Hall <imjasonh@gmail.com> +Jason Moiron <jmoiron@jmoiron.net> +Kamil Kisiel <kamil@kamilkisiel.net> +Kevin Stock <kevinstock@tantalic.com> +Markus Zimmermann <markus.zimmermann@nethead.at> +Matt Silverlock <matt@eatsleeprepeat.net> +Matthew Dawson <matthew@mjdsystems.ca> +Milan Aleksic <milanaleksic@gmail.com> +Milan Aleksić <milanaleksic@gmail.com> +nlimpid <jshuangzl@gmail.com> +Paul Petring <paul@defendtheplanet.net> +Sean Enck <enckse@users.noreply.github.com> +Sue Spence <virtuallysue@gmail.com> +Supermighty <ukiah@faction.com> +Toru Fukui <fukuimone@gmail.com> +Vabd <vabd@anon.acme> +Volker <lists.volker@gmail.com> +ZhiFeng Hu <hufeng1987@gmail.com> +weberc2 <weberc2@gmail.com> + diff --git a/vendor/github.com/gorilla/feeds/LICENSE b/vendor/github.com/gorilla/feeds/LICENSE new file mode 100644 index 0000000000..e24412d561 --- /dev/null +++ b/vendor/github.com/gorilla/feeds/LICENSE @@ -0,0 +1,22 @@ +Copyright (c) 2013-2018 The Gorilla Feeds Authors. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/vendor/github.com/gorilla/feeds/README.md b/vendor/github.com/gorilla/feeds/README.md new file mode 100644 index 0000000000..4d733cf538 --- /dev/null +++ b/vendor/github.com/gorilla/feeds/README.md @@ -0,0 +1,185 @@ +## 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.svg?branch=master)](https://travis-ci.org/gorilla/feeds) + +feeds is a web feed generator library for generating RSS, Atom and JSON feeds from Go +applications. + +### Goals + + * Provide a simple interface to create both Atom & RSS 2.0 feeds + * Full support for [Atom][atom], [RSS 2.0][rss], and [JSON Feed Version 1][jsonfeed] spec elements + * Ability to modify particulars for each spec + +[atom]: https://tools.ietf.org/html/rfc4287 +[rss]: http://www.rssboard.org/rss-specification +[jsonfeed]: https://jsonfeed.org/version/1 + +### Usage + +```go +package main + +import ( + "fmt" + "log" + "time" + "github.com/gorilla/feeds" +) + +func main() { + now := time.Now() + feed := &feeds.Feed{ + Title: "jmoiron.net blog", + Link: &feeds.Link{Href: "http://jmoiron.net/blog"}, + Description: "discussion about tech, footie, photos", + Author: &feeds.Author{Name: "Jason Moiron", Email: "jmoiron@jmoiron.net"}, + Created: now, + } + + feed.Items = []*feeds.Item{ + &feeds.Item{ + Title: "Limiting Concurrency in Go", + Link: &feeds.Link{Href: "http://jmoiron.net/blog/limiting-concurrency-in-go/"}, + Description: "A discussion on controlled parallelism in golang", + Author: &feeds.Author{Name: "Jason Moiron", Email: "jmoiron@jmoiron.net"}, + Created: now, + }, + &feeds.Item{ + Title: "Logic-less Template Redux", + Link: &feeds.Link{Href: "http://jmoiron.net/blog/logicless-template-redux/"}, + Description: "More thoughts on logicless templates", + Created: now, + }, + &feeds.Item{ + Title: "Idiomatic Code Reuse in Go", + Link: &feeds.Link{Href: "http://jmoiron.net/blog/idiomatic-code-reuse-in-go/"}, + Description: "How to use interfaces <em>effectively</em>", + Created: now, + }, + } + + atom, err := feed.ToAtom() + if err != nil { + log.Fatal(err) + } + + rss, err := feed.ToRss() + if err != nil { + log.Fatal(err) + } + + json, err := feed.ToJSON() + if err != nil { + log.Fatal(err) + } + + fmt.Println(atom, "\n", rss, "\n", json) +} +``` + +Outputs: + +```xml +<?xml version="1.0" encoding="UTF-8"?> +<feed xmlns="http://www.w3.org/2005/Atom"> + <title>jmoiron.net blog</title> + <link href="http://jmoiron.net/blog"></link> + <id>http://jmoiron.net/blog</id> + <updated>2013-01-16T03:26:01-05:00</updated> + <summary>discussion about tech, footie, photos</summary> + <entry> + <title>Limiting Concurrency in Go</title> + <link href="http://jmoiron.net/blog/limiting-concurrency-in-go/"></link> + <updated>2013-01-16T03:26:01-05:00</updated> + <id>tag:jmoiron.net,2013-01-16:/blog/limiting-concurrency-in-go/</id> + <summary type="html">A discussion on controlled parallelism in golang</summary> + <author> + <name>Jason Moiron</name> + <email>jmoiron@jmoiron.net</email> + </author> + </entry> + <entry> + <title>Logic-less Template Redux</title> + <link href="http://jmoiron.net/blog/logicless-template-redux/"></link> + <updated>2013-01-16T03:26:01-05:00</updated> + <id>tag:jmoiron.net,2013-01-16:/blog/logicless-template-redux/</id> + <summary type="html">More thoughts on logicless templates</summary> + <author></author> + </entry> + <entry> + <title>Idiomatic Code Reuse in Go</title> + <link href="http://jmoiron.net/blog/idiomatic-code-reuse-in-go/"></link> + <updated>2013-01-16T03:26:01-05:00</updated> + <id>tag:jmoiron.net,2013-01-16:/blog/idiomatic-code-reuse-in-go/</id> + <summary type="html">How to use interfaces <em>effectively</em></summary> + <author></author> + </entry> +</feed> + +<?xml version="1.0" encoding="UTF-8"?> +<rss version="2.0"> + <channel> + <title>jmoiron.net blog</title> + <link>http://jmoiron.net/blog</link> + <description>discussion about tech, footie, photos</description> + <managingEditor>jmoiron@jmoiron.net (Jason Moiron)</managingEditor> + <pubDate>2013-01-16T03:22:24-05:00</pubDate> + <item> + <title>Limiting Concurrency in Go</title> + <link>http://jmoiron.net/blog/limiting-concurrency-in-go/</link> + <description>A discussion on controlled parallelism in golang</description> + <pubDate>2013-01-16T03:22:24-05:00</pubDate> + </item> + <item> + <title>Logic-less Template Redux</title> + <link>http://jmoiron.net/blog/logicless-template-redux/</link> + <description>More thoughts on logicless templates</description> + <pubDate>2013-01-16T03:22:24-05:00</pubDate> + </item> + <item> + <title>Idiomatic Code Reuse in Go</title> + <link>http://jmoiron.net/blog/idiomatic-code-reuse-in-go/</link> + <description>How to use interfaces <em>effectively</em></description> + <pubDate>2013-01-16T03:22:24-05:00</pubDate> + </item> + </channel> +</rss> + +{ + "version": "https://jsonfeed.org/version/1", + "title": "jmoiron.net blog", + "home_page_url": "http://jmoiron.net/blog", + "description": "discussion about tech, footie, photos", + "author": { + "name": "Jason Moiron" + }, + "items": [ + { + "id": "", + "url": "http://jmoiron.net/blog/limiting-concurrency-in-go/", + "title": "Limiting Concurrency in Go", + "summary": "A discussion on controlled parallelism in golang", + "date_published": "2013-01-16T03:22:24.530817846-05:00", + "author": { + "name": "Jason Moiron" + } + }, + { + "id": "", + "url": "http://jmoiron.net/blog/logicless-template-redux/", + "title": "Logic-less Template Redux", + "summary": "More thoughts on logicless templates", + "date_published": "2013-01-16T03:22:24.530817846-05:00" + }, + { + "id": "", + "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", + "date_published": "2013-01-16T03:22:24.530817846-05:00" + } + ] +} +``` + diff --git a/vendor/github.com/gorilla/feeds/atom.go b/vendor/github.com/gorilla/feeds/atom.go new file mode 100644 index 0000000000..7196f4781e --- /dev/null +++ b/vendor/github.com/gorilla/feeds/atom.go @@ -0,0 +1,169 @@ +package feeds + +import ( + "encoding/xml" + "fmt" + "net/url" + "time" +) + +// Generates Atom feed as XML + +const ns = "http://www.w3.org/2005/Atom" + +type AtomPerson struct { + Name string `xml:"name,omitempty"` + Uri string `xml:"uri,omitempty"` + Email string `xml:"email,omitempty"` +} + +type AtomSummary struct { + XMLName xml.Name `xml:"summary"` + Content string `xml:",chardata"` + Type string `xml:"type,attr"` +} + +type AtomContent struct { + XMLName xml.Name `xml:"content"` + Content string `xml:",chardata"` + Type string `xml:"type,attr"` +} + +type AtomAuthor struct { + XMLName xml.Name `xml:"author"` + AtomPerson +} + +type AtomContributor struct { + XMLName xml.Name `xml:"contributor"` + AtomPerson +} + +type AtomEntry struct { + XMLName xml.Name `xml:"entry"` + Xmlns string `xml:"xmlns,attr,omitempty"` + Title string `xml:"title"` // required + Updated string `xml:"updated"` // required + Id string `xml:"id"` // required + Category string `xml:"category,omitempty"` + Content *AtomContent + Rights string `xml:"rights,omitempty"` + Source string `xml:"source,omitempty"` + Published string `xml:"published,omitempty"` + Contributor *AtomContributor + 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"` + Href string `xml:"href,attr"` + Rel string `xml:"rel,attr,omitempty"` + Type string `xml:"type,attr,omitempty"` + Length string `xml:"length,attr,omitempty"` +} + +type AtomFeed struct { + XMLName xml.Name `xml:"feed"` + Xmlns string `xml:"xmlns,attr"` + Title string `xml:"title"` // required + Id string `xml:"id"` // required + Updated string `xml:"updated"` // required + Category string `xml:"category,omitempty"` + Icon string `xml:"icon,omitempty"` + Logo string `xml:"logo,omitempty"` + Rights string `xml:"rights,omitempty"` // copyright used + Subtitle string `xml:"subtitle,omitempty"` + Link *AtomLink + Author *AtomAuthor `xml:"author,omitempty"` + Contributor *AtomContributor + Entries []*AtomEntry `xml:"entry"` +} + +type Atom struct { + *Feed +} + +func newAtomEntry(i *Item) *AtomEntry { + id := i.Id + // assume the description is html + s := &AtomSummary{Content: i.Description, Type: "html"} + + if len(id) == 0 { + // if there's no id set, try to create one, either from data or just a uuid + if len(i.Link.Href) > 0 && (!i.Created.IsZero() || !i.Updated.IsZero()) { + dateStr := anyTimeFormat("2006-01-02", i.Updated, i.Created) + host, path := i.Link.Href, "/invalid.html" + if url, err := url.Parse(i.Link.Href); err == nil { + host, path = url.Host, url.Path + } + id = fmt.Sprintf("tag:%s,%s:%s", host, dateStr, path) + } else { + id = "urn:uuid:" + NewUUID().String() + } + } + var name, email string + if i.Author != nil { + name, email = i.Author.Name, i.Author.Email + } + + link_rel := i.Link.Rel + if link_rel == "" { + link_rel = "alternate" + } + x := &AtomEntry{ + Title: i.Title, + Links: []AtomLink{{Href: i.Link.Href, Rel: link_rel, Type: i.Link.Type}}, + Id: id, + Updated: anyTimeFormat(time.RFC3339, i.Updated, i.Created), + Summary: s, + } + + // if there's a content, assume it's html + if len(i.Content) > 0 { + x.Content = &AtomContent{Content: i.Content, Type: "html"} + } + + 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 { + x.Author = &AtomAuthor{AtomPerson: AtomPerson{Name: name, Email: email}} + } + return x +} + +// create a new AtomFeed with a generic Feed struct's data +func (a *Atom) AtomFeed() *AtomFeed { + updated := anyTimeFormat(time.RFC3339, a.Updated, a.Created) + feed := &AtomFeed{ + Xmlns: ns, + Title: a.Title, + Link: &AtomLink{Href: a.Link.Href, Rel: a.Link.Rel}, + Subtitle: a.Description, + Id: a.Link.Href, + Updated: updated, + Rights: a.Copyright, + } + if a.Author != nil { + feed.Author = &AtomAuthor{AtomPerson: AtomPerson{Name: a.Author.Name, Email: a.Author.Email}} + } + for _, e := range a.Items { + feed.Entries = append(feed.Entries, newAtomEntry(e)) + } + return feed +} + +// FeedXml returns an XML-Ready object for an Atom object +func (a *Atom) FeedXml() interface{} { + return a.AtomFeed() +} + +// FeedXml returns an XML-ready object for an AtomFeed object +func (a *AtomFeed) FeedXml() interface{} { + return a +} diff --git a/vendor/github.com/gorilla/feeds/doc.go b/vendor/github.com/gorilla/feeds/doc.go new file mode 100644 index 0000000000..4e0759cccc --- /dev/null +++ b/vendor/github.com/gorilla/feeds/doc.go @@ -0,0 +1,73 @@ +/* +Syndication (feed) generator library for golang. + +Installing + + go get github.com/gorilla/feeds + +Feeds provides a simple, generic Feed interface with a generic Item object as well as RSS, Atom and JSON Feed specific RssFeed, AtomFeed and JSONFeed objects which allow access to all of each spec's defined elements. + +Examples + +Create a Feed and some Items in that feed using the generic interfaces: + + import ( + "time" + . "github.com/gorilla/feeds" + ) + + now = time.Now() + + feed := &Feed{ + Title: "jmoiron.net blog", + Link: &Link{Href: "http://jmoiron.net/blog"}, + Description: "discussion about tech, footie, photos", + Author: &Author{Name: "Jason Moiron", Email: "jmoiron@jmoiron.net"}, + Created: now, + Copyright: "This work is copyright © Benjamin Button", + } + + feed.Items = []*Item{ + &Item{ + Title: "Limiting Concurrency in Go", + Link: &Link{Href: "http://jmoiron.net/blog/limiting-concurrency-in-go/"}, + Description: "A discussion on controlled parallelism in golang", + Author: &Author{Name: "Jason Moiron", Email: "jmoiron@jmoiron.net"}, + Created: now, + }, + &Item{ + Title: "Logic-less Template Redux", + Link: &Link{Href: "http://jmoiron.net/blog/logicless-template-redux/"}, + Description: "More thoughts on logicless templates", + Created: now, + }, + &Item{ + 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>", + Created: now, + }, + } + +From here, you can output Atom, RSS, or JSON Feed versions of this feed easily + + atom, err := feed.ToAtom() + rss, err := feed.ToRss() + json, err := feed.ToJSON() + +You can also get access to the underlying objects that feeds uses to export its XML + + atomFeed := (&Atom{Feed: feed}).AtomFeed() + rssFeed := (&Rss{Feed: feed}).RssFeed() + jsonFeed := (&JSON{Feed: feed}).JSONFeed() + +From here, you can modify or add each syndication's specific fields before outputting + + atomFeed.Subtitle = "plays the blues" + atom, err := ToXML(atomFeed) + rssFeed.Generator = "gorilla/feeds v1.0 (github.com/gorilla/feeds)" + rss, err := ToXML(rssFeed) + jsonFeed.NextUrl = "https://www.example.com/feed.json?page=2" + json, err := jsonFeed.ToJSON() +*/ +package feeds diff --git a/vendor/github.com/gorilla/feeds/feed.go b/vendor/github.com/gorilla/feeds/feed.go new file mode 100644 index 0000000000..790a1b6ce6 --- /dev/null +++ b/vendor/github.com/gorilla/feeds/feed.go @@ -0,0 +1,145 @@ +package feeds + +import ( + "encoding/json" + "encoding/xml" + "io" + "sort" + "time" +) + +type Link struct { + Href, Rel, Type, Length string +} + +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 + Source *Link + Author *Author + Description string // used as description in rss, summary in atom + Id string // used as guid in rss, id in atom + Updated time.Time + Created time.Time + Enclosure *Enclosure + Content string +} + +type Feed struct { + Title string + Link *Link + Description string + Author *Author + Updated time.Time + Created time.Time + Id string + Subtitle string + Items []*Item + Copyright string + Image *Image +} + +// add a new Item to a Feed +func (f *Feed) Add(item *Item) { + f.Items = append(f.Items, item) +} + +// returns the first non-zero time formatted as a string or "" +func anyTimeFormat(format string, times ...time.Time) string { + for _, t := range times { + if !t.IsZero() { + return t.Format(format) + } + } + return "" +} + +// interface used by ToXML to get a object suitable for exporting XML. +type XmlFeed interface { + FeedXml() interface{} +} + +// turn a feed object (either a Feed, AtomFeed, or RssFeed) into xml +// returns an error if xml marshaling fails +func ToXML(feed XmlFeed) (string, error) { + x := feed.FeedXml() + data, err := xml.MarshalIndent(x, "", " ") + if err != nil { + return "", err + } + // strip empty line from default xml header + s := xml.Header[:len(xml.Header)-1] + string(data) + return s, nil +} + +// WriteXML writes a feed object (either a Feed, AtomFeed, or RssFeed) as XML into +// the writer. Returns an error if XML marshaling fails. +func WriteXML(feed XmlFeed, w io.Writer) error { + x := feed.FeedXml() + // write default xml header, without the newline + if _, err := w.Write([]byte(xml.Header[:len(xml.Header)-1])); err != nil { + return err + } + e := xml.NewEncoder(w) + e.Indent("", " ") + return e.Encode(x) +} + +// creates an Atom representation of this feed +func (f *Feed) ToAtom() (string, error) { + a := &Atom{f} + return ToXML(a) +} + +// WriteAtom writes an Atom representation of this feed to the writer. +func (f *Feed) WriteAtom(w io.Writer) error { + return WriteXML(&Atom{f}, w) +} + +// creates an Rss representation of this feed +func (f *Feed) ToRss() (string, error) { + r := &Rss{f} + return ToXML(r) +} + +// WriteRss writes an RSS representation of this feed to the writer. +func (f *Feed) WriteRss(w io.Writer) error { + return WriteXML(&Rss{f}, w) +} + +// ToJSON creates a JSON Feed representation of this feed +func (f *Feed) ToJSON() (string, error) { + j := &JSON{f} + return j.ToJSON() +} + +// WriteJSON writes an JSON representation of this feed to the writer. +func (f *Feed) WriteJSON(w io.Writer) error { + j := &JSON{f} + feed := j.JSONFeed() + + e := json.NewEncoder(w) + e.SetIndent("", " ") + return e.Encode(feed) +} + +// Sort sorts the Items in the feed with the given less function. +func (f *Feed) Sort(less func(a, b *Item) bool) { + lessFunc := func(i, j int) bool { + return less(f.Items[i], f.Items[j]) + } + sort.SliceStable(f.Items, lessFunc) +} diff --git a/vendor/github.com/gorilla/feeds/json.go b/vendor/github.com/gorilla/feeds/json.go new file mode 100644 index 0000000000..75a82fd62a --- /dev/null +++ b/vendor/github.com/gorilla/feeds/json.go @@ -0,0 +1,183 @@ +package feeds + +import ( + "encoding/json" + "strings" + "time" +) + +const jsonFeedVersion = "https://jsonfeed.org/version/1" + +// JSONAuthor represents the author of the feed or of an individual item +// in the feed +type JSONAuthor struct { + Name string `json:"name,omitempty"` + Url string `json:"url,omitempty"` + Avatar string `json:"avatar,omitempty"` +} + +// JSONAttachment represents a related resource. Podcasts, for instance, would +// include an attachment that’s an audio or video file. +type JSONAttachment struct { + Url string `json:"url,omitempty"` + MIMEType string `json:"mime_type,omitempty"` + Title string `json:"title,omitempty"` + Size int32 `json:"size,omitempty"` + Duration time.Duration `json:"duration_in_seconds,omitempty"` +} + +// MarshalJSON implements the json.Marshaler interface. +// The Duration field is marshaled in seconds, all other fields are marshaled +// based upon the definitions in struct tags. +func (a *JSONAttachment) MarshalJSON() ([]byte, error) { + type EmbeddedJSONAttachment JSONAttachment + return json.Marshal(&struct { + Duration float64 `json:"duration_in_seconds,omitempty"` + *EmbeddedJSONAttachment + }{ + EmbeddedJSONAttachment: (*EmbeddedJSONAttachment)(a), + Duration: a.Duration.Seconds(), + }) +} + +// UnmarshalJSON implements the json.Unmarshaler interface. +// The Duration field is expected to be in seconds, all other field types +// match the struct definition. +func (a *JSONAttachment) UnmarshalJSON(data []byte) error { + type EmbeddedJSONAttachment JSONAttachment + var raw struct { + Duration float64 `json:"duration_in_seconds,omitempty"` + *EmbeddedJSONAttachment + } + raw.EmbeddedJSONAttachment = (*EmbeddedJSONAttachment)(a) + + err := json.Unmarshal(data, &raw) + if err != nil { + return err + } + + if raw.Duration > 0 { + nsec := int64(raw.Duration * float64(time.Second)) + raw.EmbeddedJSONAttachment.Duration = time.Duration(nsec) + } + + return nil +} + +// JSONItem represents a single entry/post for the feed. +type JSONItem struct { + Id string `json:"id"` + Url string `json:"url,omitempty"` + ExternalUrl string `json:"external_url,omitempty"` + Title string `json:"title,omitempty"` + ContentHTML string `json:"content_html,omitempty"` + ContentText string `json:"content_text,omitempty"` + Summary string `json:"summary,omitempty"` + Image string `json:"image,omitempty"` + BannerImage string `json:"banner_,omitempty"` + PublishedDate *time.Time `json:"date_published,omitempty"` + ModifiedDate *time.Time `json:"date_modified,omitempty"` + Author *JSONAuthor `json:"author,omitempty"` + Tags []string `json:"tags,omitempty"` + Attachments []JSONAttachment `json:"attachments,omitempty"` +} + +// JSONHub describes an endpoint that can be used to subscribe to real-time +// notifications from the publisher of this feed. +type JSONHub struct { + Type string `json:"type"` + Url string `json:"url"` +} + +// JSONFeed represents a syndication feed in the JSON Feed Version 1 format. +// Matching the specification found here: https://jsonfeed.org/version/1. +type JSONFeed struct { + Version string `json:"version"` + Title string `json:"title"` + HomePageUrl string `json:"home_page_url,omitempty"` + FeedUrl string `json:"feed_url,omitempty"` + Description string `json:"description,omitempty"` + UserComment string `json:"user_comment,omitempty"` + NextUrl string `json:"next_url,omitempty"` + Icon string `json:"icon,omitempty"` + Favicon string `json:"favicon,omitempty"` + Author *JSONAuthor `json:"author,omitempty"` + Expired *bool `json:"expired,omitempty"` + Hubs []*JSONItem `json:"hubs,omitempty"` + Items []*JSONItem `json:"items,omitempty"` +} + +// JSON is used to convert a generic Feed to a JSONFeed. +type JSON struct { + *Feed +} + +// ToJSON encodes f into a JSON string. Returns an error if marshalling fails. +func (f *JSON) ToJSON() (string, error) { + return f.JSONFeed().ToJSON() +} + +// ToJSON encodes f into a JSON string. Returns an error if marshalling fails. +func (f *JSONFeed) ToJSON() (string, error) { + data, err := json.MarshalIndent(f, "", " ") + if err != nil { + return "", err + } + + return string(data), nil +} + +// JSONFeed creates a new JSONFeed with a generic Feed struct's data. +func (f *JSON) JSONFeed() *JSONFeed { + feed := &JSONFeed{ + Version: jsonFeedVersion, + Title: f.Title, + Description: f.Description, + } + + if f.Link != nil { + feed.HomePageUrl = f.Link.Href + } + if f.Author != nil { + feed.Author = &JSONAuthor{ + Name: f.Author.Name, + } + } + for _, e := range f.Items { + feed.Items = append(feed.Items, newJSONItem(e)) + } + return feed +} + +func newJSONItem(i *Item) *JSONItem { + item := &JSONItem{ + Id: i.Id, + Title: i.Title, + Summary: i.Description, + + ContentHTML: i.Content, + } + + if i.Link != nil { + item.Url = i.Link.Href + } + if i.Source != nil { + item.ExternalUrl = i.Source.Href + } + if i.Author != nil { + item.Author = &JSONAuthor{ + Name: i.Author.Name, + } + } + if !i.Created.IsZero() { + item.PublishedDate = &i.Created + } + if !i.Updated.IsZero() { + item.ModifiedDate = &i.Updated + } + if i.Enclosure != nil && strings.HasPrefix(i.Enclosure.Type, "image/") { + item.Image = i.Enclosure.Url + } + + return item +} diff --git a/vendor/github.com/gorilla/feeds/rss.go b/vendor/github.com/gorilla/feeds/rss.go new file mode 100644 index 0000000000..09179dfb2a --- /dev/null +++ b/vendor/github.com/gorilla/feeds/rss.go @@ -0,0 +1,168 @@ +package feeds + +// rss support +// validation done according to spec here: +// http://cyber.law.harvard.edu/rss/rss.html + +import ( + "encoding/xml" + "fmt" + "time" +) + +// private wrapper around the RssFeed which gives us the <rss>..</rss> xml +type RssFeedXml struct { + XMLName xml.Name `xml:"rss"` + Version string `xml:"version,attr"` + ContentNamespace string `xml:"xmlns:content,attr"` + Channel *RssFeed +} + +type RssContent struct { + XMLName xml.Name `xml:"content:encoded"` + Content string `xml:",cdata"` +} + +type RssImage struct { + XMLName xml.Name `xml:"image"` + Url string `xml:"url"` + Title string `xml:"title"` + Link string `xml:"link"` + Width int `xml:"width,omitempty"` + Height int `xml:"height,omitempty"` +} + +type RssTextInput struct { + XMLName xml.Name `xml:"textInput"` + Title string `xml:"title"` + Description string `xml:"description"` + Name string `xml:"name"` + Link string `xml:"link"` +} + +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"` + Image *RssImage + TextInput *RssTextInput + Items []*RssItem `xml:"item"` +} + +type RssItem struct { + XMLName xml.Name `xml:"item"` + Title string `xml:"title"` // required + Link string `xml:"link"` // required + Description string `xml:"description"` // required + Content *RssContent + Author string `xml:"author,omitempty"` + Category string `xml:"category,omitempty"` + Comments string `xml:"comments,omitempty"` + Enclosure *RssEnclosure + Guid string `xml:"guid,omitempty"` // Id used + PubDate string `xml:"pubDate,omitempty"` // created or updated + Source string `xml:"source,omitempty"` +} + +type RssEnclosure struct { + //RSS 2.0 <enclosure url="http://example.com/file.mp3" length="123456789" type="audio/mpeg" /> + XMLName xml.Name `xml:"enclosure"` + Url string `xml:"url,attr"` + Length string `xml:"length,attr"` + Type string `xml:"type,attr"` +} + +type Rss struct { + *Feed +} + +// create a new RssItem with a generic Item struct's data +func newRssItem(i *Item) *RssItem { + item := &RssItem{ + Title: i.Title, + Link: i.Link.Href, + Description: i.Description, + Guid: i.Id, + PubDate: anyTimeFormat(time.RFC1123Z, i.Created, i.Updated), + } + if len(i.Content) > 0 { + item.Content = &RssContent{Content: i.Content} + } + if i.Source != nil { + item.Source = i.Source.Href + } + + // 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 + } + return item +} + +// create a new RssFeed with a generic Feed struct's data +func (r *Rss) RssFeed() *RssFeed { + pub := anyTimeFormat(time.RFC1123Z, r.Created, r.Updated) + build := anyTimeFormat(time.RFC1123Z, r.Updated) + author := "" + if r.Author != nil { + author = r.Author.Email + if len(r.Author.Name) > 0 { + author = fmt.Sprintf("%s (%s)", r.Author.Email, r.Author.Name) + } + } + + 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, + Description: r.Description, + ManagingEditor: author, + PubDate: pub, + LastBuildDate: build, + Copyright: r.Copyright, + Image: image, + } + for _, i := range r.Items { + channel.Items = append(channel.Items, newRssItem(i)) + } + return channel +} + +// FeedXml returns an XML-Ready object for an Rss object +func (r *Rss) FeedXml() interface{} { + // only generate version 2.0 feeds for now + return r.RssFeed().FeedXml() + +} + +// FeedXml returns an XML-ready object for an RssFeed object +func (r *RssFeed) FeedXml() interface{} { + return &RssFeedXml{ + Version: "2.0", + Channel: r, + ContentNamespace: "http://purl.org/rss/1.0/modules/content/", + } +} diff --git a/vendor/github.com/gorilla/feeds/test.atom b/vendor/github.com/gorilla/feeds/test.atom new file mode 100644 index 0000000000..aa15214815 --- /dev/null +++ b/vendor/github.com/gorilla/feeds/test.atom @@ -0,0 +1,92 @@ +<?xml version="1.0" encoding="UTF-8"?> +<feed xmlns:atom="http://www.w3.org/2005/Atom"> + <title><![CDATA[Lorem ipsum feed for an interval of 1 minutes]]></title> + <description><![CDATA[This is a constantly updating lorem ipsum feed]]></description> + <link>http://example.com/</link> + <generator>RSS for Node</generator> + <lastBuildDate>Tue, 30 Oct 2018 23:22:37 GMT</lastBuildDate> + <author><![CDATA[John Smith]]></author> + <pubDate>Tue, 30 Oct 2018 23:22:00 GMT</pubDate> + <copyright><![CDATA[Michael Bertolacci, licensed under a Creative Commons Attribution 3.0 Unported License.]]></copyright> + <ttl>60</ttl> + <entry> + <title><![CDATA[Lorem ipsum 2018-10-30T23:22:00+00:00]]></title> + <description><![CDATA[Exercitation ut Lorem sint proident.]]></description> + <link>http://example.com/test/1540941720</link> + <guid isPermaLink="true">http://example.com/test/1540941720</guid> + <dc:creator><![CDATA[John Smith]]></dc:creator> + <pubDate>Tue, 30 Oct 2018 23:22:00 GMT</pubDate> + </entry> + <entry> + <title><![CDATA[Lorem ipsum 2018-10-30T23:21:00+00:00]]></title> + <description><![CDATA[Ea est do quis fugiat exercitation.]]></description> + <link>http://example.com/test/1540941660</link> + <guid isPermaLink="true">http://example.com/test/1540941660</guid> + <dc:creator><![CDATA[John Smith]]></dc:creator> + <pubDate>Tue, 30 Oct 2018 23:21:00 GMT</pubDate> + </entry> + <entry> + <title><![CDATA[Lorem ipsum 2018-10-30T23:20:00+00:00]]></title> + <description><![CDATA[Ipsum velit cillum ad laborum sit nulla exercitation consequat sint veniam culpa veniam voluptate incididunt.]]></description> + <link>http://example.com/test/1540941600</link> + <guid isPermaLink="true">http://example.com/test/1540941600</guid> + <dc:creator><![CDATA[John Smith]]></dc:creator> + <pubDate>Tue, 30 Oct 2018 23:20:00 GMT</pubDate> + </entry> + <entry> + <title><![CDATA[Lorem ipsum 2018-10-30T23:19:00+00:00]]></title> + <description><![CDATA[Ullamco pariatur aliqua consequat ea veniam id qui incididunt laborum.]]></description> + <link>http://example.com/test/1540941540</link> + <guid isPermaLink="true">http://example.com/test/1540941540</guid> + <dc:creator><![CDATA[John Smith]]></dc:creator> + <pubDate>Tue, 30 Oct 2018 23:19:00 GMT</pubDate> + </entry> + <entry> + <title><![CDATA[Lorem ipsum 2018-10-30T23:18:00+00:00]]></title> + <description><![CDATA[Velit proident aliquip aliquip anim mollit voluptate laboris voluptate et occaecat occaecat laboris ea nulla.]]></description> + <link>http://example.com/test/1540941480</link> + <guid isPermaLink="true">http://example.com/test/1540941480</guid> + <dc:creator><![CDATA[John Smith]]></dc:creator> + <pubDate>Tue, 30 Oct 2018 23:18:00 GMT</pubDate> + </entry> + <entry> + <title><![CDATA[Lorem ipsum 2018-10-30T23:17:00+00:00]]></title> + <description><![CDATA[Do in quis mollit consequat id in minim laborum sint exercitation laborum elit officia.]]></description> + <link>http://example.com/test/1540941420</link> + <guid isPermaLink="true">http://example.com/test/1540941420</guid> + <dc:creator><![CDATA[John Smith]]></dc:creator> + <pubDate>Tue, 30 Oct 2018 23:17:00 GMT</pubDate> + </entry> + <entry> + <title><![CDATA[Lorem ipsum 2018-10-30T23:16:00+00:00]]></title> + <description><![CDATA[Irure id sint ullamco Lorem magna consectetur officia adipisicing duis incididunt.]]></description> + <link>http://example.com/test/1540941360</link> + <guid isPermaLink="true">http://example.com/test/1540941360</guid> + <dc:creator><![CDATA[John Smith]]></dc:creator> + <pubDate>Tue, 30 Oct 2018 23:16:00 GMT</pubDate> + </entry> + <entry> + <title><![CDATA[Lorem ipsum 2018-10-30T23:15:00+00:00]]></title> + <description><![CDATA[Sunt anim excepteur esse nisi commodo culpa laborum exercitation ad anim ex elit.]]></description> + <link>http://example.com/test/1540941300</link> + <guid isPermaLink="true">http://example.com/test/1540941300</guid> + <dc:creator><![CDATA[John Smith]]></dc:creator> + <pubDate>Tue, 30 Oct 2018 23:15:00 GMT</pubDate> + </entry> + <entry> + <title><![CDATA[Lorem ipsum 2018-10-30T23:14:00+00:00]]></title> + <description><![CDATA[Excepteur aliquip fugiat ex labore nisi.]]></description> + <link>http://example.com/test/1540941240</link> + <guid isPermaLink="true">http://example.com/test/1540941240</guid> + <dc:creator><![CDATA[John Smith]]></dc:creator> + <pubDate>Tue, 30 Oct 2018 23:14:00 GMT</pubDate> + </entry> + <entry> + <title><![CDATA[Lorem ipsum 2018-10-30T23:13:00+00:00]]></title> + <description><![CDATA[Id proident adipisicing proident pariatur aute pariatur pariatur dolor dolor in voluptate dolor.]]></description> + <link>http://example.com/test/1540941180</link> + <guid isPermaLink="true">http://example.com/test/1540941180</guid> + <dc:creator><![CDATA[John Smith]]></dc:creator> + <pubDate>Tue, 30 Oct 2018 23:13:00 GMT</pubDate> + </entry> +</feed>
\ No newline at end of file diff --git a/vendor/github.com/gorilla/feeds/test.rss b/vendor/github.com/gorilla/feeds/test.rss new file mode 100644 index 0000000000..8d912aba52 --- /dev/null +++ b/vendor/github.com/gorilla/feeds/test.rss @@ -0,0 +1,96 @@ +<?xml version="1.0" encoding="UTF-8"?> +<rss xmlns:dc="http://purl.org/dc/elements/1.1/" + xmlns:content="http://purl.org/rss/1.0/modules/content/" + xmlns:atom="http://www.w3.org/2005/Atom" version="2.0"> + <channel> + <title><![CDATA[Lorem ipsum feed for an interval of 1 minutes]]></title> + <description><![CDATA[This is a constantly updating lorem ipsum feed]]></description> + <link>http://example.com/</link> + <generator>RSS for Node</generator> + <lastBuildDate>Tue, 30 Oct 2018 23:22:37 GMT</lastBuildDate> + <author><![CDATA[John Smith]]></author> + <pubDate>Tue, 30 Oct 2018 23:22:00 GMT</pubDate> + <copyright><![CDATA[Michael Bertolacci, licensed under a Creative Commons Attribution 3.0 Unported License.]]></copyright> + <ttl>60</ttl> + <item> + <title><![CDATA[Lorem ipsum 2018-10-30T23:22:00+00:00]]></title> + <description><![CDATA[Exercitation ut Lorem sint proident.]]></description> + <link>http://example.com/test/1540941720</link> + <guid isPermaLink="true">http://example.com/test/1540941720</guid> + <dc:creator><![CDATA[John Smith]]></dc:creator> + <pubDate>Tue, 30 Oct 2018 23:22:00 GMT</pubDate> + </item> + <item> + <title><![CDATA[Lorem ipsum 2018-10-30T23:21:00+00:00]]></title> + <description><![CDATA[Ea est do quis fugiat exercitation.]]></description> + <link>http://example.com/test/1540941660</link> + <guid isPermaLink="true">http://example.com/test/1540941660</guid> + <dc:creator><![CDATA[John Smith]]></dc:creator> + <pubDate>Tue, 30 Oct 2018 23:21:00 GMT</pubDate> + </item> + <item> + <title><![CDATA[Lorem ipsum 2018-10-30T23:20:00+00:00]]></title> + <description><![CDATA[Ipsum velit cillum ad laborum sit nulla exercitation consequat sint veniam culpa veniam voluptate incididunt.]]></description> + <link>http://example.com/test/1540941600</link> + <guid isPermaLink="true">http://example.com/test/1540941600</guid> + <dc:creator><![CDATA[John Smith]]></dc:creator> + <pubDate>Tue, 30 Oct 2018 23:20:00 GMT</pubDate> + </item> + <item> + <title><![CDATA[Lorem ipsum 2018-10-30T23:19:00+00:00]]></title> + <description><![CDATA[Ullamco pariatur aliqua consequat ea veniam id qui incididunt laborum.]]></description> + <link>http://example.com/test/1540941540</link> + <guid isPermaLink="true">http://example.com/test/1540941540</guid> + <dc:creator><![CDATA[John Smith]]></dc:creator> + <pubDate>Tue, 30 Oct 2018 23:19:00 GMT</pubDate> + </item> + <item> + <title><![CDATA[Lorem ipsum 2018-10-30T23:18:00+00:00]]></title> + <description><![CDATA[Velit proident aliquip aliquip anim mollit voluptate laboris voluptate et occaecat occaecat laboris ea nulla.]]></description> + <link>http://example.com/test/1540941480</link> + <guid isPermaLink="true">http://example.com/test/1540941480</guid> + <dc:creator><![CDATA[John Smith]]></dc:creator> + <pubDate>Tue, 30 Oct 2018 23:18:00 GMT</pubDate> + </item> + <item> + <title><![CDATA[Lorem ipsum 2018-10-30T23:17:00+00:00]]></title> + <description><![CDATA[Do in quis mollit consequat id in minim laborum sint exercitation laborum elit officia.]]></description> + <link>http://example.com/test/1540941420</link> + <guid isPermaLink="true">http://example.com/test/1540941420</guid> + <dc:creator><![CDATA[John Smith]]></dc:creator> + <pubDate>Tue, 30 Oct 2018 23:17:00 GMT</pubDate> + </item> + <item> + <title><![CDATA[Lorem ipsum 2018-10-30T23:16:00+00:00]]></title> + <description><![CDATA[Irure id sint ullamco Lorem magna consectetur officia adipisicing duis incididunt.]]></description> + <link>http://example.com/test/1540941360</link> + <guid isPermaLink="true">http://example.com/test/1540941360</guid> + <dc:creator><![CDATA[John Smith]]></dc:creator> + <pubDate>Tue, 30 Oct 2018 23:16:00 GMT</pubDate> + </item> + <item> + <title><![CDATA[Lorem ipsum 2018-10-30T23:15:00+00:00]]></title> + <description><![CDATA[Sunt anim excepteur esse nisi commodo culpa laborum exercitation ad anim ex elit.]]></description> + <link>http://example.com/test/1540941300</link> + <guid isPermaLink="true">http://example.com/test/1540941300</guid> + <dc:creator><![CDATA[John Smith]]></dc:creator> + <pubDate>Tue, 30 Oct 2018 23:15:00 GMT</pubDate> + </item> + <item> + <title><![CDATA[Lorem ipsum 2018-10-30T23:14:00+00:00]]></title> + <description><![CDATA[Excepteur aliquip fugiat ex labore nisi.]]></description> + <link>http://example.com/test/1540941240</link> + <guid isPermaLink="true">http://example.com/test/1540941240</guid> + <dc:creator><![CDATA[John Smith]]></dc:creator> + <pubDate>Tue, 30 Oct 2018 23:14:00 GMT</pubDate> + </item> + <item> + <title><![CDATA[Lorem ipsum 2018-10-30T23:13:00+00:00]]></title> + <description><![CDATA[Id proident adipisicing proident pariatur aute pariatur pariatur dolor dolor in voluptate dolor.]]></description> + <link>http://example.com/test/1540941180</link> + <guid isPermaLink="true">http://example.com/test/1540941180</guid> + <dc:creator><![CDATA[John Smith]]></dc:creator> + <pubDate>Tue, 30 Oct 2018 23:13:00 GMT</pubDate> + </item> + </channel> +</rss>
\ No newline at end of file diff --git a/vendor/github.com/gorilla/feeds/to-implement.md b/vendor/github.com/gorilla/feeds/to-implement.md new file mode 100644 index 0000000000..45fd1e75e2 --- /dev/null +++ b/vendor/github.com/gorilla/feeds/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) + +``` +<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> +```
\ No newline at end of file diff --git a/vendor/github.com/gorilla/feeds/uuid.go b/vendor/github.com/gorilla/feeds/uuid.go new file mode 100644 index 0000000000..51bbafe13f --- /dev/null +++ b/vendor/github.com/gorilla/feeds/uuid.go @@ -0,0 +1,27 @@ +package feeds + +// relevant bits from https://github.com/abneptis/GoUUID/blob/master/uuid.go + +import ( + "crypto/rand" + "fmt" +) + +type UUID [16]byte + +// create a new uuid v4 +func NewUUID() *UUID { + u := &UUID{} + _, err := rand.Read(u[:16]) + if err != nil { + panic(err) + } + + u[8] = (u[8] | 0x80) & 0xBf + u[6] = (u[6] | 0x40) & 0x4f + return u +} + +func (u *UUID) String() string { + return fmt.Sprintf("%x-%x-%x-%x-%x", u[:4], u[4:6], u[6:8], u[8:10], u[10:]) +} diff --git a/vendor/modules.txt b/vendor/modules.txt index 72704a7f4f..82afbb6730 100644 --- a/vendor/modules.txt +++ b/vendor/modules.txt @@ -469,6 +469,9 @@ github.com/google/uuid github.com/gorilla/context # github.com/gorilla/css v1.0.0 github.com/gorilla/css/scanner +# github.com/gorilla/feeds v1.1.1 +## explicit +github.com/gorilla/feeds # github.com/gorilla/handlers v1.5.1 github.com/gorilla/handlers # github.com/gorilla/mux v1.8.0 |