Add IsFollowed field on Users

This commit is contained in:
Alessio 2022-02-26 15:58:30 -08:00
parent f9eb986aed
commit 373b9ce16e
5 changed files with 71 additions and 4 deletions

View File

@ -19,6 +19,7 @@ create table users (rowid integer primary key,
banner_image_local_path text,
pinned_tweet_id integer check(typeof(pinned_tweet_id) = 'integer' or pinned_tweet_id = ''),
is_followed boolean default 0,
is_content_downloaded boolean default 0
);

View File

@ -1,6 +1,7 @@
package persistence
import (
"fmt"
"database/sql"
"time"
"offline_twitter/scraper"
@ -78,7 +79,7 @@ func parse_user_from_row(row *sql.Row) (scraper.User, error) {
var u scraper.User
var joinDate 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.IsBanned, &u.ProfileImageUrl, &u.ProfileImageLocalPath, &u.BannerImageUrl, &u.BannerImageLocalPath, &u.PinnedTweetID, &u.IsContentDownloaded)
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.IsBanned, &u.ProfileImageUrl, &u.ProfileImageLocalPath, &u.BannerImageUrl, &u.BannerImageLocalPath, &u.PinnedTweetID, &u.IsContentDownloaded, &u.IsFollowed)
if err != nil {
return u, err
}
@ -101,7 +102,7 @@ func (p Profile) GetUserByHandle(handle scraper.UserHandle) (scraper.User, error
db := p.DB
stmt, err := db.Prepare(`
select id, display_name, handle, bio, following_count, followers_count, location, website, join_date, is_private, is_verified, is_banned, profile_image_url, profile_image_local_path, banner_image_url, banner_image_local_path, pinned_tweet_id, is_content_downloaded
select id, display_name, handle, bio, following_count, followers_count, location, website, join_date, is_private, is_verified, is_banned, profile_image_url, profile_image_local_path, banner_image_url, banner_image_local_path, pinned_tweet_id, is_content_downloaded, is_followed
from users
where lower(handle) = lower(?)
`)
@ -132,7 +133,7 @@ func (p Profile) GetUserByID(id scraper.UserID) (scraper.User, error) {
db := p.DB
stmt, err := db.Prepare(`
select id, display_name, handle, bio, following_count, followers_count, location, website, join_date, is_private, is_verified, is_banned, profile_image_url, profile_image_local_path, banner_image_url, banner_image_local_path, pinned_tweet_id, is_content_downloaded
select id, display_name, handle, bio, following_count, followers_count, location, website, join_date, is_private, is_verified, is_banned, profile_image_url, profile_image_local_path, banner_image_url, banner_image_local_path, pinned_tweet_id, is_content_downloaded, is_followed
from users
where id = ?
`)
@ -189,3 +190,20 @@ func (p Profile) CheckUserContentDownloadNeeded(user scraper.User) bool {
}
return false
}
/**
* Follow / unfollow a user. Update the given User object's IsFollowed field.
*/
func (p Profile) SetUserFollowed(user *scraper.User, is_followed bool) {
result, err := p.DB.Exec("update users set is_followed = ? where id = ?", is_followed, user.ID)
if err != nil {
panic("Unknown error: " + err.Error())
}
if count, _ := result.RowsAffected(); count != 1 {
panic(fmt.Sprintf("User with handle %q not found", user.Handle))
}
if err != nil {
panic(fmt.Sprintf("Error inserting user with handle %q: %s", user.Handle, err.Error()))
}
user.IsFollowed = is_followed
}

View File

@ -4,6 +4,9 @@ import (
"testing"
"time"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"github.com/go-test/deep"
)
@ -205,3 +208,46 @@ func TestCheckUserContentDownloadNeeded(t *testing.T) {
t.Errorf("If banner image changed, user should require another download")
}
}
/**
* Make sure following works
*
* - users are unfollowed by default
* - following a user makes it save as is_followed
* - using regular save method doesn't un-follow
* - unfollowing a user makes it save as no longer is_followed
*/
func TestFollowUnfollowUser(t *testing.T) {
assert := assert.New(t)
profile_path := "test_profiles/TestUserQueries"
profile := create_or_load_profile(profile_path)
user := create_dummy_user()
assert.False(user.IsFollowed)
profile.SaveUser(user)
profile.SetUserFollowed(&user, true)
assert.True(user.IsFollowed)
// Ensure the change was persisted
user_reloaded, err := profile.GetUserByHandle(user.Handle)
require.NoError(t, err)
assert.Equal(user.ID, user_reloaded.ID) // Verify it's the same user
assert.True(user_reloaded.IsFollowed)
profile.SaveUser(user) // should NOT un-set is_followed
user_reloaded, err = profile.GetUserByHandle(user.Handle)
require.NoError(t, err)
assert.Equal(user.ID, user_reloaded.ID) // Verify it's the same user
assert.True(user_reloaded.IsFollowed)
profile.SetUserFollowed(&user, false)
assert.False(user.IsFollowed)
// Ensure the change was persisted
user_reloaded, err = profile.GetUserByHandle(user.Handle)
require.NoError(t, err)
assert.Equal(user.ID, user_reloaded.ID) // Verify it's the same user
assert.False(user_reloaded.IsFollowed)
}

View File

@ -8,7 +8,7 @@ import (
)
const ENGINE_DATABASE_VERSION = 8
const ENGINE_DATABASE_VERSION = 9
type VersionMismatchError struct {
@ -61,6 +61,7 @@ var MIGRATIONS = []string{
`alter table users add column is_banned boolean default 0`,
`alter table urls add column short_text text not null default ""`,
`insert into tombstone_types (rowid, short_name, tombstone_text) values (7, 'age-restricted', 'Age-restricted adult content. This content might not be appropriate for people under 18 years old. To view this media, youll need to log in to Twitter')`,
`alter table users add column is_followed boolean default 0`,
}
/**

View File

@ -44,6 +44,7 @@ type User struct {
PinnedTweetID TweetID
PinnedTweet *Tweet
IsFollowed bool
IsContentDownloaded bool
}