Implement 'likes sort order' for Likes tab
This commit is contained in:
parent
9aff2b8a93
commit
dc1bde2fe6
@ -155,13 +155,40 @@ func TestUserLikesFeed(t *testing.T) {
|
|||||||
|
|
||||||
// Fetch @Peter_Nimitz user feed while logged in as @MysteryGrove
|
// Fetch @Peter_Nimitz user feed while logged in as @MysteryGrove
|
||||||
c := persistence.NewUserFeedLikesCursor(UserHandle("MysteryGrove"))
|
c := persistence.NewUserFeedLikesCursor(UserHandle("MysteryGrove"))
|
||||||
|
require.Equal(c.SortOrder, persistence.SORT_ORDER_LIKED_AT)
|
||||||
|
c.PageSize = 2
|
||||||
feed, err := profile.NextPage(c, UserID(0))
|
feed, err := profile.NextPage(c, UserID(0))
|
||||||
require.NoError(err)
|
require.NoError(err)
|
||||||
|
|
||||||
// Should have "liked" 1 tweet
|
require.Len(feed.Tweets, 2)
|
||||||
|
for i, expected_tweet_id := range []TweetID{1698765208393576891, 1426669666928414720} {
|
||||||
|
assert.Equal(feed.Items[i].TweetID, expected_tweet_id)
|
||||||
|
_, is_ok := feed.Tweets[expected_tweet_id]
|
||||||
|
assert.True(is_ok)
|
||||||
|
}
|
||||||
|
|
||||||
|
require.Equal(feed.CursorBottom.CursorValue, 4)
|
||||||
|
feed, err = profile.NextPage(feed.CursorBottom, UserID(0))
|
||||||
|
require.NoError(err)
|
||||||
|
|
||||||
|
require.Len(feed.Tweets, 2)
|
||||||
|
for i, expected_tweet_id := range []TweetID{1343633011364016128, 1513313535480287235} {
|
||||||
|
assert.Equal(feed.Items[i].TweetID, expected_tweet_id)
|
||||||
|
_, is_ok := feed.Tweets[expected_tweet_id]
|
||||||
|
assert.True(is_ok)
|
||||||
|
}
|
||||||
|
|
||||||
|
assert.Equal(feed.CursorBottom.CursorValue, 2)
|
||||||
|
feed, err = profile.NextPage(feed.CursorBottom, UserID(0))
|
||||||
|
require.NoError(err)
|
||||||
|
|
||||||
require.Len(feed.Tweets, 1)
|
require.Len(feed.Tweets, 1)
|
||||||
_, is_ok := feed.Tweets[1413646595493568516]
|
for i, expected_tweet_id := range []TweetID{1413646595493568516} {
|
||||||
assert.True(is_ok)
|
assert.Equal(feed.Items[i].TweetID, expected_tweet_id)
|
||||||
|
_, is_ok := feed.Tweets[expected_tweet_id]
|
||||||
|
assert.True(is_ok)
|
||||||
|
}
|
||||||
|
assert.Equal(feed.CursorBottom.CursorPosition, persistence.CURSOR_END)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestTweetDetailWithReplies(t *testing.T) {
|
func TestTweetDetailWithReplies(t *testing.T) {
|
||||||
|
@ -16,6 +16,7 @@ const (
|
|||||||
SORT_ORDER_OLDEST
|
SORT_ORDER_OLDEST
|
||||||
SORT_ORDER_MOST_LIKES
|
SORT_ORDER_MOST_LIKES
|
||||||
SORT_ORDER_MOST_RETWEETS
|
SORT_ORDER_MOST_RETWEETS
|
||||||
|
SORT_ORDER_LIKED_AT
|
||||||
)
|
)
|
||||||
|
|
||||||
func (o SortOrder) OrderByClause() string {
|
func (o SortOrder) OrderByClause() string {
|
||||||
@ -28,6 +29,8 @@ func (o SortOrder) OrderByClause() string {
|
|||||||
return "order by num_likes desc"
|
return "order by num_likes desc"
|
||||||
case SORT_ORDER_MOST_RETWEETS:
|
case SORT_ORDER_MOST_RETWEETS:
|
||||||
return "order by num_retweets desc"
|
return "order by num_retweets desc"
|
||||||
|
case SORT_ORDER_LIKED_AT:
|
||||||
|
return "order by likes_sort_order desc"
|
||||||
default:
|
default:
|
||||||
panic(fmt.Sprintf("Invalid sort order: %d", o))
|
panic(fmt.Sprintf("Invalid sort order: %d", o))
|
||||||
}
|
}
|
||||||
@ -42,6 +45,8 @@ func (o SortOrder) PaginationWhereClause() string {
|
|||||||
return "num_likes < ?"
|
return "num_likes < ?"
|
||||||
case SORT_ORDER_MOST_RETWEETS:
|
case SORT_ORDER_MOST_RETWEETS:
|
||||||
return "num_retweets < ?"
|
return "num_retweets < ?"
|
||||||
|
case SORT_ORDER_LIKED_AT:
|
||||||
|
return "likes_sort_order < ?"
|
||||||
default:
|
default:
|
||||||
panic(fmt.Sprintf("Invalid sort order: %d", o))
|
panic(fmt.Sprintf("Invalid sort order: %d", o))
|
||||||
}
|
}
|
||||||
@ -56,6 +61,8 @@ func (o SortOrder) NextCursorValue(r CursorResult) int {
|
|||||||
return r.NumLikes
|
return r.NumLikes
|
||||||
case SORT_ORDER_MOST_RETWEETS:
|
case SORT_ORDER_MOST_RETWEETS:
|
||||||
return r.NumRetweets
|
return r.NumRetweets
|
||||||
|
case SORT_ORDER_LIKED_AT:
|
||||||
|
return r.LikeSortOrder
|
||||||
default:
|
default:
|
||||||
panic(fmt.Sprintf("Invalid sort order: %d", o))
|
panic(fmt.Sprintf("Invalid sort order: %d", o))
|
||||||
}
|
}
|
||||||
@ -94,8 +101,9 @@ const (
|
|||||||
type CursorResult struct {
|
type CursorResult struct {
|
||||||
scraper.Tweet
|
scraper.Tweet
|
||||||
scraper.Retweet
|
scraper.Retweet
|
||||||
Chrono int `db:"chrono"`
|
Chrono int `db:"chrono"`
|
||||||
ByUserID scraper.UserID `db:"by_user_id"`
|
LikeSortOrder int `db:"likes_sort_order"`
|
||||||
|
ByUserID scraper.UserID `db:"by_user_id"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type Cursor struct {
|
type Cursor struct {
|
||||||
@ -181,7 +189,7 @@ func NewUserFeedLikesCursor(h scraper.UserHandle) Cursor {
|
|||||||
UntilTimestamp: scraper.TimestampFromUnix(0),
|
UntilTimestamp: scraper.TimestampFromUnix(0),
|
||||||
CursorPosition: CURSOR_START,
|
CursorPosition: CURSOR_START,
|
||||||
CursorValue: 0,
|
CursorValue: 0,
|
||||||
SortOrder: SORT_ORDER_NEWEST,
|
SortOrder: SORT_ORDER_LIKED_AT,
|
||||||
PageSize: 50,
|
PageSize: 50,
|
||||||
|
|
||||||
LikedByUserHandle: h,
|
LikedByUserHandle: h,
|
||||||
@ -255,6 +263,8 @@ func (c *Cursor) apply_token(token string) error {
|
|||||||
c.ToUserHandles = append(c.ToUserHandles, scraper.UserHandle(parts[1]))
|
c.ToUserHandles = append(c.ToUserHandles, scraper.UserHandle(parts[1]))
|
||||||
case "retweeted_by":
|
case "retweeted_by":
|
||||||
c.RetweetedByUserHandle = scraper.UserHandle(parts[1])
|
c.RetweetedByUserHandle = scraper.UserHandle(parts[1])
|
||||||
|
case "liked_by":
|
||||||
|
c.LikedByUserHandle = scraper.UserHandle(parts[1])
|
||||||
case "since":
|
case "since":
|
||||||
c.SinceTimestamp.Time, err = time.Parse("2006-01-02", parts[1])
|
c.SinceTimestamp.Time, err = time.Parse("2006-01-02", parts[1])
|
||||||
case "until":
|
case "until":
|
||||||
@ -396,10 +406,16 @@ func (p Profile) NextPage(c Cursor, current_user_id scraper.UserID) (Feed, error
|
|||||||
}
|
}
|
||||||
|
|
||||||
liked_by_filter_join_clause := ""
|
liked_by_filter_join_clause := ""
|
||||||
|
likes_sort_order_field := ""
|
||||||
if c.LikedByUserHandle != "" {
|
if c.LikedByUserHandle != "" {
|
||||||
liked_by_filter_join_clause = " join likes filter_likes on tweets.id = filter_likes.tweet_id "
|
liked_by_filter_join_clause = " join likes filter_likes on tweets.id = filter_likes.tweet_id "
|
||||||
where_clauses = append(where_clauses, "filter_likes.user_id = (select id from users where handle like ?) ")
|
where_clauses = append(where_clauses, "filter_likes.user_id = (select id from users where handle like ?) ")
|
||||||
bind_values = append(bind_values, c.LikedByUserHandle)
|
bind_values = append(bind_values, c.LikedByUserHandle)
|
||||||
|
likes_sort_order_field = ", coalesce(filter_likes.sort_order, -1) likes_sort_order "
|
||||||
|
|
||||||
|
// Don't include retweets on "liked by" searches because it doesn't distinguish which retweet
|
||||||
|
// version was the "liked" one
|
||||||
|
where_clauses = append(where_clauses, "retweet_id = 0")
|
||||||
}
|
}
|
||||||
|
|
||||||
// Pagination
|
// Pagination
|
||||||
@ -414,7 +430,7 @@ func (p Profile) NextPage(c Cursor, current_user_id scraper.UserID) (Feed, error
|
|||||||
}
|
}
|
||||||
|
|
||||||
q := `select * from (
|
q := `select * from (
|
||||||
select ` + TWEETS_ALL_SQL_FIELDS + `,
|
select ` + TWEETS_ALL_SQL_FIELDS + likes_sort_order_field + `,
|
||||||
0 tweet_id, 0 retweet_id, 0 retweeted_by, 0 retweeted_at,
|
0 tweet_id, 0 retweet_id, 0 retweeted_by, 0 retweeted_at,
|
||||||
posted_at chrono, tweets.user_id by_user_id
|
posted_at chrono, tweets.user_id by_user_id
|
||||||
from tweets
|
from tweets
|
||||||
@ -427,7 +443,7 @@ func (p Profile) NextPage(c Cursor, current_user_id scraper.UserID) (Feed, error
|
|||||||
union
|
union
|
||||||
|
|
||||||
select * from (
|
select * from (
|
||||||
select ` + TWEETS_ALL_SQL_FIELDS + `,
|
select ` + TWEETS_ALL_SQL_FIELDS + likes_sort_order_field + `,
|
||||||
retweets.tweet_id, retweet_id, retweeted_by, retweeted_at,
|
retweets.tweet_id, retweet_id, retweeted_by, retweeted_at,
|
||||||
retweeted_at chrono, retweeted_by by_user_id
|
retweeted_at chrono, retweeted_by by_user_id
|
||||||
from retweets
|
from retweets
|
||||||
|
@ -190,10 +190,6 @@ create table hashtags (rowid integer primary key,
|
|||||||
foreign key(tweet_id) references tweets(id)
|
foreign key(tweet_id) references tweets(id)
|
||||||
);
|
);
|
||||||
|
|
||||||
create table database_version(rowid integer primary key,
|
|
||||||
version_number integer not null unique
|
|
||||||
);
|
|
||||||
|
|
||||||
create table likes(rowid integer primary key,
|
create table likes(rowid integer primary key,
|
||||||
sort_order integer unique not null,
|
sort_order integer unique not null,
|
||||||
user_id integer not null,
|
user_id integer not null,
|
||||||
@ -202,6 +198,12 @@ create table likes(rowid integer primary key,
|
|||||||
foreign key(user_id) references users(id)
|
foreign key(user_id) references users(id)
|
||||||
foreign key(tweet_id) references tweets(id)
|
foreign key(tweet_id) references tweets(id)
|
||||||
);
|
);
|
||||||
|
create index if not exists index_likes_user_id on likes (user_id);
|
||||||
|
create index if not exists index_likes_tweet_id on likes (tweet_id);
|
||||||
|
|
||||||
create table fake_user_sequence(latest_fake_id integer not null);
|
create table fake_user_sequence(latest_fake_id integer not null);
|
||||||
insert into fake_user_sequence values(0x4000000000000000);
|
insert into fake_user_sequence values(0x4000000000000000);
|
||||||
|
|
||||||
|
create table database_version(rowid integer primary key,
|
||||||
|
version_number integer not null unique
|
||||||
|
);
|
||||||
|
@ -307,6 +307,11 @@ create table likes(rowid integer primary key,
|
|||||||
foreign key(tweet_id) references tweets(id)
|
foreign key(tweet_id) references tweets(id)
|
||||||
);
|
);
|
||||||
insert into likes values(1, 1, 1178839081222115328, 1413646595493568516);
|
insert into likes values(1, 1, 1178839081222115328, 1413646595493568516);
|
||||||
|
insert into likes values(2, 2, 1178839081222115328, 1513313535480287235);
|
||||||
|
insert into likes values(3, 3, 1178839081222115328, 1343633011364016128);
|
||||||
|
insert into likes values(4, 4, 1178839081222115328, 1426669666928414720);
|
||||||
|
insert into likes values(5, 5, 1178839081222115328, 1698765208393576891);
|
||||||
|
|
||||||
|
|
||||||
create table fake_user_sequence(latest_fake_id integer not null);
|
create table fake_user_sequence(latest_fake_id integer not null);
|
||||||
insert into fake_user_sequence values(0x4000000000000000);
|
insert into fake_user_sequence values(0x4000000000000000);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user