8
8
"strings"
9
9
"time"
10
10
11
+ "github.com/nextdotid/proof_server/util"
11
12
"github.com/samber/lo"
12
13
"golang.org/x/xerrors"
13
14
)
@@ -20,16 +21,18 @@ type APIResponse struct {
20
21
Text string `json:"text"`
21
22
}
22
23
23
- const (
24
- BASIC_AUTH_USERNAME = "3rJOl1ODzm9yZy63FACdg"
25
- BASIC_AUTH_PASSWORD = "5jPoQ5kQvMJFDYRNE8bQ4rHuds4xJqhvgNJM4awaE8"
26
- )
24
+ type Tokens struct {
25
+ AccessToken string `json:"access_token"`
26
+ GuestToken string `json:"guest_token"`
27
+ FlowToken string `json:"flow_token"`
28
+ OAuthKey string `json:"oauth_key"`
29
+ OAuthSecret string `json:"oauth_secret"`
30
+ CreatedAt string `json:"created_at"`
31
+ }
27
32
28
- var (
29
- // TODO: should save accessToken to somewhere else (shared by all Lambda instances)
30
- accessToken string
31
- guestToken string
32
- flowToken string
33
+ const (
34
+ TWITTER_CONSUMER_KEY = "3rJOl1ODzm9yZy63FACdg"
35
+ TWITTER_CONSUMER_SECRET = "5jPoQ5kQvMJFDYRNE8bQ4rHuds4xJqhvgNJM4awaE8"
33
36
)
34
37
35
38
func fetchPostWithAPI (id string , maxRetries int ) (tweet * APIResponse , err error ) {
@@ -38,7 +41,7 @@ func fetchPostWithAPI(id string, maxRetries int) (tweet *APIResponse, err error)
38
41
return nil , nil
39
42
}
40
43
41
- func setHeaders (req * http.Request , setAccessToken , setGuestToken bool ) {
44
+ func setHeaders (req * http.Request , tokens * Tokens , setAccessToken , setGuestToken bool ) {
42
45
req .Header .Set ("User-Agent" , "TwitterAndroid/9.95.0-release.0 (29950000-r-0) ONEPLUS+A3010/9 (OnePlus;ONEPLUS+A3010;OnePlus;OnePlus3;0;;1;2016)" )
43
46
req .Header .Set ("Content-Type" , "application/json" )
44
47
req .Header .Set ("Accept" , "application/json" )
@@ -49,20 +52,23 @@ func setHeaders(req *http.Request, setAccessToken, setGuestToken bool) {
49
52
req .Header .Set ("System-User-Agent" , "Dalvik/2.1.0 (Linux; U; Android 9; ONEPLUS A3010 Build/PKQ1.181203.001)" )
50
53
req .Header .Set ("X-Twitter-Active-User" , "yes" )
51
54
if setGuestToken {
52
- req .Header .Set ("X-Guest-Token" , guestToken )
55
+ req .Header .Set ("X-Guest-Token" , tokens . GuestToken )
53
56
}
54
57
if setAccessToken {
55
- req .Header .Set ("Authorization" , "Bearer " + accessToken )
58
+ req .Header .Set ("Authorization" , "Bearer " + tokens . AccessToken )
56
59
}
57
60
}
58
61
59
- func GetOauthToken () (err error ) {
60
- if flowToken == "" {
61
- if err := getFlowToken (); err != nil {
62
- return err
63
- }
62
+ // GenerateOauthToken generates a new Twitter OAuth guest token
63
+ // which can be used in calling Official APIs.
64
+ func GenerateOauthToken () (tokens * Tokens , err error ) {
65
+ tokens = new (Tokens )
66
+ tokens .CreatedAt = util .TimeToTimestampString (time .Now ())
67
+
68
+ if err := tokens .getFlowToken (); err != nil {
69
+ return nil , err
64
70
}
65
- l .Infof ("Access token: %s\n Guest token: %s\n Flow token: %s\n " , accessToken , guestToken , flowToken )
71
+ l .Infof ("Access token: %s\n Guest token: %s\n Flow token: %s\n " , tokens . AccessToken , tokens . GuestToken , tokens . FlowToken )
66
72
67
73
requestBody := fmt .Sprintf (`{
68
74
"flow_token": "%s",
@@ -128,22 +134,22 @@ func GetOauthToken() (err error) {
128
134
"location_permission_prompt": 2,
129
135
"notifications_permission_prompt": 4
130
136
}
131
- }` , flowToken )
137
+ }` , tokens . FlowToken )
132
138
133
139
req , err := http .NewRequest ("POST" , "https://api.twitter.com/1.1/onboarding/task.json" , strings .NewReader (requestBody ))
134
140
if err != nil {
135
- return err
141
+ return nil , err
136
142
}
137
- setHeaders (req , true , true )
143
+ setHeaders (req , tokens , true , true )
138
144
139
145
resp , err := new (http.Client ).Do (req )
140
146
if err != nil {
141
- return err
147
+ return nil , err
142
148
}
143
149
144
150
body , err := io .ReadAll (resp .Body )
145
151
if err != nil {
146
- return err
152
+ return nil , err
147
153
}
148
154
l .Infof ("Response: \n %s\n " , body )
149
155
type ResponseSubtask struct {
@@ -163,36 +169,37 @@ func GetOauthToken() (err error) {
163
169
// Should be "success"
164
170
Status string `json:"status"`
165
171
// A new flow token, usually ends with ":3"
166
- FlowToken string `json:"flow_token"`
172
+ FlowToken string `json:"flow_token"`
167
173
Subtasks []ResponseSubtask `json:"subtasks"`
168
174
}
169
175
response := new (Response )
170
176
err = json .Unmarshal (body , response )
171
177
if err != nil {
172
- return err
178
+ return nil , err
173
179
}
174
180
if response .Errors != nil {
175
- return xerrors .Errorf ("error when getting oauth token: %+v" , * response .Errors )
181
+ return nil , xerrors .Errorf ("error when getting oauth token: %+v" , * response .Errors )
176
182
}
177
183
if response .Status != "success" {
178
- return xerrors .Errorf ("wrong API status: %s" , response .Status )
184
+ return nil , xerrors .Errorf ("wrong API status: %s" , response .Status )
179
185
}
180
186
181
187
st , found := lo .Find (response .Subtasks , func (subtask ResponseSubtask ) bool {
182
188
return (subtask .OpenAccount != nil )
183
189
})
184
190
if ! found {
185
- return xerrors .Errorf ("oauth token not found in response" )
191
+ return nil , xerrors .Errorf ("oauth token not found in response" )
186
192
}
187
- flowToken = response .FlowToken
193
+ // Update new FlowToken
194
+ tokens .FlowToken = response .FlowToken
188
195
l .Infof ("OAUTH TOKEN REGISTERED: %s --- %s" , st .OpenAccount .OauthToken , st .OpenAccount .OauthTokenSecret )
189
196
190
- return nil
197
+ return tokens , nil
191
198
}
192
199
193
- func getFlowToken () (err error ) {
194
- if guestToken == "" {
195
- if err := getGuestToken (); err != nil {
200
+ func ( tokens * Tokens ) getFlowToken () (err error ) {
201
+ if tokens . GuestToken == "" {
202
+ if err := tokens . getGuestToken (); err != nil {
196
203
return err
197
204
}
198
205
}
@@ -269,7 +276,7 @@ func getFlowToken() (err error) {
269
276
if err != nil {
270
277
return err
271
278
}
272
- setHeaders (req , true , true )
279
+ setHeaders (req , tokens , true , true )
273
280
274
281
resp , err := new (http.Client ).Do (req )
275
282
if err != nil {
@@ -293,24 +300,24 @@ func getFlowToken() (err error) {
293
300
return xerrors .Errorf ("empty FlowToken" )
294
301
}
295
302
296
- flowToken = response .FlowToken
303
+ tokens . FlowToken = response .FlowToken
297
304
return nil
298
305
}
299
306
300
- func getGuestToken () (err error ) {
301
- if guestToken != "" {
307
+ func ( tokens * Tokens ) getGuestToken () (err error ) {
308
+ if tokens . GuestToken != "" {
302
309
return nil
303
310
}
304
- if accessToken == "" {
305
- if err = getAccessToken (); err != nil {
311
+ if tokens . AccessToken == "" {
312
+ if err = tokens . getAccessToken (); err != nil {
306
313
return err
307
314
}
308
315
}
309
316
req , err := http .NewRequest ("POST" , "https://api.twitter.com/1.1/guest/activate.json" , nil )
310
317
if err != nil {
311
318
return err
312
319
}
313
- setHeaders (req , true , false )
320
+ setHeaders (req , tokens , true , false )
314
321
type Response struct {
315
322
GuestToken string `json:"guest_token"`
316
323
}
@@ -333,13 +340,13 @@ func getGuestToken() (err error) {
333
340
if response .GuestToken == "" {
334
341
return xerrors .Errorf ("Wrong guest token: %s" , response .GuestToken )
335
342
}
336
- guestToken = response .GuestToken
343
+ tokens . GuestToken = response .GuestToken
337
344
338
345
return nil
339
346
}
340
347
341
- func getAccessToken () (err error ) {
342
- if accessToken != "" {
348
+ func ( tokens * Tokens ) getAccessToken () (err error ) {
349
+ if tokens . AccessToken != "" {
343
350
return nil
344
351
}
345
352
@@ -351,8 +358,8 @@ func getAccessToken() (err error) {
351
358
if err != nil {
352
359
return err
353
360
}
354
- setHeaders (req , false , false )
355
- req .SetBasicAuth (BASIC_AUTH_USERNAME , BASIC_AUTH_PASSWORD )
361
+ setHeaders (req , tokens , false , false )
362
+ req .SetBasicAuth (TWITTER_CONSUMER_KEY , TWITTER_CONSUMER_SECRET )
356
363
resp , err := new (http.Client ).Do (req )
357
364
if err != nil {
358
365
return err
@@ -373,6 +380,13 @@ func getAccessToken() (err error) {
373
380
return xerrors .Errorf ("Wrong bearer token: %s %s" , response .TokenType , response .AccessToken )
374
381
}
375
382
376
- accessToken = response .AccessToken
383
+ tokens . AccessToken = response .AccessToken
377
384
return nil
378
385
}
386
+
387
+ func (tokens * Tokens ) IsExpired () bool {
388
+ const EXPIRED_AT = "24h"
389
+ expiredAt , _ := time .ParseDuration (EXPIRED_AT )
390
+ createdAt , _ := util .TimestampStringToTime (tokens .CreatedAt )
391
+ return createdAt .Add (expiredAt ).Before (time .Now ())
392
+ }
0 commit comments