-
Notifications
You must be signed in to change notification settings - Fork 65
/
builder_url.go
120 lines (106 loc) · 3.36 KB
/
builder_url.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
package stm
import (
"errors"
"fmt"
"time"
"github.com/beevik/etree"
"github.com/fatih/structs"
)
// URLModel is specific sample model for valuedate.
// http://www.sitemaps.org/protocol.html
// https://support.google.com/webmasters/answer/178636
type URLModel struct {
Priority float64 `valid:"float,length(0.0|1.0)"`
Changefreq string `valid:"alpha(always|hourly|daily|weekly|monthly|yearly|never)"`
Lastmod time.Time `valid:"-"`
Expires time.Time `valid:"-"`
Host string `valid:"ipv4"`
Loc string `valid:"url"`
Image string `valid:"url"`
Video string `valid:"url"`
Tag string `valid:""`
Geo string `valid:""`
News string `valid:"-"`
Mobile bool `valid:"-"`
Alternate string `valid:"-"`
Alternates map[string]interface{} `valid:"-"`
Pagemap map[string]interface{} `valid:"-"`
}
// fieldnames []string{"priority" "changefreq" "lastmod" "expires" "host" "images"
// "video" "geo" "news" "videos" "mobile" "alternate" "alternates" "pagemap"}
var fieldnames = ToLowerString(structs.Names(&URLModel{}))
// NewSitemapURL returns the created the SitemapURL's pointer
// and it validates URL types error.
func NewSitemapURL(opts *Options, url URL) (SitemapURL, error) {
smu := &sitemapURL{opts: opts, data: url}
err := smu.validate()
return smu, err
}
// sitemapURL provides xml validator and xml builder.
type sitemapURL struct {
opts *Options
data URL
}
// validate is checking correct keys and checks the existence.
// TODO: Will create value's validator
func (su *sitemapURL) validate() error {
var key string
var invalid bool
for key = range su.data {
invalid = true
for _, name := range fieldnames {
if key == name {
invalid = false
break
}
}
if invalid {
break
}
}
if invalid {
msg := fmt.Sprintf("Unknown map's key `%s` in URL type", key)
return errors.New(msg)
}
if _, ok := su.data["loc"]; !ok {
msg := fmt.Sprintf("URL type must have `loc` map's key")
return errors.New(msg)
}
if _, ok := su.data["host"]; !ok {
msg := fmt.Sprintf("URL type must have `host` map's key")
return errors.New(msg)
}
return nil
}
// XML is building xml.
func (su *sitemapURL) XML() []byte {
doc := etree.NewDocument()
url := doc.CreateElement("url")
SetBuilderElementValue(url, su.data.URLJoinBy("loc", "host", "loc"), "loc")
if _, ok := SetBuilderElementValue(url, su.data, "lastmod"); !ok {
lastmod := url.CreateElement("lastmod")
lastmod.SetText(time.Now().Format(time.RFC3339))
}
if _, ok := SetBuilderElementValue(url, su.data, "changefreq"); !ok {
changefreq := url.CreateElement("changefreq")
changefreq.SetText("weekly")
}
if _, ok := SetBuilderElementValue(url, su.data, "priority"); !ok {
priority := url.CreateElement("priority")
priority.SetText("0.5")
}
SetBuilderElementValue(url, su.data, "expires")
SetBuilderElementValue(url, su.data, "mobile")
SetBuilderElementValue(url, su.data, "news")
SetBuilderElementValue(url, su.data, "video")
SetBuilderElementValue(url, su.data, "image")
SetBuilderElementValue(url, su.data, "geo")
if su.opts.pretty {
doc.Indent(2)
}
buf := poolBuffer.Get()
doc.WriteTo(buf)
bytes := buf.Bytes()
poolBuffer.Put(buf)
return bytes
}