Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
ALTER TABLE settings ADD COLUMN news_rss_enabled BOOLEAN DEFAULT TRUE;
6 changes: 4 additions & 2 deletions internal/newsfeed/new_feed_manager_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -149,13 +149,15 @@ func (s *NewsFeedManagerSuite) TestStartAndStopFetching() {
ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
defer cancel()

newsFeedManager.StartFetching(ctx)
newsFeedManager.StartPolling(ctx)

time.Sleep(1 * time.Millisecond) // Leave time for the go routine to run and process

// The start fetching does an initial fetch immediately
s.Require().Len(captured, 1)
s.Require().Equal("New Item", captured[0].Title)
s.Require().True(newsFeedManager.IsPolling())

newsFeedManager.StopFetching()
newsFeedManager.StopPolling()
s.Require().False(newsFeedManager.IsPolling())
}
19 changes: 17 additions & 2 deletions internal/newsfeed/news_feed_manager.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ type NewsFeedManager struct {
handler FeedHandler
fetchFrom time.Time
pollingInterval time.Duration
polling bool
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we even need the manager, if we're not polling? 🤔

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I thought it would be simpler to start the polling (when the setting is set back up) if the manager is already set up.
Same thing for stopping it.

It just seems like more complex to delete and initialize the whole manager than just stopping the polling.

cancel context.CancelFunc
logger *zap.Logger
}
Expand Down Expand Up @@ -73,6 +74,7 @@ func NewNewsFeedManager(opts ...Option) *NewsFeedManager {
nfm := &NewsFeedManager{
pollingInterval: time.Minute * 30,
fetchFrom: time.Now(),
polling: false,
}

for _, opt := range opts {
Expand Down Expand Up @@ -122,7 +124,16 @@ func (n *NewsFeedManager) fetchRSSAndHandle() error {
return nil
}

func (n *NewsFeedManager) StartFetching(ctx context.Context) {
func (n *NewsFeedManager) IsPolling() bool {
return n.polling
}

func (n *NewsFeedManager) StartPolling(ctx context.Context) {
if n.polling {
return
}
n.polling = true

// Derive the given context, save the CancelFunc
ctx, n.cancel = context.WithCancel(ctx)

Expand All @@ -145,6 +156,10 @@ func (n *NewsFeedManager) StartFetching(ctx context.Context) {
}()
}

func (n *NewsFeedManager) StopFetching() {
func (n *NewsFeedManager) StopPolling() {
if !n.polling {
return
}
n.cancel()
n.polling = false
}
6 changes: 6 additions & 0 deletions multiaccounts/settings/columns.go
Original file line number Diff line number Diff line change
Expand Up @@ -242,6 +242,11 @@ var (
dBColumnName: "news_notifications_enabled",
valueHandler: BoolHandler,
}
NewsRSSEnabled = SettingField{
reactFieldName: "news-rss-enabled?",
dBColumnName: "news_rss_enabled",
valueHandler: BoolHandler,
}
NodeConfig = SettingField{
reactFieldName: "node-config",
dBColumnName: "node_config",
Expand Down Expand Up @@ -582,6 +587,7 @@ var (
NewsFeedEnabled,
NewsFeedLastFetchedTimestamp,
NewsNotificationsEnabled,
NewsRSSEnabled,
MessengerNotificationsEnabled,
NodeConfig,
NotificationsEnabled,
Expand Down
27 changes: 26 additions & 1 deletion multiaccounts/settings/database.go
Original file line number Diff line number Diff line change
Expand Up @@ -396,7 +396,7 @@ func (db *Database) GetSettings() (Settings, error) {
test_networks_enabled, mutual_contact_enabled, profile_migration_needed, wallet_token_preferences_group_by_community, url_unfurling_mode,
mnemonic_was_not_shown, wallet_show_community_asset_when_sending_tokens, wallet_display_assets_below_balance,
wallet_display_assets_below_balance_threshold, wallet_collectible_preferences_group_by_collection, wallet_collectible_preferences_group_by_community,
peer_syncing_enabled, auto_refresh_tokens_enabled, last_tokens_update, news_feed_enabled, news_feed_last_fetched_timestamp
peer_syncing_enabled, auto_refresh_tokens_enabled, last_tokens_update, news_feed_enabled, news_feed_last_fetched_timestamp, news_rss_enabled
FROM
settings
WHERE
Expand Down Expand Up @@ -485,6 +485,7 @@ func (db *Database) GetSettings() (Settings, error) {
&lastTokensUpdate,
&s.NewsFeedEnabled,
&newsFeedLastFetchedTimestamp,
&s.NewsRSSEnabled,
)

if err != nil {
Expand Down Expand Up @@ -902,3 +903,27 @@ func (db *Database) NewsFeedLastFetchedTimestamp() (result time.Time, err error)
}
return
}

func (db *Database) NewsFeedEnabled() (result bool, err error) {
err = db.makeSelectRow(NewsFeedEnabled).Scan(&result)
if err == sql.ErrNoRows {
return result, nil
}
return result, err
}

func (db *Database) NewsNotificationsEnabled() (result bool, err error) {
err = db.makeSelectRow(NewsNotificationsEnabled).Scan(&result)
if err == sql.ErrNoRows {
return result, nil
}
return result, err
}

func (db *Database) NewsRSSEnabled() (result bool, err error) {
err = db.makeSelectRow(NewsRSSEnabled).Scan(&result)
if err == sql.ErrNoRows {
return result, nil
}
return result, err
}
3 changes: 3 additions & 0 deletions multiaccounts/settings/database_settings_manager.go
Original file line number Diff line number Diff line change
Expand Up @@ -84,4 +84,7 @@ type DatabaseSettingsManager interface {
AutoRefreshTokensEnabled() (result bool, err error)
LastTokensUpdate() (result time.Time, err error)
NewsFeedLastFetchedTimestamp() (result time.Time, err error)
NewsFeedEnabled() (result bool, err error)
NewsNotificationsEnabled() (result bool, err error)
NewsRSSEnabled() (result bool, err error)
}
31 changes: 25 additions & 6 deletions multiaccounts/settings/database_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ var (
DisplayAssetsBelowBalance: false,
ShowCommunityAssetWhenSendingTokens: true,
NewsFeedEnabled: true,
NewsRSSEnabled: true,
}
)

Expand Down Expand Up @@ -208,9 +209,9 @@ func TestDatabase_NewsNotificationsEnabled(t *testing.T) {

require.NoError(t, db.CreateSettings(settings, config))

settings, err := db.GetSettings()
enabled, err := db.NewsNotificationsEnabled()
require.NoError(t, err)
require.Equal(t, false, settings.NewsNotificationsEnabled)
require.Equal(t, false, enabled)

err = db.SaveSetting(NewsNotificationsEnabled.GetReactName(), true)
require.NoError(t, err)
Expand Down Expand Up @@ -244,10 +245,10 @@ func TestDatabase_NewsFeedEnabled(t *testing.T) {

require.NoError(t, db.CreateSettings(settings, config))

settings, err := db.GetSettings()
enabled, err := db.NewsFeedEnabled()
require.NoError(t, err)

require.Equal(t, true, settings.NewsFeedEnabled)
require.Equal(t, true, enabled)

err = db.SaveSetting(NewsFeedEnabled.GetReactName(), false)
require.NoError(t, err)
Expand All @@ -263,11 +264,11 @@ func TestDatabase_NewsFeedLastFetchedTimestamp(t *testing.T) {

require.NoError(t, db.CreateSettings(settings, config))

settings, err := db.GetSettings()
timestamp, err := db.NewsFeedLastFetchedTimestamp()
require.NoError(t, err)

// Using GreaterOrEqual because the timestamp is set during CreateSettings and there is a tiny chance that the second changes between
require.GreaterOrEqual(t, time.Now().UTC().Second(), settings.NewsFeedLastFetchedTimestamp.UTC().Second())
require.GreaterOrEqual(t, time.Now().UTC().Second(), timestamp.UTC().Second())

dateNow := time.Now()
err = db.SaveSetting(NewsFeedLastFetchedTimestamp.GetReactName(), dateNow)
Expand All @@ -277,3 +278,21 @@ func TestDatabase_NewsFeedLastFetchedTimestamp(t *testing.T) {
require.NoError(t, err)
require.Equal(t, dateNow.UTC().Second(), settings.NewsFeedLastFetchedTimestamp.UTC().Second())
}

func TestDatabase_NewsRSSEnabled(t *testing.T) {
db, stop := setupTestDB(t)
defer stop()

require.NoError(t, db.CreateSettings(settings, config))

enabled, err := db.NewsRSSEnabled()
require.NoError(t, err)
require.Equal(t, true, enabled)

err = db.SaveSetting(NewsRSSEnabled.GetReactName(), false)
require.NoError(t, err)

settings, err = db.GetSettings()
require.NoError(t, err)
require.Equal(t, false, settings.NewsRSSEnabled)
}
1 change: 1 addition & 0 deletions multiaccounts/settings/structs.go
Original file line number Diff line number Diff line change
Expand Up @@ -161,6 +161,7 @@ type Settings struct {
NewsFeedEnabled bool `json:"news-feed-enabled?,omitempty"`
NewsFeedLastFetchedTimestamp time.Time `json:"news-feed-last-fetched-timestamp,omitempty"`
NewsNotificationsEnabled bool `json:"news-notifications-enabled?,omitempty"`
NewsRSSEnabled bool `json:"news-rss-enabled?,omitempty"`
PhotoPath string `json:"photo-path"`
PinnedMailserver *json.RawMessage `json:"pinned-mailservers,omitempty"`
// PreferredName represents the user's preferred Ethereum Name Service (ENS) name.
Expand Down
9 changes: 7 additions & 2 deletions protocol/messenger.go
Original file line number Diff line number Diff line change
Expand Up @@ -912,8 +912,13 @@ func (m *Messenger) Start() (*MessengerResponse, error) {
newsfeed.WithFetchFrom(lastFetched),
)

// TODO only start if the setting is enabled
m.newsFeedManager.StartFetching(m.ctx)
newsFeedEnabled, err := m.IsNewsFeedEnabled()
if err != nil {
return nil, err
}
if newsFeedEnabled {
m.newsFeedManager.StartPolling(m.ctx)
}
}

return response, nil
Expand Down
51 changes: 51 additions & 0 deletions protocol/messenger_news_feed.go
Original file line number Diff line number Diff line change
Expand Up @@ -91,3 +91,54 @@ func (m *Messenger) FetchNewsMessages() (*MessengerResponse, error) {
}
return response, nil
}

// The News Feed is enabled if both:
// 1. The News Feed is enabled in the settings.
// 2. The RSS feed is enabled in the settings.
func (m *Messenger) IsNewsFeedEnabled() (bool, error) {
newsFeedEnabled, err := m.settings.NewsFeedEnabled()
if err != nil {
return false, err
}
if !newsFeedEnabled {
return false, nil
}
newsRSSEnabled, err := m.settings.NewsRSSEnabled()
if err != nil {
return false, err
}
return newsRSSEnabled, nil
}

func (m *Messenger) changeNewsFeedManagerAfterUpdate() error {
if m.newsFeedManager == nil {
return nil
}
isNewsFeedEnabled, err := m.IsNewsFeedEnabled()
if err != nil {
return err
}

if isNewsFeedEnabled {
m.newsFeedManager.StartPolling(m.ctx)
} else {
m.newsFeedManager.StopPolling()
}
return nil
}

func (m *Messenger) ToggleNewsFeedEnabled(value bool) error {
err := m.settings.SaveSetting(settings.NewsFeedEnabled.GetReactName(), value)
if err != nil {
return err
}
return m.changeNewsFeedManagerAfterUpdate()
}

func (m *Messenger) ToggleNewsRSSEnabled(value bool) error {
err := m.settings.SaveSetting(settings.NewsRSSEnabled.GetReactName(), value)
if err != nil {
return err
}
return m.changeNewsFeedManagerAfterUpdate()
}
41 changes: 39 additions & 2 deletions protocol/messenger_news_feed_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,11 @@ import (
"testing"
"time"

"github.com/stretchr/testify/suite"

"github.com/brianvoe/gofakeit/v6"
"github.com/mmcdole/gofeed"
"github.com/stretchr/testify/suite"

"github.com/status-im/status-go/internal/newsfeed"
)

type MessengerNewsFeedSuite struct {
Expand All @@ -19,6 +20,14 @@ func (s *MessengerNewsFeedSuite) SetupTest() {
s.MessengerBaseTestSuite.SetupTest()

s.m = s.newMessenger()
s.m.newsFeedManager = newsfeed.NewNewsFeedManager(
newsfeed.WithURL(newsfeed.STATUS_FEED_URL),
newsfeed.WithParser(gofeed.NewParser()),
newsfeed.WithHandler(s.m),
newsfeed.WithLogger(s.m.logger),
newsfeed.WithPollingInterval(30*time.Minute),
newsfeed.WithFetchFrom(time.Now().Add(-1*time.Hour)),
)
}

func TestMessengerNewsFeedSuite(t *testing.T) {
Expand Down Expand Up @@ -55,3 +64,31 @@ func (s *MessengerNewsFeedSuite) TestHandleNewsFeedItem() {
s.Require().Len(notifications, 1)
s.Require().Equal(item.Title, notifications[0].NewsTitle)
}

func (s *MessengerNewsFeedSuite) TestToggleSettings() {
err := s.m.ToggleNewsFeedEnabled(true)
s.Require().NoError(err)
s.Require().True(s.m.newsFeedManager.IsPolling())

// Polling is off as soon as one setting is off
err = s.m.ToggleNewsFeedEnabled(false)
s.Require().NoError(err)
s.Require().False(s.m.newsFeedManager.IsPolling())

err = s.m.ToggleNewsRSSEnabled(false)
s.Require().NoError(err)
s.Require().False(s.m.newsFeedManager.IsPolling())

//Poolling is still off
err = s.m.ToggleNewsRSSEnabled(true)
s.Require().NoError(err)
s.Require().False(s.m.newsFeedManager.IsPolling())

// Polling restart if both settings are on
err = s.m.ToggleNewsFeedEnabled(true)
s.Require().NoError(err)
s.Require().True(s.m.newsFeedManager.IsPolling())

s.m.newsFeedManager.StopPolling()
s.Require().False(s.m.newsFeedManager.IsPolling())
}
13 changes: 13 additions & 0 deletions services/accounts/settings.go
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,19 @@ func (api *SettingsAPI) SaveNodeConfig(ctx context.Context, n *params.NodeConfig
return nodecfg.SaveNodeConfig(api.db.DB(), n)
}

// News Settings
func (api *SettingsAPI) NewsFeedEnabled() (bool, error) {
return api.db.NewsFeedEnabled()
}

func (api *SettingsAPI) NewsNotificationsEnabled() (bool, error) {
return api.db.NewsNotificationsEnabled()
}

func (api *SettingsAPI) NewsRSSEnabled() (bool, error) {
return api.db.NewsRSSEnabled()
}

// Notifications Settings
func (api *SettingsAPI) NotificationsGetAllowNotifications() (bool, error) {
return api.db.GetAllowNotifications()
Expand Down
10 changes: 10 additions & 0 deletions services/ext/api.go
Original file line number Diff line number Diff line change
Expand Up @@ -1362,6 +1362,16 @@ func (api *PublicAPI) FetchNewsMessages() (*protocol.MessengerResponse, error) {
return m.FetchNewsMessages()
}

func (api *PublicAPI) ToggleNewsFeedEnabled(value bool) error {
m := api.service.messenger
return m.ToggleNewsFeedEnabled(value)
}

func (api *PublicAPI) ToggleNewsRSSEnabled(value bool) error {
m := api.service.messenger
return m.ToggleNewsRSSEnabled(value)
}

func (api *PublicAPI) RequestAllHistoricMessages(forceFetchingBackup bool) (*protocol.MessengerResponse, error) {
return api.service.messenger.RequestAllHistoricMessages(forceFetchingBackup, false)
}
Expand Down