-
Notifications
You must be signed in to change notification settings - Fork 2
/
Copy pathtags.go
137 lines (112 loc) · 3.55 KB
/
tags.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
package pinboard
import (
"encoding/xml"
"fmt"
"net/url"
"strings"
)
type tags struct {
XMLName xml.Name `xml:"tags"`
Tags []Tag `xml:"tag"`
}
// A Tag in Pinboard is a simple string applied to posts for organizational purposes.
// Users can create Private Tags (tags only visible to the posting user) by prepending
// the tag with a period (.). Tags returned from the Tags endpoints contain a count of
// how often they're used.
type Tag struct {
XMLName xml.Name `xml:"tag"`
Count int `xml:"count,attr"`
Tag string `xml:"tag,attr"`
}
// TagsGet returns a list of []Tag corresponding to the tags in the user's account.
func (p *Pinboard) TagsGet() ([]Tag, error) {
u, err := url.Parse(apiBase + "tags/get")
if err != nil {
return []Tag{}, fmt.Errorf("Failed to parse Tags API URL: %v", err)
}
resp, err := p.get(u)
if err != nil {
return []Tag{}, err
}
tmp, err := parseResponse(resp, &tags{})
if err != nil {
return []Tag{}, fmt.Errorf("Failed to parse Tags response %v", err)
}
t := tmp.(*tags)
return t.Tags, err
}
// TagsDelete deletes the given tag from a user's Pinboard account. There is no
// central store for tags, they are simply removed from every post in a user's
// account. This API endpoint has no meaningful response, so an error is returned
// only if the HTTP request fails.
func (p *Pinboard) TagsDelete(tag string) error {
u, err := url.Parse(apiBase + "tags/delete")
if err != nil {
return fmt.Errorf("Failed to parse TagsDelete API URL: %v", err)
}
q := u.Query()
if len(tag) < 1 || len(tag) > 255 {
return fmt.Errorf("Tags must be between 1 and 255 characters in length")
}
q.Set("tag", tag)
u.RawQuery = q.Encode()
_, err = p.get(u)
if err != nil {
return fmt.Errorf("Error from TagsDelete request %v", err)
}
return nil
}
// TagsRename renames a tag by changing that tag on every post in the user's account.
func (p *Pinboard) TagsRename(old, new string) error {
u, err := url.Parse(apiBase + "tags/rename")
if err != nil {
return fmt.Errorf("Failed to parse TagsRename API URL: %v", err)
}
q := u.Query()
if len(old) < 1 || len(new) < 1 {
return fmt.Errorf("Both old and new tag must not be empty string for TagsRename")
}
q.Set("old", old)
q.Set("new", new)
u.RawQuery = q.Encode()
_, err = p.get(u)
if err != nil {
return fmt.Errorf("Error from TagsRename request %v", err)
}
return nil
}
// Pinboard returns two types of tag suggestions, popular tags are tags from the community.
// Recommended tags are based on the user's existing tags
type TagSuggestions struct {
XMLName xml.Name `xml:"suggested"`
Popular []string `xml:"popular"`
Recommended []string `xml:"recommended"`
}
// TagsSuggestions returns tag suggestions for the given URL. Note: Currently only recommended
// tags are actually returned from the Pinboard API
func (p *Pinboard) TagsSuggestions(postUrl string) (TagSuggestions, error) {
u, _ := url.Parse(apiBase + "posts/suggest")
q := u.Query()
pu, _ := url.Parse(postUrl)
validScheme := false
for _, v := range validSchemes {
if strings.ToLower(pu.Scheme) == v {
validScheme = true
}
}
if !validScheme {
return TagSuggestions{}, fmt.Errorf("Invalid scheme for Pinboard URL. Scheme must be one of %v", validSchemes)
}
q.Set("url", postUrl)
u.RawQuery = q.Encode()
resp, err := p.get(u)
if err != nil {
return TagSuggestions{}, err
}
tmp, err := parseResponse(resp, &TagSuggestions{})
if err != nil {
return TagSuggestions{}, fmt.Errorf("Failed to parse TagsSuggestions response %v", err)
}
t := tmp.(*TagSuggestions)
return *t, err
}