Implement 'likes sort order' for Likes tab

This commit is contained in:
Alessio 2023-10-12 15:34:24 -03:00
parent 9aff2b8a93
commit dc1bde2fe6
4 changed files with 62 additions and 12 deletions

View File

@ -155,13 +155,40 @@ func TestUserLikesFeed(t *testing.T) {
// Fetch @Peter_Nimitz user feed while logged in as @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))
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)
_, is_ok := feed.Tweets[1413646595493568516]
assert.True(is_ok)
for i, expected_tweet_id := range []TweetID{1413646595493568516} {
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) {

View File

@ -16,6 +16,7 @@ const (
SORT_ORDER_OLDEST
SORT_ORDER_MOST_LIKES
SORT_ORDER_MOST_RETWEETS
SORT_ORDER_LIKED_AT
)
func (o SortOrder) OrderByClause() string {
@ -28,6 +29,8 @@ func (o SortOrder) OrderByClause() string {
return "order by num_likes desc"
case SORT_ORDER_MOST_RETWEETS:
return "order by num_retweets desc"
case SORT_ORDER_LIKED_AT:
return "order by likes_sort_order desc"
default:
panic(fmt.Sprintf("Invalid sort order: %d", o))
}
@ -42,6 +45,8 @@ func (o SortOrder) PaginationWhereClause() string {
return "num_likes < ?"
case SORT_ORDER_MOST_RETWEETS:
return "num_retweets < ?"
case SORT_ORDER_LIKED_AT:
return "likes_sort_order < ?"
default:
panic(fmt.Sprintf("Invalid sort order: %d", o))
}
@ -56,6 +61,8 @@ func (o SortOrder) NextCursorValue(r CursorResult) int {
return r.NumLikes
case SORT_ORDER_MOST_RETWEETS:
return r.NumRetweets
case SORT_ORDER_LIKED_AT:
return r.LikeSortOrder
default:
panic(fmt.Sprintf("Invalid sort order: %d", o))
}
@ -94,8 +101,9 @@ const (
type CursorResult struct {
scraper.Tweet
scraper.Retweet
Chrono int `db:"chrono"`
ByUserID scraper.UserID `db:"by_user_id"`
Chrono int `db:"chrono"`
LikeSortOrder int `db:"likes_sort_order"`
ByUserID scraper.UserID `db:"by_user_id"`
}
type Cursor struct {
@ -181,7 +189,7 @@ func NewUserFeedLikesCursor(h scraper.UserHandle) Cursor {
UntilTimestamp: scraper.TimestampFromUnix(0),
CursorPosition: CURSOR_START,
CursorValue: 0,
SortOrder: SORT_ORDER_NEWEST,
SortOrder: SORT_ORDER_LIKED_AT,
PageSize: 50,
LikedByUserHandle: h,
@ -255,6 +263,8 @@ func (c *Cursor) apply_token(token string) error {
c.ToUserHandles = append(c.ToUserHandles, scraper.UserHandle(parts[1]))
case "retweeted_by":
c.RetweetedByUserHandle = scraper.UserHandle(parts[1])
case "liked_by":
c.LikedByUserHandle = scraper.UserHandle(parts[1])
case "since":
c.SinceTimestamp.Time, err = time.Parse("2006-01-02", parts[1])
case "until":
@ -396,10 +406,16 @@ func (p Profile) NextPage(c Cursor, current_user_id scraper.UserID) (Feed, error
}
liked_by_filter_join_clause := ""
likes_sort_order_field := ""
if c.LikedByUserHandle != "" {
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 ?) ")
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
@ -414,7 +430,7 @@ func (p Profile) NextPage(c Cursor, current_user_id scraper.UserID) (Feed, error
}
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,
posted_at chrono, tweets.user_id by_user_id
from tweets
@ -427,7 +443,7 @@ func (p Profile) NextPage(c Cursor, current_user_id scraper.UserID) (Feed, error
union
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,
retweeted_at chrono, retweeted_by by_user_id
from retweets

View File

@ -190,10 +190,6 @@ create table hashtags (rowid integer primary key,
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,
sort_order integer unique 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(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);
insert into fake_user_sequence values(0x4000000000000000);
create table database_version(rowid integer primary key,
version_number integer not null unique
);

View File

@ -307,6 +307,11 @@ create table likes(rowid integer primary key,
foreign key(tweet_id) references tweets(id)
);
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);
insert into fake_user_sequence values(0x4000000000000000);