-
Notifications
You must be signed in to change notification settings - Fork 1
/
jsonfeed.go
154 lines (140 loc) · 3.66 KB
/
jsonfeed.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
package jsonfeed
import (
"encoding/json"
"fmt"
"io"
"net/http"
"path"
"strconv"
"time"
"reflect"
)
func (jf *JSONFeed) Read(r io.Reader) error {
dec := json.NewDecoder(r)
dec.Decode(&jf)
missing, err := jf.GetMissing()
if err != nil {
return err
}
if len(missing) != 0 {
return fmt.Errorf("Feed missing field(s): %v", missing)
}
return nil
}
func (jf *JSONFeed) Write(w io.Writer) error {
missing, err := jf.GetMissing()
if err != nil {
return err
}
if len(missing) > 0 {
return fmt.Errorf("Feed missing field(s): %v", missing)
}
enc := json.NewEncoder(w)
enc.SetEscapeHTML(false)
return enc.Encode(jf)
}
//getMissingRecursive Checks if struct has all required fields recursively
func getMissingRecursive(s interface{}) (missing []string, err error) {
st := reflect.ValueOf(s)
for i := 0; i < st.NumField(); i++ {
field := st.Field(i)
if feed, ok := st.Type().Field(i).Tag.Lookup("feed"); ok {
if field.Type().Kind() == reflect.Struct {
m, err := getMissingRecursive(field)
if err != nil {
return missing, err
}
missing = append(missing, m...)
} else {
if feed == "required" && field == reflect.Zero(field.Type()).Interface() {
missing = append(missing, st.Type().Field(i).Name)
}
}
}
}
return
}
//SetVersion set the version JSON Feed to use
func (jf *JSONFeed) SetVersion(v int) {
jf.Version = "https://jsonfeed.org/version/" + strconv.Itoa(v)
}
//GetMissing checks if the feed has all the required fields
func (jf JSONFeed) GetMissing() (missing []string, err error) {
return getMissingRecursive(jf)
}
func (jf *JSONFeed) ServeHTTP(rw http.ResponseWriter, r *http.Request) {
rw.Header().Add("Content-Type", "application/json; charset=utf-8")
jf.Write(rw)
}
//OpenFeed read from url into a JSONFeed
func OpenFeed(url string) (feed *JSONFeed, err error) {
p, err := http.Get(url)
if err != nil {
return nil, err
}
feed = &JSONFeed{}
err = feed.Read(p.Body)
if err != nil {
return nil, err
}
p.Body.Close()
return feed, nil
}
//CreateJSONFeed creates a new json feed (v1)
func CreateJSONFeed(title string, description string) (feed *JSONFeed) {
feed = &JSONFeed{
Title: title,
Description: description,
}
feed.SetVersion(1)
return
}
//PublishText publishes a new plain text item to a JSON Feed, the publish date is time.Now()
func (jf *JSONFeed) PublishText(id string, title string, text string, attachments ...*Attachment) (i *Item) {
jf.Items = append([]*Item{&Item{
ID: id,
Title: title,
ContentText: text,
Attachments: attachments,
DatePublished: time.Now(),
}}, jf.Items...)
return jf.Items[0]
}
//PublishHTML publishes a new html text item to a JSON Feed, the publish date is time.Now()
func (jf *JSONFeed) PublishHTML(id string, title string, textHTML string, attachments ...*Attachment) (i *Item) {
jf.Items = append([]*Item{&Item{
ID: id,
Title: title,
ContentHTML: textHTML,
Attachments: attachments,
DatePublished: time.Now(),
}}, jf.Items...)
return jf.Items[0]
}
//NewImage creates a new image attachment
func NewImage(title string, url string) (at *Attachment) {
imgType := path.Ext(url)
return &Attachment{
Title: title,
URL: url,
MimeType: "image/" + imgType[1:],
}
}
//NewVideo creates a new video attachment
func NewVideo(title string, url string) (at *Attachment) {
vidType := path.Ext(url)
return &Attachment{
Title: title,
URL: url,
MimeType: "video/" + vidType[1:],
}
}
//NewAudio creates a new adio attachment
func NewAudio(title string, url string) (at *Attachment) {
audType := path.Ext(url)
return &Attachment{
Title: title,
URL: url,
MimeType: "audio/" + audType[1:],
}
}