@@ -4,14 +4,11 @@ import (
4
4
"bytes"
5
5
"context"
6
6
"encoding/json"
7
- "errors"
8
7
"fmt"
8
+ "github.com/tidwall/gjson"
9
9
"io/ioutil"
10
10
"net/http"
11
- "strings"
12
11
"time"
13
-
14
- "github.com/valyala/fastjson"
15
12
)
16
13
17
14
const (
@@ -27,7 +24,7 @@ const (
27
24
xErrorHeader = "X-Error"
28
25
xErrorCodeHeader = "X-Error-Code"
29
26
30
- defaultTimeout = time .Second * 5
27
+ defaultTimeout = time .Second * 10
31
28
)
32
29
33
30
// Client is a getpocket API client
@@ -39,7 +36,7 @@ type Client struct {
39
36
// NewClient creates a new client with your application key (to generate a key, create your application here: https://getpocket.com/developer/apps)
40
37
func NewClient (consumerKey string ) (* Client , error ) {
41
38
if consumerKey == "" {
42
- return nil , errors . New ("empty consumer key" )
39
+ return nil , fmt . Errorf ("empty consumer key" )
43
40
}
44
41
45
42
return & Client {
@@ -79,56 +76,63 @@ func (c *Client) Retrieving(ctx context.Context, input RetrievingInput) ([]Item,
79
76
return nil , err
80
77
}
81
78
82
- values , err := c .doHTTP (ctx , endpointRetrieving , req )
79
+ result , err := c .doHTTP (ctx , endpointRetrieving , req )
83
80
if err != nil {
84
81
return nil , err
85
82
}
86
83
87
- if values .GetObject ("list" ) == nil {
88
- return nil , nil
89
- }
84
+ return c .getItems (result ), nil
85
+ }
90
86
91
- return c .parseItems (values ), nil
87
+ func (c * Client ) getItems (result gjson.Result ) []Item {
88
+ var items []Item
89
+ for itemId := range result .Get ("list" ).Map () {
90
+ item := newItem (itemId )
91
+ item .fillFields (result )
92
+ items = append (items , item )
93
+ }
94
+ return items
92
95
}
93
96
94
97
// Authorize returns the Authorization structure with the access token, user name and state obtained from the authorization request
95
98
func (c * Client ) Authorize (ctx context.Context , requestToken string ) (Authorization , error ) {
96
99
if requestToken == "" {
97
- return Authorization {}, errors . New ("empty request token" )
100
+ return Authorization {}, fmt . Errorf ("empty request token" )
98
101
}
99
102
100
103
body := requestAuthorization {
101
104
ConsumerKey : c .consumerKey ,
102
105
Code : requestToken ,
103
106
}
104
107
105
- values , err := c .doHTTP (ctx , endpointRequestAuthorize , body )
108
+ result , err := c .doHTTP (ctx , endpointRequestAuthorize , body )
106
109
if err != nil {
107
110
return Authorization {}, err
108
111
}
109
112
110
- accessToken := values .GetStringBytes ("access_token" )
111
- username := values .GetStringBytes ("username" )
112
- state := values .GetStringBytes ("state" )
113
- if string (accessToken ) == "" {
114
- return Authorization {}, errors .New ("empty access token in API response" )
113
+ accessToken := result .Get ("access_token" ).String ()
114
+ username := result .Get ("username" ).String ()
115
+ state := result .Get ("state" ).String ()
116
+
117
+ if accessToken == "" {
118
+ return Authorization {}, fmt .Errorf ("empty access token in API response" )
115
119
}
116
120
117
121
return Authorization {
118
- AccessToken : string ( accessToken ) ,
119
- Username : string ( username ) ,
120
- State : string ( state ) ,
122
+ AccessToken : accessToken ,
123
+ Username : username ,
124
+ State : state ,
121
125
}, nil
122
126
}
123
127
124
128
// GetAuthorizationURL returns the url string that is used to grant the user access rights to his Pocket account in your application
125
129
func (c * Client ) GetAuthorizationURL (requestToken , redirectURL string ) (string , error ) {
126
130
if requestToken == "" {
127
- return "" , errors . New ("empty request token" )
131
+ return "" , fmt . Errorf ("empty request token" )
128
132
}
129
133
130
134
if redirectURL == "" {
131
- return "" , errors . New ("empty redirection URL" )
135
+ return "" , fmt . Errorf ("empty redirection URL" )
132
136
}
133
137
134
138
return fmt .Sprintf (authorizeUrl , requestToken , redirectURL ), nil
@@ -139,7 +143,7 @@ func (c *Client) GetAuthorizationURL(requestToken, redirectURL string) (string,
139
143
// State - metadata string that will be returned at each subsequent authentication response (if you don't need it, specify an empty string).
140
144
func (c * Client ) GetRequestToken (ctx context.Context , redirectURL string , state string ) (string , error ) {
141
145
if redirectURL == "" {
142
- return "" , errors . New ("empty redirect URL" )
146
+ return "" , fmt . Errorf ("empty redirect URL" )
143
147
}
144
148
145
149
body := requestToken {
@@ -148,84 +152,52 @@ func (c *Client) GetRequestToken(ctx context.Context, redirectURL string, state
148
152
State : state ,
149
153
}
150
154
151
- values , err := c .doHTTP (ctx , endpointRequestToken , body )
155
+ result , err := c .doHTTP (ctx , endpointRequestToken , body )
152
156
if err != nil {
153
157
return "" , err
154
158
}
155
159
156
- token := values .GetStringBytes ("code" )
157
- if string (token ) == "" {
158
- return "" , errors .New ("empty request token in API response" )
159
- }
160
-
161
- return string (token ), nil
162
- }
163
-
164
- func (c * Client ) parseItems (values * fastjson.Value ) []Item {
165
- const indexForItemId int = 13
166
-
167
- var (
168
- items []Item
169
- itemId string
170
- index int
171
- )
172
-
173
- newJsonStr := values .GetObject ("list" ).String ()
174
- for index != - 1 {
175
- index = strings .Index (newJsonStr , ":{\" item_id\" :\" " )
176
- if index != - 1 {
177
- for i := index + indexForItemId ; string (newJsonStr [i ]) != "\" " ; i ++ {
178
- itemId += string (newJsonStr [i ])
179
- }
180
-
181
- items = append (items , createItem (itemId , values ))
182
-
183
- itemId = ""
184
- oldJsonStr := newJsonStr
185
- newJsonStr = ``
186
-
187
- for i := index + indexForItemId ; i != len (oldJsonStr ); i ++ {
188
- newJsonStr += string (oldJsonStr [i ])
189
- }
190
- }
160
+ token := result .Get ("code" ).String ()
161
+ if token == "" {
162
+ return "" , fmt .Errorf ("empty request token in API response" )
191
163
}
192
164
193
- return items
165
+ return token , nil
194
166
}
195
167
196
- func (c * Client ) doHTTP (ctx context.Context , endpoint string , body interface {}) (* fastjson. Value , error ) {
168
+ func (c * Client ) doHTTP (ctx context.Context , endpoint string , body interface {}) (gjson. Result , error ) {
197
169
b , err := json .Marshal (body )
198
170
if err != nil {
199
- return nil , fmt .Errorf ("an error occurred when marshal the input body: %s" , err .Error ())
171
+ return gjson. Result {} , fmt .Errorf ("an error occurred when marshal the input body: %s" , err .Error ())
200
172
}
201
173
202
174
req , err := http .NewRequestWithContext (ctx , "POST" , host + endpoint , bytes .NewBufferString (string (b )))
203
175
if err != nil {
204
- return nil , fmt .Errorf ("an error occurred when creating the query: %s" , err .Error ())
176
+ return gjson. Result {} , fmt .Errorf ("an error occurred when creating the query: %s" , err .Error ())
205
177
}
206
178
207
179
req .Header .Set ("Content-Type" , "application/json; charset=UTF-8" )
208
180
req .Header .Set ("X-Accept" , "application/json" )
209
181
210
182
resp , err := c .client .Do (req )
211
183
if err != nil {
212
- return nil , fmt .Errorf ("an error occurred when sending a request to the Pocket server: %s" , err .Error ())
184
+ return gjson. Result {} , fmt .Errorf ("an error occurred when sending a request to the Pocket server: %s" , err .Error ())
213
185
}
214
186
defer resp .Body .Close ()
215
187
216
188
if resp .StatusCode != http .StatusOK {
217
- return nil , fmt .Errorf ("API error %s: %s" , resp .Header .Get (xErrorCodeHeader ), resp .Header .Get (xErrorHeader ))
189
+ return gjson. Result {} , fmt .Errorf ("API error %s: %s" , resp .Header .Get (xErrorCodeHeader ), resp .Header .Get (xErrorHeader ))
218
190
}
219
191
220
192
respBody , err := ioutil .ReadAll (resp .Body )
221
193
if err != nil {
222
- return nil , fmt .Errorf ("an error occurred when reading the request body: %s" , err .Error ())
194
+ return gjson. Result {} , fmt .Errorf ("an error occurred when reading the request body: %s" , err .Error ())
223
195
}
224
196
225
- values , err := fastjson .Parse (string (respBody ))
226
- if err != nil {
227
- return nil , fmt .Errorf ("an error occurred while parsing the response body: %s" , err . Error () )
197
+ result := gjson .Parse (string (respBody ))
198
+ if result . String () == "" {
199
+ return gjson. Result {} , fmt .Errorf ("failed to parse response body" )
228
200
}
229
201
230
- return values , nil
202
+ return result , nil
231
203
}
0 commit comments