summaryrefslogtreecommitdiff
path: root/vendor/github.com/gorilla/feeds/json.go
diff options
context:
space:
mode:
authorLibravatar tobi <31960611+tsmethurst@users.noreply.github.com>2022-10-08 14:00:39 +0200
committerLibravatar GitHub <noreply@github.com>2022-10-08 14:00:39 +0200
commit80663061d8f361ae4bcea1307a10a40c41174ebe (patch)
tree999f9e8decfb3e6e211e8462415103819eddd1c2 /vendor/github.com/gorilla/feeds/json.go
parent[chore] Standardize database queries, use `bun.Ident()` properly (#886) (diff)
downloadgotosocial-80663061d8f361ae4bcea1307a10a40c41174ebe.tar.xz
[feature] Add opt-in RSS feed for account's latest Public posts (#897)
* start adding rss functionality * add gorilla/feeds dependency * first bash at building rss feed still needs work, this is an interim commit * tidy up a bit * add publicOnly option to GetAccountLastPosted * implement rss endpoint * fix test * add initial user docs for rss * update rss logo * docs update * add rssFeed to frontend * feed -> feed.rss * enableRSS * increase rss logo size a lil bit * add rss toggle * move emojify to text package * fiddle with rss feed formatting * add Text field to test statuses * move status to rss item to typeconverter * update bun schema for enablerss * simplify 304 checking * assume account not rss * update tests * update swagger docs * allow more characters in title, trim nicer * update last posted to be more consistent
Diffstat (limited to 'vendor/github.com/gorilla/feeds/json.go')
-rw-r--r--vendor/github.com/gorilla/feeds/json.go183
1 files changed, 183 insertions, 0 deletions
diff --git a/vendor/github.com/gorilla/feeds/json.go b/vendor/github.com/gorilla/feeds/json.go
new file mode 100644
index 000000000..75a82fd62
--- /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
+}