-
Notifications
You must be signed in to change notification settings - Fork 3
/
client.go
168 lines (132 loc) · 3.43 KB
/
client.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
package instabot
import (
"context"
"io"
"net/http"
"net/url"
"path"
)
// Client defines instabot.
type Client struct {
pageAccessToken string
endpointBase *url.URL
httpClient *http.Client
}
// ClientOption defines optional argument for new client construction.
type ClientOption func(*Client) error
// WithHTTPClient sets client http client.
func WithHTTPClient(c *http.Client) ClientOption {
return func(client *Client) error {
client.httpClient = c
return nil
}
}
// WithEndpointBase sets client base endpoint.
func WithEndpointBase(endpointBase string) ClientOption {
return func(client *Client) error {
url, err := url.ParseRequestURI(endpointBase)
if err != nil {
return err
}
client.endpointBase = url
return nil
}
}
// New returns a new bot client instance.
func New(pageAccessToken string, options ...ClientOption) (*Client, error) {
if pageAccessToken == "" {
return nil, ErrMissingPageAccessToken
}
client := &Client{
pageAccessToken: pageAccessToken,
}
for _, option := range options {
err := option(client)
if err != nil {
return nil, err
}
}
if client.endpointBase == nil {
u, err := url.ParseRequestURI(APIEndpointBase)
if err != nil {
return nil, err
}
client.endpointBase = u
}
if client.httpClient == nil {
client.httpClient = http.DefaultClient
}
return client, nil
}
func (client *Client) url(base *url.URL, endpoint string) string {
u := *base
u.Path = path.Join(u.Path, endpoint)
// pass page_access_token to query string
query := u.Query()
query.Add("access_token", client.pageAccessToken)
u.RawQuery = query.Encode()
return u.String()
}
// abstraction for later usage like to set some global property of request, ex- header etc.
func (client *Client) do(req *http.Request) (*http.Response, error) {
return client.httpClient.Do(req)
}
func (client *Client) get(ctx context.Context, endpoint string, query url.Values) (*http.Response, error) {
req, err := http.NewRequestWithContext(
ctx,
http.MethodGet,
client.url(client.endpointBase, endpoint),
nil,
)
if err != nil {
return nil, err
}
if query != nil {
query.Set("access_token", req.URL.Query().Get("access_token"))
req.URL.RawQuery = query.Encode()
}
return client.do(req)
}
func (client *Client) post(ctx context.Context, endpoint string, body io.Reader) (*http.Response, error) {
req, err := http.NewRequestWithContext(
ctx,
http.MethodPost,
client.url(client.endpointBase, endpoint),
body,
)
if err != nil {
return nil, err
}
req.Header.Set("Content-Type", "application/json; charset=UTF-8")
return client.do(req)
}
func (client *Client) put(ctx context.Context, endpoint string, body io.Reader) (*http.Response, error) {
req, err := http.NewRequestWithContext(
ctx,
http.MethodPut,
client.url(client.endpointBase, endpoint),
body,
)
if err != nil {
return nil, err
}
req.Header.Set("Content-Type", "application/json; charset=UTF-8")
return client.do(req)
}
func (client *Client) delete(ctx context.Context, endpoint string, body io.Reader, query url.Values) (*http.Response, error) {
req, err := http.NewRequestWithContext(
ctx,
http.MethodDelete,
client.url(client.endpointBase, endpoint),
body,
)
if err != nil {
return nil, err
}
if query != nil {
query.Set("access_token", req.URL.Query().Get("access_token"))
req.URL.RawQuery = query.Encode()
}
req.Header.Set("Content-Type", "application/json; charset=UTF-8")
return client.do(req)
}