diff --git a/cmd/fetch_tweet_to_stdout/main.go b/cmd/fetch_tweet_to_stdout/main.go
index 5a4b266..863e4f0 100644
--- a/cmd/fetch_tweet_to_stdout/main.go
+++ b/cmd/fetch_tweet_to_stdout/main.go
@@ -5,6 +5,7 @@ import (
"fmt"
"offline_twitter/scraper"
// "time"
+ "strconv"
"log"
"strings"
)
@@ -15,12 +16,16 @@ const INCLUDE_REPLIES = true;
func parse_tweet(url string) (scraper.TweetID, error) {
parts := strings.Split(url, "/")
if len(parts) != 6 {
- return "", fmt.Errorf("Tweet format isn't right (%d)", len(parts))
+ return 0, fmt.Errorf("Tweet format isn't right (%d)", len(parts))
}
if parts[0] != "https:" || parts[1] != "" || parts[2] != "twitter.com" || parts[4] != "status" {
- return "", fmt.Errorf("Tweet format isn't right")
+ return 0, fmt.Errorf("Tweet format isn't right")
}
- return scraper.TweetID(parts[5]), nil
+ id, err := strconv.Atoi(parts[5])
+ if err != nil {
+ return 0, err
+ }
+ return scraper.TweetID(id), nil
}
func main() {
diff --git a/cmd/twitter/helpers.go b/cmd/twitter/helpers.go
index e2c339f..e63d5d2 100644
--- a/cmd/twitter/helpers.go
+++ b/cmd/twitter/helpers.go
@@ -6,6 +6,7 @@ import (
"offline_twitter/scraper"
"offline_twitter/terminal_utils"
"strings"
+ "strconv"
)
@@ -51,10 +52,14 @@ func die(text string, display_help bool, exit_code int) {
func extract_id_from(url string) (scraper.TweetID, error) {
parts := strings.Split(url, "/")
if len(parts) != 6 {
- return "", fmt.Errorf("Tweet format isn't right (%d)", len(parts))
+ return 0, fmt.Errorf("Tweet format isn't right (%d)", len(parts))
}
if parts[0] != "https:" || parts[1] != "" || parts[2] != "twitter.com" || parts[4] != "status" {
- return "", fmt.Errorf("Tweet format isn't right")
+ return 0, fmt.Errorf("Tweet format isn't right")
}
- return scraper.TweetID(parts[5]), nil
+ id, err := strconv.Atoi(parts[5])
+ if err != nil {
+ return 0, err
+ }
+ return scraper.TweetID(id), nil
}
diff --git a/persistence/media_download_test.go b/persistence/media_download_test.go
index 77d2c79..3a0e73d 100644
--- a/persistence/media_download_test.go
+++ b/persistence/media_download_test.go
@@ -6,24 +6,11 @@ import (
"offline_twitter/scraper"
)
-/**
- * Should return the base name (filename) of the remote URL
- */
-func TestImageFilenameWhenDownloaded(t *testing.T) {
- i := scraper.Image{IsDownloaded: false, Filename: "https://pbs.twimg.com/media/E7vG1kxWQAQrWGF.jpg"}
- outpath := i.FilenameWhenDownloaded()
- expected := "E7vG1kxWQAQrWGF.jpg"
- if outpath != expected {
- t.Errorf("Expected output path to be %q, but got %q", expected, outpath)
- }
-}
-
-
/**
* Should return an `.mp4`file matching its parent Tweet's ID
*/
func TestVideoFilenameWhenDownloaded(t *testing.T) {
- v := scraper.Video{TweetID: scraper.TweetID("23"), IsDownloaded: false, Filename: "https://video.twimg.com/ext_tw_video/1418951950020845568/pu/vid/320x568/IXaQ5rPyf9mbD1aD.mp4?tag=12"}
+ v := scraper.Video{TweetID: scraper.TweetID(23), IsDownloaded: false, Filename: "https://video.twimg.com/ext_tw_video/1418951950020845568/pu/vid/320x568/IXaQ5rPyf9mbD1aD.mp4?tag=12"}
outpath := v.FilenameWhenDownloaded()
expected := "23.mp4"
if outpath != expected {
diff --git a/persistence/tweet_queries.go b/persistence/tweet_queries.go
index 886feb9..0f68e60 100644
--- a/persistence/tweet_queries.go
+++ b/persistence/tweet_queries.go
@@ -120,10 +120,9 @@ func (p Profile) GetTweetById(id scraper.TweetID) (scraper.Tweet, error) {
var postedAt int
var mentions string
var hashtags string
- var tweet_id int64
row := stmt.QueryRow(id)
- err = row.Scan(&tweet_id, &t.UserID, &t.Text, &postedAt, &t.NumLikes, &t.NumRetweets, &t.NumReplies, &t.NumQuoteTweets, &t.InReplyTo, &t.QuotedTweet, &mentions, &hashtags)
+ err = row.Scan(&t.ID, &t.UserID, &t.Text, &postedAt, &t.NumLikes, &t.NumRetweets, &t.NumReplies, &t.NumQuoteTweets, &t.InReplyTo, &t.QuotedTweet, &mentions, &hashtags)
if err != nil {
return t, err
}
@@ -133,7 +132,6 @@ func (p Profile) GetTweetById(id scraper.TweetID) (scraper.Tweet, error) {
t.Mentions = append(t.Mentions, scraper.UserHandle(m))
}
t.Hashtags = strings.Split(hashtags, ",")
- t.ID = scraper.TweetID(fmt.Sprint(tweet_id))
imgs, err := p.GetImagesForTweet(t)
if err != nil {
diff --git a/persistence/tweet_queries_test.go b/persistence/tweet_queries_test.go
index 0eadcaa..0c13b2f 100644
--- a/persistence/tweet_queries_test.go
+++ b/persistence/tweet_queries_test.go
@@ -48,7 +48,7 @@ func TestIsTweetInDatabase(t *testing.T) {
exists := profile.IsTweetInDatabase(tweet.ID)
if exists {
- t.Errorf("It shouldn't exist, but it does: %s", tweet.ID)
+ t.Errorf("It shouldn't exist, but it does: %d", tweet.ID)
}
err := profile.SaveTweet(tweet)
if err != nil {
@@ -56,7 +56,7 @@ func TestIsTweetInDatabase(t *testing.T) {
}
exists = profile.IsTweetInDatabase(tweet.ID)
if !exists {
- t.Errorf("It should exist, but it doesn't: %s", tweet.ID)
+ t.Errorf("It should exist, but it doesn't: %d", tweet.ID)
}
}
diff --git a/persistence/user_queries.go b/persistence/user_queries.go
index d3f4708..0dec7a6 100644
--- a/persistence/user_queries.go
+++ b/persistence/user_queries.go
@@ -81,15 +81,13 @@ func (p Profile) UserExists(handle scraper.UserHandle) bool {
func parse_user_from_row(row *sql.Row) (scraper.User, error) {
var u scraper.User
var joinDate int64
- var pinned_tweet_id int64
- err := row.Scan(&u.ID, &u.DisplayName, &u.Handle, &u.Bio, &u.FollowingCount, &u.FollowersCount, &u.Location, &u.Website, &joinDate, &u.IsPrivate, &u.IsVerified, &u.ProfileImageUrl, &u.BannerImageUrl, &pinned_tweet_id)
+ err := row.Scan(&u.ID, &u.DisplayName, &u.Handle, &u.Bio, &u.FollowingCount, &u.FollowersCount, &u.Location, &u.Website, &joinDate, &u.IsPrivate, &u.IsVerified, &u.ProfileImageUrl, &u.BannerImageUrl, &u.PinnedTweetID)
if err != nil {
return u, err
}
u.JoinDate = time.Unix(joinDate, 0)
- u.PinnedTweetID = scraper.TweetID(fmt.Sprint(pinned_tweet_id))
return u, nil
}
diff --git a/persistence/utils_test.go b/persistence/utils_test.go
index bc8e44e..04a25dd 100644
--- a/persistence/utils_test.go
+++ b/persistence/utils_test.go
@@ -54,7 +54,7 @@ func create_stable_user() scraper.User {
IsPrivate: false,
ProfileImageUrl: "stable profile image url",
BannerImageUrl: "stable banner image url",
- PinnedTweetID: scraper.TweetID("345"),
+ PinnedTweetID: scraper.TweetID(345),
}
}
@@ -65,7 +65,7 @@ func create_image_from_id(id int) scraper.Image {
filename := fmt.Sprintf("image%d.jpg", id)
return scraper.Image{
ID: scraper.ImageID(id),
- TweetID: "-1",
+ TweetID: -1,
Filename: filename,
IsDownloaded: false,
}
@@ -75,7 +75,7 @@ func create_image_from_id(id int) scraper.Image {
* Create a stable tweet with a fixed ID and content
*/
func create_stable_tweet() scraper.Tweet {
- tweet_id := scraper.TweetID("-1")
+ tweet_id := scraper.TweetID(-1)
return scraper.Tweet{
ID: tweet_id,
UserID: -1,
@@ -117,7 +117,7 @@ func create_dummy_user() scraper.User {
IsPrivate: true,
ProfileImageUrl: "profile image url",
BannerImageUrl: "banner image url",
- PinnedTweetID: scraper.TweetID("234"),
+ PinnedTweetID: scraper.TweetID(234),
}
}
@@ -127,7 +127,7 @@ func create_dummy_user() scraper.User {
*/
func create_dummy_tweet() scraper.Tweet {
rand.Seed(time.Now().UnixNano())
- tweet_id := scraper.TweetID(fmt.Sprint(rand.Int()))
+ tweet_id := scraper.TweetID(rand.Int())
img1 := create_image_from_id(rand.Int())
img1.TweetID = tweet_id
@@ -143,7 +143,7 @@ func create_dummy_tweet() scraper.Tweet {
NumRetweets: 2,
NumReplies: 3,
NumQuoteTweets: 4,
- Videos: []scraper.Video{scraper.Video{TweetID: tweet_id, Filename: "video" + string(tweet_id), IsDownloaded: false}},
+ Videos: []scraper.Video{scraper.Video{TweetID: tweet_id, Filename: "video" + fmt.Sprint(tweet_id), IsDownloaded: false}},
Urls: []string{"url1", "url2"},
Images: []scraper.Image{img1, img2},
Mentions: []scraper.UserHandle{"mention1", "mention2"},
diff --git a/scraper/api_request_utils.go b/scraper/api_request_utils.go
index fdb00b4..c91cd07 100644
--- a/scraper/api_request_utils.go
+++ b/scraper/api_request_utils.go
@@ -77,7 +77,7 @@ func (api API) GetMoreTweets(user_id UserID, response *TweetResponse, max_tweets
func (api API) GetTweet(id TweetID, cursor string) (TweetResponse, error) {
client := &http.Client{Timeout: 10 * time.Second}
- req, err := http.NewRequest("GET", fmt.Sprintf("%s%s.json", API_CONVERSATION_BASE_PATH, id), nil)
+ req, err := http.NewRequest("GET", fmt.Sprintf("%s%d.json", API_CONVERSATION_BASE_PATH, id), nil)
if err != nil {
return TweetResponse{}, err
}
diff --git a/scraper/api_types.go b/scraper/api_types.go
index 977fd7b..e41b93c 100644
--- a/scraper/api_types.go
+++ b/scraper/api_types.go
@@ -4,6 +4,7 @@ import (
"time"
"strings"
"encoding/json"
+ "strconv"
)
type SortableVariants []struct {
@@ -22,8 +23,8 @@ type APIMedia struct {
}
type APITweet struct {
- ID string `json:"id_str"`
- ConversationIDStr string `json:"conversation_id_str"`
+ ID int64 `json:"id_str,string"`
+ ConversationID int64 `json:"conversation_id_str,string"`
CreatedAt string `json:"created_at"`
FavoriteCount int `json:"favorite_count"`
FullText string `json:"full_text"`
@@ -51,13 +52,15 @@ type APITweet struct {
} `json:"video_info"`
} `json:"media"`
} `json:"extended_entities"`
- InReplyToStatusIDStr string `json:"in_reply_to_status_id_str"`
+ InReplyToStatusID int64 `json:"in_reply_to_status_id_str,string"`
InReplyToScreenName string `json:"in_reply_to_screen_name"`
ReplyCount int `json:"reply_count"`
RetweetCount int `json:"retweet_count"`
QuoteCount int `json:"quote_count"`
- RetweetedStatusIDStr string `json:"retweeted_status_id_str"`
- QuotedStatusIDStr string `json:"quoted_status_id_str"`
+ RetweetedStatusIDStr string `json:"retweeted_status_id_str"` // Can be empty string
+ RetweetedStatusID int64
+ QuotedStatusIDStr string `json:"quoted_status_id_str"` // Can be empty string
+ QuotedStatusID int64
Time time.Time `json:"time"`
UserID int64 `json:"user_id_str,string"`
}
@@ -83,6 +86,15 @@ func (t *APITweet) NormalizeContent() {
}
}
t.FullText = strings.TrimSpace(t.FullText)
+
+ id, err := strconv.Atoi(t.QuotedStatusIDStr)
+ if err == nil {
+ t.QuotedStatusID = int64(id)
+ }
+ id, err = strconv.Atoi(t.RetweetedStatusIDStr)
+ if err == nil {
+ t.RetweetedStatusID = int64(id)
+ }
}
func (t APITweet) String() string {
@@ -166,3 +178,12 @@ func (t *TweetResponse) GetCursor() string {
}
return ""
}
+
+
+func idstr_to_int(idstr string) int64 {
+ id, err := strconv.Atoi(idstr)
+ if err != nil {
+ panic(err)
+ }
+ return int64(id)
+}
diff --git a/scraper/api_types_test.go b/scraper/api_types_test.go
index 1ed2120..8823dec 100644
--- a/scraper/api_types_test.go
+++ b/scraper/api_types_test.go
@@ -13,11 +13,16 @@ func TestNormalizeContent(t *testing.T) {
test_cases := []struct {
filename string
eventual_full_text string
+ quoted_status_id scraper.TweetID
+ in_reply_to scraper.TweetID
+ retweeted_status_id scraper.TweetID
} {
- {"test_responses/tweet_with_gif_reply.json", ""},
- {"test_responses/tweet_with_image.json", "this saddens me every time"},
- {"test_responses/tweet_with_reply.json", "I always liked \"The Anarchist's Cookbook.\""},
- {"test_responses/tweet_with_4_images.json", "These are public health officials who are making decisions about your lifestyle because they know more about health, fitness and well-being than you do"},
+ {"test_responses/tweet_with_gif_reply.json", "", 0, 1395882872729477131, 0},
+ {"test_responses/tweet_with_image.json", "this saddens me every time", 0, 0, 0},
+ {"test_responses/tweet_with_reply.json", "I always liked \"The Anarchist's Cookbook.\"", 0, 1395978577267593218, 0},
+ {"test_responses/tweet_with_4_images.json", "These are public health officials who are making decisions about your lifestyle because they know more about health, fitness and well-being than you do", 0, 0, 0},
+ {"test_responses/tweet_with_quoted_tweet.json", "", 1422680899670274048, 0, 0},
+ {"test_responses/tweet_that_is_a_retweet.json", "RT @nofunin10ded: @michaelmalice We're dealing with people who will napalm your children and then laugh about it", 0, 0, 1404269989646028804},
}
for _, v := range test_cases {
data, err := ioutil.ReadFile(v.filename)
@@ -35,6 +40,15 @@ func TestNormalizeContent(t *testing.T) {
if tweet.FullText != v.eventual_full_text {
t.Errorf("Expected %q, got %q", v.eventual_full_text, tweet.FullText)
}
+ if scraper.TweetID(tweet.QuotedStatusID) != v.quoted_status_id {
+ t.Errorf("Expected quoted status %d, but got %d", v.quoted_status_id, tweet.QuotedStatusID)
+ }
+ if scraper.TweetID(tweet.InReplyToStatusID) != v.in_reply_to {
+ t.Errorf("Expected quoted status %d, but got %d", v.in_reply_to, tweet.InReplyToStatusID)
+ }
+ if scraper.TweetID(tweet.RetweetedStatusID) != v.retweeted_status_id {
+ t.Errorf("Expected quoted status %d, but got %d", v.retweeted_status_id, tweet.RetweetedStatusID)
+ }
}
}
diff --git a/scraper/retweet.go b/scraper/retweet.go
index 0c1771d..91e0a4d 100644
--- a/scraper/retweet.go
+++ b/scraper/retweet.go
@@ -14,8 +14,10 @@ type Retweet struct {
}
func ParseSingleRetweet(apiTweet APITweet) (ret Retweet, err error) {
+ apiTweet.NormalizeContent()
+
ret.RetweetID = TweetID(apiTweet.ID)
- ret.TweetID = TweetID(apiTweet.RetweetedStatusIDStr)
+ ret.TweetID = TweetID(apiTweet.RetweetedStatusID)
ret.RetweetedByID = UserID(apiTweet.UserID)
ret.RetweetedAt, err = time.Parse(time.RubyDate, apiTweet.CreatedAt)
return
diff --git a/scraper/retweet_test.go b/scraper/retweet_test.go
index f6718e8..616b576 100644
--- a/scraper/retweet_test.go
+++ b/scraper/retweet_test.go
@@ -23,14 +23,15 @@ func TestParseSingleRetweet(t *testing.T) {
if err != nil {
t.Errorf(err.Error())
}
-
- if retweet.RetweetID != "1404270043018448896" {
- t.Errorf("Expected %q, got %q", "1404270043018448896", retweet.RetweetID)
+ expected_id := 1404270043018448896
+ if retweet.RetweetID != scraper.TweetID(1404270043018448896) {
+ t.Errorf("Expected %d, got %d", expected_id, retweet.RetweetID)
}
- if retweet.TweetID != "1404269989646028804" {
- t.Errorf("Expected %q, got %q", "1404269989646028804", retweet.TweetID)
+ expected_id = 1404269989646028804
+ if retweet.TweetID != scraper.TweetID(expected_id) {
+ t.Errorf("Expected %d, got %d", expected_id, retweet.TweetID)
}
- expected_id := 44067298
+ expected_id = 44067298
if retweet.RetweetedByID != scraper.UserID(expected_id) {
t.Errorf("Expected %d, got %d", expected_id, retweet.RetweetedByID)
}
diff --git a/scraper/test_responses/tweet_that_is_a_retweet.json b/scraper/test_responses/tweet_that_is_a_retweet.json
index 2d4e187..bb03cb5 100644
--- a/scraper/test_responses/tweet_that_is_a_retweet.json
+++ b/scraper/test_responses/tweet_that_is_a_retweet.json
@@ -1,34 +1 @@
-{
- "created_at": "Mon Jun 14 02:50:42 +0000 2021",
- "id_str": "1404270043018448896",
- "text": "RT @nofunin10ded: @michaelmalice We're dealing with people who will napalm your children and then laugh about it",
- "entities": {
- "user_mentions": [
- {
- "screen_name": "nofunin10ded",
- "name": "Adam",
- "id_str": "1265866918835236865",
- "indices": [
- 3,
- 16
- ]
- },
- {
- "screen_name": "michaelmalice",
- "name": "Michael Malice",
- "id_str": "44067298",
- "indices": [
- 18,
- 32
- ]
- }
- ]
- },
- "source": "Twitter Web App",
- "user_id_str": "44067298",
- "retweeted_status_id_str": "1404269989646028804",
- "retweet_count": 17,
- "favorite_count": 0,
- "conversation_id_str": "1404270043018448896",
- "lang": "en"
-}
+{"created_at":"Mon Jun 14 02:50:42 +0000 2021","id_str":"1404270043018448896","full_text":"RT @nofunin10ded: @michaelmalice We're dealing with people who will napalm your children and then laugh about it","display_text_range":[0,112],"entities":{"user_mentions":[{"screen_name":"nofunin10ded","name":"Adam","id_str":"1265866918835236865","indices":[3,16]},{"screen_name":"michaelmalice","name":"Michael Malice","id_str":"44067298","indices":[18,32]}]},"source":"Twitter Web App","user_id_str":"44067298","retweeted_status_id_str":"1404269989646028804","retweet_count":26,"favorite_count":0,"reply_count":0,"quote_count":0,"conversation_id_str":"1404270043018448896","lang":"en"}
diff --git a/scraper/test_responses/tweet_with_quoted_tweet.json b/scraper/test_responses/tweet_with_quoted_tweet.json
new file mode 100644
index 0000000..2de374d
--- /dev/null
+++ b/scraper/test_responses/tweet_with_quoted_tweet.json
@@ -0,0 +1 @@
+{"created_at":"Tue Aug 03 23:56:40 +0000 2021","id_str":"1422708023768793091","full_text":"https://t.co/8FaOybk9Zz","display_text_range":[0,0],"entities":{"media":[{"id_str":"1422708017481531394","indices":[0,23],"media_url":"http://pbs.twimg.com/media/E755Z3EWQAIZ0Bf.jpg","media_url_https":"https://pbs.twimg.com/media/E755Z3EWQAIZ0Bf.jpg","url":"https://t.co/8FaOybk9Zz","display_url":"pic.twitter.com/8FaOybk9Zz","expanded_url":"https://twitter.com/michaelmalice/status/1422708023768793091/photo/1","type":"photo","original_info":{"width":2048,"height":1152,"focus_rects":[{"x":0,"y":0,"h":1147,"w":2048},{"x":499,"y":0,"h":1152,"w":1152},{"x":570,"y":0,"h":1152,"w":1011},{"x":787,"y":0,"h":1152,"w":576},{"x":0,"y":0,"h":1152,"w":2048}]},"sizes":{"thumb":{"w":150,"h":150,"resize":"crop"},"medium":{"w":1200,"h":675,"resize":"fit"},"large":{"w":2048,"h":1152,"resize":"fit"},"small":{"w":680,"h":383,"resize":"fit"}}}]},"extended_entities":{"media":[{"id_str":"1422708017481531394","indices":[0,23],"media_url":"http://pbs.twimg.com/media/E755Z3EWQAIZ0Bf.jpg","media_url_https":"https://pbs.twimg.com/media/E755Z3EWQAIZ0Bf.jpg","url":"https://t.co/8FaOybk9Zz","display_url":"pic.twitter.com/8FaOybk9Zz","expanded_url":"https://twitter.com/michaelmalice/status/1422708023768793091/photo/1","type":"photo","original_info":{"width":2048,"height":1152,"focus_rects":[{"x":0,"y":0,"h":1147,"w":2048},{"x":499,"y":0,"h":1152,"w":1152},{"x":570,"y":0,"h":1152,"w":1011},{"x":787,"y":0,"h":1152,"w":576},{"x":0,"y":0,"h":1152,"w":2048}]},"sizes":{"thumb":{"w":150,"h":150,"resize":"crop"},"medium":{"w":1200,"h":675,"resize":"fit"},"large":{"w":2048,"h":1152,"resize":"fit"},"small":{"w":680,"h":383,"resize":"fit"}},"media_key":"3_1422708017481531394","ext_alt_text":null,"ext_media_availability":{"status":"available"},"ext_media_color":{"palette":[{"rgb":{"red":4,"green":0,"blue":0},"percentage":93.11},{"rgb":{"red":85,"green":61,"blue":32},"percentage":2.51},{"rgb":{"red":157,"green":151,"blue":143},"percentage":2.12},{"rgb":{"red":31,"green":33,"blue":45},"percentage":0.68},{"rgb":{"red":79,"green":33,"blue":11},"percentage":0.21}]},"ext":{"mediaStats":{"r":"Missing","ttl":-1}}}]},"source":"Twitter Web App","user_id_str":"44067298","is_quote_status":true,"quoted_status_id_str":"1422680899670274048","quoted_status_permalink":{"url":"https://t.co/6qm3rFL9V0","expanded":"https://twitter.com/steffdaz/status/1422680899670274048","display":"twitter.com/steffdaz/statu…"},"retweet_count":24,"favorite_count":352,"reply_count":9,"quote_count":1,"conversation_id_str":"1422708023768793091","possibly_sensitive_editable":true,"lang":"und"}
diff --git a/scraper/tweet.go b/scraper/tweet.go
index 91ad2c4..ecfac39 100644
--- a/scraper/tweet.go
+++ b/scraper/tweet.go
@@ -10,7 +10,7 @@ import (
const DEFAULT_MAX_REPLIES_EAGER_LOAD = 50
-type TweetID string
+type TweetID int64
type Tweet struct {
ID TweetID
@@ -86,7 +86,7 @@ func ParseSingleTweet(apiTweet APITweet) (ret Tweet, err error) {
ret.NumRetweets = apiTweet.RetweetCount
ret.NumReplies = apiTweet.ReplyCount
ret.NumQuoteTweets = apiTweet.QuoteCount
- ret.InReplyTo = TweetID(apiTweet.InReplyToStatusIDStr)
+ ret.InReplyTo = TweetID(apiTweet.InReplyToStatusID)
for _, url := range apiTweet.Entities.URLs {
ret.Urls = append(ret.Urls, url.ExpandedURL)
@@ -107,7 +107,7 @@ func ParseSingleTweet(apiTweet APITweet) (ret Tweet, err error) {
ret.Mentions = append(ret.Mentions, UserHandle(mention.UserName))
}
- ret.QuotedTweet = TweetID(apiTweet.QuotedStatusIDStr)
+ ret.QuotedTweet = TweetID(apiTweet.QuotedStatusID)
for _, entity := range apiTweet.ExtendedEntities.Media {
if entity.Type != "video" {
@@ -133,7 +133,7 @@ func GetTweet(id TweetID) (Tweet, error) {
return Tweet{}, fmt.Errorf("Error in API call: %s", err)
}
- single_tweet, ok := tweet_response.GlobalObjects.Tweets[string(id)]
+ single_tweet, ok := tweet_response.GlobalObjects.Tweets[fmt.Sprint(id)]
if !ok {
return Tweet{}, fmt.Errorf("Didn't get the tweet!\n%v", tweet_response)
diff --git a/scraper/tweet_test.go b/scraper/tweet_test.go
index af9278a..f7bdf5e 100644
--- a/scraper/tweet_test.go
+++ b/scraper/tweet_test.go
@@ -1,6 +1,7 @@
package scraper_test
import (
+ "fmt"
"encoding/json"
"io/ioutil"
"testing"
@@ -112,15 +113,15 @@ func TestParseSingleTweet2(t *testing.T) {
if tweet2.InReplyTo != tweet1.ID {
t.Errorf("Expected %q, got %q", tweet1.ID, tweet2.InReplyTo)
}
- if tweet1.QuotedTweet != "" {
+ if tweet1.QuotedTweet != 0 {
t.Errorf("Incorrectly believes it quote-tweets %q", tweet1.QuotedTweet)
}
- if tweet2.QuotedTweet == "" {
+ if tweet2.QuotedTweet == 0 {
t.Errorf("Should be a quoted tweet")
}
- quoted_tweet_, ok := tweets[string(tweet2.QuotedTweet)]
+ quoted_tweet_, ok := tweets[fmt.Sprint(tweet2.QuotedTweet)]
if !ok {
t.Errorf("Couldn't find the quoted tweet")
}
diff --git a/scraper/user.go b/scraper/user.go
index 863a8ff..a31b988 100644
--- a/scraper/user.go
+++ b/scraper/user.go
@@ -92,7 +92,7 @@ func ParseSingleUser(apiUser APIUser) (ret User, err error) {
ret.ProfileImageUrl = apiUser.ProfileImageURLHTTPS
ret.BannerImageUrl = apiUser.ProfileBannerURL
if len(apiUser.PinnedTweetIdsStr) > 0 {
- ret.PinnedTweetID = TweetID(apiUser.PinnedTweetIdsStr[0])
+ ret.PinnedTweetID = TweetID(idstr_to_int(apiUser.PinnedTweetIdsStr[0]))
}
return
}
diff --git a/scraper/user_test.go b/scraper/user_test.go
index 00e4d12..3c137c1 100644
--- a/scraper/user_test.go
+++ b/scraper/user_test.go
@@ -68,7 +68,8 @@ func TestParseSingleUser(t *testing.T) {
if user.BannerImageUrl != expectedBannerImage {
t.Errorf("Expected %q, got %q", expectedBannerImage, user.BannerImageUrl)
}
- if user.PinnedTweetID != scraper.TweetID("1403835414373339136") {
- t.Errorf("Expected %q, got %q", scraper.TweetID("1403835414373339136"), user.PinnedTweet)
+ expected_id = 1403835414373339136
+ if user.PinnedTweetID != scraper.TweetID(expected_id) {
+ t.Errorf("Expected %q, got %q", expected_id, user.PinnedTweet)
}
}
diff --git a/scraper/video.go b/scraper/video.go
index 45ecf5d..406e9e1 100644
--- a/scraper/video.go
+++ b/scraper/video.go
@@ -14,5 +14,5 @@ type Video struct {
}
func (v Video) FilenameWhenDownloaded() string {
- return fmt.Sprintf("%s.mp4", v.TweetID)
+ return fmt.Sprintf("%d.mp4", v.TweetID)
}