-
Notifications
You must be signed in to change notification settings - Fork 3
/
patreon.go
181 lines (149 loc) · 5.65 KB
/
patreon.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
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
package patreon
import (
"encoding/json"
"fmt"
"net/http"
"net/url"
"strconv"
)
const (
// AuthorizationURL specifies Patreon's OAuth2 authorization endpoint (see https://tools.ietf.org/html/rfc6749#section-3.1).
// See Example_refreshToken for examples.
AuthorizationURL = "https://www.patreon.com/oauth2/authorize"
// AccessTokenURL specifies Patreon's OAuth2 token endpoint (see https://tools.ietf.org/html/rfc6749#section-3.2).
// See Example_refreshToken for examples.
AccessTokenURL = "https://api.patreon.com/oauth2/token"
// baseURL is the base url for api V2 (see https://docs.patreon.com/#apiv2-resource-endpoints).
baseURL = "https://patreon.com"
)
// AllScopes is every scope possible for Oauth (see https://docs.patreon.com/#scopes).
var AllScopes = []string{
"identity", "identity[email]", "identity.memberships", "campaigns",
"w:campaigns.webhook", "campaigns.members", "campaigns.members[email]",
"campaigns.members.address", "campaigns.posts",
}
// Client manages communication with Patreon API.
type Client struct {
httpClient *http.Client
baseURL string
}
// NewClient returns a new Patreon API client. If a nil httpClient is
// provided, http.DefaultClient will be used. To use API methods which require
// authentication, provide an http.Client that will perform the authentication
// for you (such as that provided by the golang.org/x/oauth2 library).
func NewClient(httpClient *http.Client) *Client {
if httpClient == nil {
httpClient = http.DefaultClient
}
return &Client{httpClient: httpClient, baseURL: baseURL}
}
// Client returns the HTTP client configured for this client.
func (c *Client) Client() *http.Client {
return c.httpClient
}
// FetchIdentity fetches a patron's profile info.
// This is the endpoint for accessing information about the current User with reference to the oauth token.
// It is most typically used in the OAuth "Log in with Patreon" flow to create or update the user's account on your site.
func (c *Client) FetchIdentity(opts ...requestOption) (*UserResponse, error) {
resp := &UserResponse{}
err := c.get("/api/oauth2/v2/identity", resp, opts...)
return resp, err
}
// FetchCampaign is the single resource endpoint returns information about a single Campaign, fetched by campaign ID.
// Requires the campaigns scope.
func (c *Client) FetchCampaign(campaignID string, opts ...requestOption) (*CampaignResponse, error) {
resp := &CampaignResponse{}
err := c.get(fmt.Sprintf("/api/oauth2/v2/campaigns/%s", campaignID), resp, opts...)
return resp, err
}
// FetchCampaigns Returns a list of Campaigns owned by the authorized user.
// Requires the campaigns scope.
func (c *Client) FetchCampaigns(opts ...requestOption) (*CampaignsResponse, error) {
resp := &CampaignsResponse{}
err := c.get("/api/oauth2/v2/campaigns", resp, opts...)
return resp, err
}
// FetchCampaignMembers gets the Members for a given Campaign.
// Requires the campaigns.members scope.
func (c *Client) FetchCampaignMembers(campaignID string, opts ...requestOption) (*MembersResponse, error) {
resp := &MembersResponse{}
err := c.get(fmt.Sprintf("/api/oauth2/v2/campaigns/%s/members", campaignID), resp, opts...)
return resp, err
}
// FetchCampaignMember gets a particular member by id.
// Requires the campaigns.members scope.
func (c *Client) FetchCampaignMember(memberID string, opts ...requestOption) (*MemberResponse, error) {
resp := &MemberResponse{}
err := c.get(fmt.Sprintf("/api/oauth2/v2/members/%s", memberID), resp, opts...)
return resp, err
}
// FetchCampaignPosts gets a list of all the Posts on a given Campaign by campaign ID.
// Requires the campaigns.posts scope.
func (c *Client) FetchCampaignPosts(campaignID string, opts ...requestOption) (*PostsResponse, error) {
resp := &PostsResponse{}
err := c.get(fmt.Sprintf("/api/oauth2/v2/campaigns/%s/posts", campaignID), resp, opts...)
return resp, err
}
// FetchCampaignPost gets a particular Post by ID.
// Requires the campaigns.posts scope.
func (c *Client) FetchCampaignPost(postID string, opts ...requestOption) (*PostResponse, error) {
resp := &PostResponse{}
err := c.get(fmt.Sprintf("/api/oauth2/v2/posts/%s", postID), resp, opts...)
return resp, err
}
// FetchCampaignWebhooks gets the Webhooks for the current user's Campaign created by the API client.
// You will only be able to see webhooks created by your client.
// Requires the w:campaigns.webhook scope.
func (c *Client) FetchCampaignWebhooks(opts ...requestOption) (*WebhookResponse, error) {
resp := &WebhookResponse{}
err := c.get("/api/oauth2/v2/webhoooks", resp, opts...)
return resp, err
}
func (c *Client) buildURL(path string, opts ...requestOption) (string, error) {
cfg := getOptions(opts...)
u, err := url.ParseRequestURI(c.baseURL + path)
if err != nil {
return "", err
}
q := url.Values{}
if cfg.include != "" {
q.Set("include", cfg.include)
}
if len(cfg.fields) > 0 {
for resource, fields := range cfg.fields {
key := fmt.Sprintf("fields[%s]", resource)
q.Set(key, fields)
}
}
if cfg.size != 0 {
q.Set("page[count]", strconv.Itoa(cfg.size))
}
if cfg.cursor != "" {
q.Set("page[cursor]", cfg.cursor)
}
u.RawQuery = q.Encode()
return u.String(), nil
}
func (c *Client) get(path string, v interface{}, opts ...requestOption) error {
addr, err := c.buildURL(path, opts...)
if err != nil {
return err
}
resp, err := c.httpClient.Get(addr)
if err != nil {
return err
}
// body, err := ioutil.ReadAll(resp.Body)
// if err != nil {
// return err
// }
// fmt.Println(string(body))
if resp.StatusCode != http.StatusOK {
errs := ErrorResponse{}
if err := json.NewDecoder(resp.Body).Decode(&errs); err != nil {
return err
}
return errs
}
return json.NewDecoder(resp.Body).Decode(v)
}