-
Notifications
You must be signed in to change notification settings - Fork 246
/
tweet.go
154 lines (135 loc) · 5.9 KB
/
tweet.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
package anaconda
import (
"encoding/json"
"fmt"
"time"
)
type Tweet struct {
Contributors []int64 `json:"contributors"`
Coordinates *Coordinates `json:"coordinates"`
CreatedAt string `json:"created_at"`
DisplayTextRange []int `json:"display_text_range"`
Entities Entities `json:"entities"`
ExtendedEntities Entities `json:"extended_entities"`
ExtendedTweet ExtendedTweet `json:"extended_tweet"`
FavoriteCount int `json:"favorite_count"`
Favorited bool `json:"favorited"`
FilterLevel string `json:"filter_level"`
FullText string `json:"full_text"`
HasExtendedProfile bool `json:"has_extended_profile"`
Id int64 `json:"id"`
IdStr string `json:"id_str"`
InReplyToScreenName string `json:"in_reply_to_screen_name"`
InReplyToStatusID int64 `json:"in_reply_to_status_id"`
InReplyToStatusIdStr string `json:"in_reply_to_status_id_str"`
InReplyToUserID int64 `json:"in_reply_to_user_id"`
InReplyToUserIdStr string `json:"in_reply_to_user_id_str"`
IsTranslationEnabled bool `json:"is_translation_enabled"`
Lang string `json:"lang"`
Place Place `json:"place"`
QuotedStatusID int64 `json:"quoted_status_id"`
QuotedStatusIdStr string `json:"quoted_status_id_str"`
QuotedStatus *Tweet `json:"quoted_status"`
PossiblySensitive bool `json:"possibly_sensitive"`
PossiblySensitiveAppealable bool `json:"possibly_sensitive_appealable"`
RetweetCount int `json:"retweet_count"`
Retweeted bool `json:"retweeted"`
RetweetedStatus *Tweet `json:"retweeted_status"`
Source string `json:"source"`
Scopes map[string]interface{} `json:"scopes"`
Text string `json:"text"`
User User `json:"user"`
WithheldCopyright bool `json:"withheld_copyright"`
WithheldInCountries []string `json:"withheld_in_countries"`
WithheldScope string `json:"withheld_scope"`
//Geo is deprecated
//Geo interface{} `json:"geo"`
}
// CreatedAtTime is a convenience wrapper that returns the Created_at time, parsed as a time.Time struct
func (t Tweet) CreatedAtTime() (time.Time, error) {
return time.Parse(time.RubyDate, t.CreatedAt)
}
// It may be worth placing these in an additional source file(s)
// Could also use User, since the fields match, but only these fields are possible in Contributor
type Contributor struct {
Id int64 `json:"id"`
IdStr string `json:"id_str"`
ScreenName string `json:"screen_name"`
}
type Coordinates struct {
Coordinates [2]float64 `json:"coordinates"` // Coordinate always has to have exactly 2 values
Type string `json:"type"`
}
type ExtendedTweet struct {
FullText string `json:"full_text"`
DisplayTextRange []int `json:"display_text_range"`
Entities Entities `json:"entities"`
ExtendedEntities Entities `json:"extended_entities"`
}
// HasCoordinates is a helper function to easily determine if a Tweet has coordinates associated with it
func (t Tweet) HasCoordinates() bool {
if t.Coordinates != nil {
if t.Coordinates.Type == "Point" {
return true
}
}
return false
}
// The following provide convenience and eliviate confusion about the order of coordinates in the Tweet
// Latitude is a convenience wrapper that returns the latitude easily
func (t Tweet) Latitude() (float64, error) {
if t.HasCoordinates() {
return t.Coordinates.Coordinates[1], nil
}
return 0, fmt.Errorf("No Coordinates in this Tweet")
}
// Longitude is a convenience wrapper that returns the longitude easily
func (t Tweet) Longitude() (float64, error) {
if t.HasCoordinates() {
return t.Coordinates.Coordinates[0], nil
}
return 0, fmt.Errorf("No Coordinates in this Tweet")
}
// X is a convenience wrapper which returns the X (Longitude) coordinate easily
func (t Tweet) X() (float64, error) {
return t.Longitude()
}
// Y is a convenience wrapper which return the Y (Lattitude) corrdinate easily
func (t Tweet) Y() (float64, error) {
return t.Latitude()
}
func (t *Tweet) extractExtendedTweet() {
// if the TruncatedText is set, the API does not return an extended tweet
// we need to manually set the Text in this case
if len(t.Text) > 0 && len(t.FullText) == 0 {
t.FullText = t.Text
}
if len(t.ExtendedTweet.FullText) > 0 {
t.DisplayTextRange = t.ExtendedTweet.DisplayTextRange
t.Entities = t.ExtendedTweet.Entities
t.ExtendedEntities = t.ExtendedTweet.ExtendedEntities
t.FullText = t.ExtendedTweet.FullText
}
// if the API supplied us with information how to extract the shortened
// text, extract it
if len(t.Text) == 0 && len(t.DisplayTextRange) == 2 {
t.Text = t.FullText[t.DisplayTextRange[0]:t.DisplayTextRange[1]]
}
// if the truncated text is still empty then full & truncated text are equal
if len(t.Text) == 0 {
t.Text = t.FullText
}
}
func (t *Tweet) UnmarshalJSON(data []byte) error {
type Alias Tweet
aux := &struct {
*Alias
}{
Alias: (*Alias)(t),
}
if err := json.Unmarshal(data, &aux); err != nil {
return err
}
t.extractExtendedTweet()
return nil
}