Add parsing of Likes feed
This commit is contained in:
parent
3d7166c4aa
commit
79a4b87f3a
@ -506,6 +506,11 @@ type APIV2Response struct {
|
||||
Data struct {
|
||||
User struct {
|
||||
Result struct {
|
||||
TimelineV2 struct { // "Likes" feed calls this "timeline_v2" for some reason
|
||||
Timeline struct {
|
||||
Instructions []APIV2Instruction `json:"instructions"`
|
||||
} `json:"timeline"`
|
||||
} `json:"timeline_v2"`
|
||||
Timeline struct {
|
||||
Timeline struct {
|
||||
Instructions []APIV2Instruction `json:"instructions"`
|
||||
@ -526,6 +531,12 @@ func (api_response APIV2Response) GetMainInstruction() *APIV2Instruction {
|
||||
return &instructions[i]
|
||||
}
|
||||
}
|
||||
instructions = api_response.Data.User.Result.TimelineV2.Timeline.Instructions
|
||||
for i := range instructions {
|
||||
if instructions[i].Type == "TimelineAddEntries" {
|
||||
return &instructions[i]
|
||||
}
|
||||
}
|
||||
instructions = api_response.Data.ThreadedConversationWithInjectionsV2.Instructions
|
||||
for i := range instructions {
|
||||
if instructions[i].Type == "TimelineAddEntries" {
|
||||
@ -677,6 +688,39 @@ func (api_response APIV2Response) ToTweetTrove() (TweetTrove, error) {
|
||||
return ret, nil // TODO: This doesn't need to return an error, it's always nil
|
||||
}
|
||||
|
||||
func (r APIV2Response) ToTweetTroveAsLikes() (TweetTrove, error) {
|
||||
ret, err := r.ToTweetTrove()
|
||||
if err != nil {
|
||||
return ret, err
|
||||
}
|
||||
|
||||
// Post-process tweets as Likes
|
||||
for _, entry := range r.GetMainInstruction().Entries {
|
||||
// Skip cursors
|
||||
if entry.Content.EntryType == "TimelineTimelineCursor" {
|
||||
continue
|
||||
}
|
||||
// Assume it's not a TimelineModule or a Tombstone
|
||||
if entry.Content.EntryType != "TimelineTimelineItem" {
|
||||
panic(fmt.Sprintf("Unknown Like entry type: %s", entry.Content.EntryType))
|
||||
}
|
||||
if entry.Content.ItemContent.ItemType == "TimelineTombstone" {
|
||||
panic(fmt.Sprintf("Liked tweet is a tombstone: %#v", entry))
|
||||
}
|
||||
|
||||
// Generate a "Like" from the entry
|
||||
tweet, is_ok := ret.Tweets[TweetID(entry.Content.ItemContent.TweetResults.Result._Result.ID)]
|
||||
if !is_ok {
|
||||
panic(entry)
|
||||
}
|
||||
ret.Likes[LikeSortID(entry.SortIndex)] = Like{
|
||||
SortID: LikeSortID(entry.SortIndex),
|
||||
TweetID: tweet.ID,
|
||||
}
|
||||
}
|
||||
return ret, err
|
||||
}
|
||||
|
||||
// Get a User feed using the new GraphQL twitter api
|
||||
func (api *API) GetGraphqlFeedFor(user_id UserID, cursor string) (APIV2Response, error) {
|
||||
url, err := url.Parse(GraphqlURL{
|
||||
|
@ -866,3 +866,23 @@ func TestTweetDetailWithUnjoinedNontombstoneTweet(t *testing.T) {
|
||||
assert.False(t3.IsStub)
|
||||
assert.Equal(t2.ID, t3.InReplyToID)
|
||||
}
|
||||
|
||||
func TestParseResultAsLikes(t *testing.T) {
|
||||
assert := assert.New(t)
|
||||
require := require.New(t)
|
||||
data, err := os.ReadFile("test_responses/api_v2/likes_feed.json")
|
||||
require.NoError(err)
|
||||
var response_result APIV2Response
|
||||
err = json.Unmarshal(data, &response_result)
|
||||
require.NoError(err)
|
||||
|
||||
trove, err := response_result.ToTweetTroveAsLikes()
|
||||
require.NoError(err)
|
||||
|
||||
assert.Len(trove.Retweets, 0)
|
||||
assert.True(len(trove.Likes) == 20)
|
||||
for _, l := range trove.Likes {
|
||||
_, is_ok := trove.Tweets[l.TweetID]
|
||||
assert.True(is_ok, "Like (%#v) didn't have its Tweet in the trove", l)
|
||||
}
|
||||
}
|
||||
|
1
scraper/test_responses/api_v2/likes_feed.json
Normal file
1
scraper/test_responses/api_v2/likes_feed.json
Normal file
File diff suppressed because one or more lines are too long
@ -12,6 +12,7 @@ type TweetTrove struct {
|
||||
Users map[UserID]User
|
||||
Retweets map[TweetID]Retweet
|
||||
Spaces map[SpaceID]Space
|
||||
Likes map[LikeSortID]Like
|
||||
|
||||
TombstoneUsers []UserHandle
|
||||
}
|
||||
@ -22,6 +23,7 @@ func NewTweetTrove() TweetTrove {
|
||||
ret.Users = make(map[UserID]User)
|
||||
ret.Retweets = make(map[TweetID]Retweet)
|
||||
ret.Spaces = make(map[SpaceID]Space)
|
||||
ret.Likes = make(map[LikeSortID]Like)
|
||||
ret.TombstoneUsers = []UserHandle{}
|
||||
return ret
|
||||
}
|
||||
@ -54,6 +56,9 @@ func (t1 *TweetTrove) MergeWith(t2 TweetTrove) {
|
||||
for id, val := range t2.Spaces {
|
||||
t1.Spaces[id] = val
|
||||
}
|
||||
for id, val := range t2.Likes {
|
||||
t1.Likes[id] = val
|
||||
}
|
||||
|
||||
t1.TombstoneUsers = append(t1.TombstoneUsers, t2.TombstoneUsers...)
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user