forked from keys-pub/keys
-
Notifications
You must be signed in to change notification settings - Fork 0
/
twitter.go
102 lines (88 loc) · 2.35 KB
/
twitter.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
package services
import (
"context"
"encoding/json"
"fmt"
"os"
"github.com/burlingtonbertie99/mykeys/http"
"github.com/burlingtonbertie99/mykeys/user"
"github.com/burlingtonbertie99/mykeys/user/validate"
"github.com/pkg/errors"
)
// TwitterID is the id for twitter.
const TwitterID = "twitter"
type twitter struct {
bearerToken string
}
// Twitter ..
var Twitter = &twitter{
bearerToken: os.Getenv("TWITTER_BEARER_TOKEN"),
}
// SetBearerToken for auth.
func (s *twitter) SetBearerToken(bearerToken string) {
s.bearerToken = bearerToken
}
func (s *twitter) ID() string {
return TwitterID
}
func (s *twitter) Request(ctx context.Context, client http.Client, usr *user.User) (user.Status, []byte, error) {
apiURL, err := validate.Twitter.APIURL(usr.Name, usr.URL)
if err != nil {
return user.StatusFailure, nil, err
}
headers := s.headers()
return Request(ctx, client, apiURL, headers)
}
func (s *twitter) Verify(ctx context.Context, b []byte, usr *user.User) (user.Status, *Verified, error) {
var tweet tweet
if err := json.Unmarshal(b, &tweet); err != nil {
return user.StatusContentInvalid, nil, err
}
logger.Debugf("Tweet: %+v", tweet)
// TODO: Double check tweet id matches
found := false
authorID := tweet.Data.AuthorID
for _, tweetUser := range tweet.Includes.Users {
if authorID == tweetUser.ID {
tweetUserName := validate.Twitter.NormalizeName(tweetUser.Username)
if tweetUserName != usr.Name {
return user.StatusContentInvalid, nil, errors.Errorf("invalid tweet username %s", tweetUser.Username)
}
found = true
}
}
if !found {
return user.StatusContentInvalid, nil, errors.Errorf("tweet username not found")
}
msg := tweet.Data.Text
status, statement, err := user.FindVerify(usr, []byte(msg), false)
if err != nil {
return status, nil, err
}
return status, &Verified{Statement: statement}, nil
}
func (s *twitter) headers() []http.Header {
if s.bearerToken == "" {
return nil
}
return []http.Header{
{
Name: "Authorization",
Value: fmt.Sprintf("Bearer %s", s.bearerToken),
},
}
}
type tweet struct {
Data struct {
ID string `json:"id"`
Text string `json:"text"`
AuthorID string `json:"author_id"`
} `json:"data"`
Includes struct {
Users []struct {
ID string `json:"id"`
Name string `json:"name"`
Username string `json:"username"`
} `json:"users"`
} `json:"includes"`
}