forked from go-vk-api/vk
-
Notifications
You must be signed in to change notification settings - Fork 0
/
client.go
103 lines (82 loc) · 2.12 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
package vk
import (
"encoding/json"
"net/http"
"reflect"
"github.com/go-vk-api/vk/httputil"
"github.com/pkg/errors"
)
const (
DefaultBaseURL = "https://api.vk.com/method"
DefaultLang = "en"
DefaultVersion = "5.103"
)
// Client manages communication with VK API.
type Client struct {
BaseURL string
Lang string
Version string
Token string
HTTPClient httputil.RequestDoer
}
// CallMethod invokes the named method and stores the result in the value pointed to by response.
func (c *Client) CallMethod(method string, params RequestParams, response interface{}) error {
queryParams, err := params.URLValues()
if err != nil {
return err
}
setIfEmpty := func(param, value string) {
if queryParams.Get(param) == "" {
queryParams.Set(param, value)
}
}
setIfEmpty("v", c.Version)
setIfEmpty("lang", c.Lang)
if c.Token != "" {
setIfEmpty("access_token", c.Token)
}
rawBody, err := httputil.Post(c.HTTPClient, c.BaseURL+"/"+method, queryParams)
if err != nil {
return err
}
var body struct {
Response interface{} `json:"response"`
Error *MethodError `json:"error"`
}
if response != nil {
valueOfResponse := reflect.ValueOf(response)
if valueOfResponse.Kind() != reflect.Ptr || valueOfResponse.IsNil() {
return errors.New("response must be a valid pointer")
}
body.Response = response
}
if err = json.Unmarshal(rawBody, &body); err != nil {
return err
}
if body.Error != nil {
return body.Error
}
return nil
}
// NewClient initializes a new VK API client with default values.
func NewClient() (*Client, error) {
return NewClientWithOptions()
}
// NewClientWithOptions initializes a new VK API client with default values. It takes functors
// to modify values when creating it, like `NewClientWithOptions(WithToken(…))`.
func NewClientWithOptions(options ...Option) (*Client, error) {
client := &Client{
BaseURL: DefaultBaseURL,
Lang: DefaultLang,
Version: DefaultVersion,
}
for _, option := range options {
if err := option(client); err != nil {
return nil, err
}
}
if client.HTTPClient == nil {
client.HTTPClient = http.DefaultClient
}
return client, nil
}