Skip to content

Commit 7f81efb

Browse files
authored
feat(news)_: add NewsFeedLastFetchedTimestamp setting and hook it (#6534)
Fixes #6496
1 parent a8f2ec8 commit 7f81efb

10 files changed

+104
-27
lines changed
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
ALTER TABLE settings ADD COLUMN news_feed_last_fetched_timestamp TIMESTAMP;
2+
UPDATE settings SET news_feed_last_fetched_timestamp = CURRENT_TIMESTAMP WHERE news_feed_last_fetched_timestamp IS NULL;

internal/newsfeed/news_feed_manager.go

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -96,8 +96,10 @@ func (n *NewsFeedManager) FetchRSS() ([]*gofeed.Item, error) {
9696
}
9797
}
9898

99-
// Update fetchFrom to now
100-
n.fetchFrom = time.Now()
99+
if len(filteredItems) > 0 {
100+
// Update fetchFrom to now since we have new items
101+
n.fetchFrom = time.Now()
102+
}
101103

102104
return filteredItems, nil
103105
}

multiaccounts/settings/columns.go

Lines changed: 17 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -227,6 +227,21 @@ var (
227227
dBColumnName: "networks",
228228
valueHandler: JSONBlobHandler,
229229
}
230+
NewsFeedEnabled = SettingField{
231+
reactFieldName: "news-feed-enabled?",
232+
dBColumnName: "news_feed_enabled",
233+
valueHandler: BoolHandler,
234+
}
235+
NewsFeedLastFetchedTimestamp = SettingField{
236+
reactFieldName: "news-feed-last-fetched-timestamp",
237+
dBColumnName: "news_feed_last_fetched_timestamp",
238+
valueHandler: TimeHandler,
239+
}
240+
NewsNotificationsEnabled = SettingField{
241+
reactFieldName: "news-notifications-enabled?",
242+
dBColumnName: "news_notifications_enabled",
243+
valueHandler: BoolHandler,
244+
}
230245
NodeConfig = SettingField{
231246
reactFieldName: "node-config",
232247
dBColumnName: "node_config",
@@ -324,11 +339,6 @@ var (
324339
dBColumnName: "remote_push_notifications_enabled",
325340
valueHandler: BoolHandler,
326341
}
327-
NewsNotificationsEnabled = SettingField{
328-
reactFieldName: "news-notifications-enabled?",
329-
dBColumnName: "news_notifications_enabled",
330-
valueHandler: BoolHandler,
331-
}
332342
MessengerNotificationsEnabled = SettingField{
333343
reactFieldName: "messenger-notifications-enabled?",
334344
dBColumnName: "messenger_notifications_enabled",
@@ -527,11 +537,6 @@ var (
527537
dBColumnName: "last_tokens_update",
528538
valueHandler: TimeHandler,
529539
}
530-
NewsFeedEnabled = SettingField{
531-
reactFieldName: "news-feed-enabled?",
532-
dBColumnName: "news_feed_enabled",
533-
valueHandler: BoolHandler,
534-
}
535540
SettingFieldRegister = []SettingField{
536541
AnonMetricsShouldSend,
537542
Appearance,
@@ -574,6 +579,8 @@ var (
574579
Name,
575580
NetworksCurrentNetwork,
576581
NetworksNetworks,
582+
NewsFeedEnabled,
583+
NewsFeedLastFetchedTimestamp,
577584
NewsNotificationsEnabled,
578585
MessengerNotificationsEnabled,
579586
NodeConfig,
@@ -612,7 +619,6 @@ var (
612619
WebviewAllowPermissionRequests,
613620
AutoRefreshTokensEnabled,
614621
LastTokensUpdate,
615-
NewsFeedEnabled,
616622
}
617623
)
618624

multiaccounts/settings/database.go

Lines changed: 26 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -147,10 +147,11 @@ INSERT INTO settings (
147147
wallet_collectible_preferences_group_by_community,
148148
test_networks_enabled,
149149
fleet,
150-
auto_refresh_tokens_enabled
150+
auto_refresh_tokens_enabled,
151+
news_feed_last_fetched_timestamp
151152
) VALUES (
152153
?,?,?,?,?,?,?,?,?,?,?,?,?,?,
153-
?,?,?,?,?,?,?,?,?,'id',?,?,?,?,?,?,?,?,?,?,?)`,
154+
?,?,?,?,?,?,?,?,?,'id',?,?,?,?,?,?,?,?,?,?,?,?)`,
154155
s.Address,
155156
s.Currency,
156157
s.CurrentNetwork,
@@ -185,6 +186,8 @@ INSERT INTO settings (
185186
s.TestNetworksEnabled,
186187
s.Fleet,
187188
s.AutoRefreshTokensEnabled,
189+
// Default the news feed last fetched timestamp to now
190+
time.Now().Unix(),
188191
)
189192
if err != nil {
190193
return err
@@ -372,8 +375,9 @@ func (db *Database) SetSettingLastSynced(setting SettingField, clock uint64) err
372375

373376
func (db *Database) GetSettings() (Settings, error) {
374377
var (
375-
s Settings
376-
lastTokensUpdate sql.NullTime
378+
s Settings
379+
lastTokensUpdate sql.NullTime
380+
newsFeedLastFetchedTimestamp sql.NullTime
377381
)
378382
err := db.db.QueryRow(`
379383
SELECT
@@ -392,7 +396,7 @@ func (db *Database) GetSettings() (Settings, error) {
392396
test_networks_enabled, mutual_contact_enabled, profile_migration_needed, wallet_token_preferences_group_by_community, url_unfurling_mode,
393397
mnemonic_was_not_shown, wallet_show_community_asset_when_sending_tokens, wallet_display_assets_below_balance,
394398
wallet_display_assets_below_balance_threshold, wallet_collectible_preferences_group_by_collection, wallet_collectible_preferences_group_by_community,
395-
peer_syncing_enabled, auto_refresh_tokens_enabled, last_tokens_update, news_feed_enabled
399+
peer_syncing_enabled, auto_refresh_tokens_enabled, last_tokens_update, news_feed_enabled, news_feed_last_fetched_timestamp
396400
FROM
397401
settings
398402
WHERE
@@ -480,6 +484,7 @@ func (db *Database) GetSettings() (Settings, error) {
480484
&s.AutoRefreshTokensEnabled,
481485
&lastTokensUpdate,
482486
&s.NewsFeedEnabled,
487+
&newsFeedLastFetchedTimestamp,
483488
)
484489

485490
if err != nil {
@@ -490,6 +495,10 @@ func (db *Database) GetSettings() (Settings, error) {
490495
s.LastTokensUpdate = lastTokensUpdate.Time
491496
}
492497

498+
if newsFeedLastFetchedTimestamp.Valid {
499+
s.NewsFeedLastFetchedTimestamp = newsFeedLastFetchedTimestamp.Time
500+
}
501+
493502
return s, err
494503
}
495504

@@ -881,3 +890,15 @@ func (db *Database) LastTokensUpdate() (result time.Time, err error) {
881890
}
882891
return
883892
}
893+
894+
func (db *Database) NewsFeedLastFetchedTimestamp() (result time.Time, err error) {
895+
var newsFeedLastFetchedTimestamp sql.NullTime
896+
err = db.makeSelectRow(NewsFeedLastFetchedTimestamp).Scan(&newsFeedLastFetchedTimestamp)
897+
if err == sql.ErrNoRows {
898+
return result, nil
899+
}
900+
if newsFeedLastFetchedTimestamp.Valid {
901+
result = newsFeedLastFetchedTimestamp.Time
902+
}
903+
return
904+
}

multiaccounts/settings/database_settings_manager.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -83,4 +83,5 @@ type DatabaseSettingsManager interface {
8383
GetPeerSyncingEnabled() (result bool, err error)
8484
AutoRefreshTokensEnabled() (result bool, err error)
8585
LastTokensUpdate() (result time.Time, err error)
86+
NewsFeedLastFetchedTimestamp() (result time.Time, err error)
8687
}

multiaccounts/settings/database_test.go

Lines changed: 27 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import (
44
"encoding/json"
55
"os"
66
"testing"
7+
"time"
78

89
"github.com/stretchr/testify/require"
910

@@ -48,7 +49,8 @@ var (
4849
DisplayAssetsBelowBalanceThreshold: int64(100000000),
4950
DisplayAssetsBelowBalance: false,
5051
ShowCommunityAssetWhenSendingTokens: true,
51-
NewsFeedEnabled: true}
52+
NewsFeedEnabled: true,
53+
}
5254
)
5355

5456
func setupTestDB(t *testing.T) (*Database, func()) {
@@ -130,6 +132,9 @@ func TestCreateSettings(t *testing.T) {
130132

131133
s, err := db.GetSettings()
132134
require.NoError(t, err)
135+
require.NotEqual(t, 0, s.NewsFeedLastFetchedTimestamp.UTC().Second())
136+
// Reset the timestamp to 0 as it is set during CreateSettings as time.now and it's impossible to test reliably
137+
s.NewsFeedLastFetchedTimestamp = time.Time{}
133138
require.Equal(t, settings, s)
134139
}
135140

@@ -251,3 +256,24 @@ func TestDatabase_NewsFeedEnabled(t *testing.T) {
251256
require.NoError(t, err)
252257
require.Equal(t, false, settings.NewsFeedEnabled)
253258
}
259+
260+
func TestDatabase_NewsFeedLastFetchedTimestamp(t *testing.T) {
261+
db, stop := setupTestDB(t)
262+
defer stop()
263+
264+
require.NoError(t, db.CreateSettings(settings, config))
265+
266+
settings, err := db.GetSettings()
267+
require.NoError(t, err)
268+
269+
// Using GreaterOrEqual because the timestamp is set during CreateSettings and there is a tiny chance that the second changes between
270+
require.GreaterOrEqual(t, time.Now().UTC().Second(), settings.NewsFeedLastFetchedTimestamp.UTC().Second())
271+
272+
dateNow := time.Now()
273+
err = db.SaveSetting(NewsFeedLastFetchedTimestamp.GetReactName(), dateNow)
274+
require.NoError(t, err)
275+
276+
settings, err = db.GetSettings()
277+
require.NoError(t, err)
278+
require.Equal(t, dateNow.UTC().Second(), settings.NewsFeedLastFetchedTimestamp.UTC().Second())
279+
}

multiaccounts/settings/structs.go

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -157,9 +157,12 @@ type Settings struct {
157157
Name string `json:"name,omitempty"`
158158
Networks *json.RawMessage `json:"networks/networks"`
159159
// NotificationsEnabled indicates whether local notifications should be enabled (android only)
160-
NotificationsEnabled bool `json:"notifications-enabled?,omitempty"`
161-
PhotoPath string `json:"photo-path"`
162-
PinnedMailserver *json.RawMessage `json:"pinned-mailservers,omitempty"`
160+
NotificationsEnabled bool `json:"notifications-enabled?,omitempty"`
161+
NewsFeedEnabled bool `json:"news-feed-enabled?,omitempty"`
162+
NewsFeedLastFetchedTimestamp time.Time `json:"news-feed-last-fetched-timestamp,omitempty"`
163+
NewsNotificationsEnabled bool `json:"news-notifications-enabled?,omitempty"`
164+
PhotoPath string `json:"photo-path"`
165+
PinnedMailserver *json.RawMessage `json:"pinned-mailservers,omitempty"`
163166
// PreferredName represents the user's preferred Ethereum Name Service (ENS) name.
164167
// If a user has multiple ENS names, they can select one as the PreferredName.
165168
// When PreferredName is set, it takes precedence over the DisplayName for displaying the user's name.
@@ -181,7 +184,6 @@ type Settings struct {
181184
RememberSyncingChoice bool `json:"remember-syncing-choice?,omitempty"`
182185
// RemotePushNotificationsEnabled indicates whether we should be using remote notifications (ios only for now)
183186
RemotePushNotificationsEnabled bool `json:"remote-push-notifications-enabled?,omitempty"`
184-
NewsNotificationsEnabled bool `json:"news-notifications-enabled?,omitempty"`
185187
MessengerNotificationsEnabled bool `json:"messenger-notifications-enabled?,omitempty"`
186188
SigningPhrase string `json:"signing-phrase"`
187189
StickerPacksInstalled *json.RawMessage `json:"stickers/packs-installed,omitempty"`
@@ -227,7 +229,6 @@ type Settings struct {
227229
PeerSyncingEnabled bool `json:"peer-syncing-enabled?,omitempty"`
228230
AutoRefreshTokensEnabled bool `json:"auto-refresh-tokens-enabled,omitempty"`
229231
LastTokensUpdate time.Time `json:"last-tokens-update,omitempty"`
230-
NewsFeedEnabled bool `json:"news-feed-enabled?,omitempty"`
231232
}
232233

233234
func (s Settings) MarshalJSON() ([]byte, error) {

protocol/messenger.go

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -899,15 +899,17 @@ func (m *Messenger) Start() (*MessengerResponse, error) {
899899
}
900900

901901
if m.config.featureFlags.EnableNewsFeed {
902-
// TODO get the last time we opened the app
903-
twoHoursAgo := time.Now().Add(-2 * time.Hour)
902+
lastFetched, err := m.settings.NewsFeedLastFetchedTimestamp()
903+
if err != nil {
904+
return nil, err
905+
}
904906
m.newsFeedManager = newsfeed.NewNewsFeedManager(
905907
newsfeed.WithURL(newsfeed.STATUS_FEED_URL),
906908
newsfeed.WithParser(gofeed.NewParser()),
907909
newsfeed.WithHandler(m),
908910
newsfeed.WithLogger(m.logger),
909911
newsfeed.WithPollingInterval(30*time.Minute),
910-
newsfeed.WithFetchFrom(twoHoursAgo),
912+
newsfeed.WithFetchFrom(lastFetched),
911913
)
912914

913915
// TODO only start if the setting is enabled

protocol/messenger_news_feed.go

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,14 @@
11
package protocol
22

33
import (
4+
"time"
5+
46
"github.com/google/uuid"
57
"github.com/mmcdole/gofeed"
68
"go.uber.org/zap"
79

810
"github.com/status-im/status-go/eth-node/types"
11+
"github.com/status-im/status-go/multiaccounts/settings"
912
"github.com/status-im/status-go/signal"
1013
)
1114

@@ -46,6 +49,13 @@ func (m *Messenger) HandleFeedItem(feedItem *gofeed.Item) (*MessengerResponse, e
4649
return nil, err
4750
}
4851

52+
// Update the lastFetch time to the current time
53+
err = m.settings.SaveSetting(settings.NewsFeedLastFetchedTimestamp.GetReactName(), time.Now())
54+
if err != nil {
55+
m.logger.Error("HandleFeedItem: failed to save last fetch time", zap.Error(err))
56+
return nil, err
57+
}
58+
4959
return response, nil
5060
}
5161

protocol/messenger_news_feed_test.go

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,12 @@ func (s *MessengerNewsFeedSuite) TestHandleNewsFeedItem() {
4343
err := s.m.HandleFeedItemAndSend(&item)
4444
s.Require().NoError(err)
4545

46+
// Check that the lastFetched timestamp is updated
47+
lastFetched, err := s.m.settings.NewsFeedLastFetchedTimestamp()
48+
s.Require().NoError(err)
49+
s.Require().GreaterOrEqual(time.Now().UTC().Second(), lastFetched.UTC().Second())
50+
51+
// Check that the notification is saved in the database
4652
_, notifications, err := s.m.persistence.ActivityCenterNotifications("", 10, []ActivityCenterType{ActivityCenterNotificationTypeNews}, ActivityCenterQueryParamsReadAll, true)
4753
s.Require().NoError(err)
4854
s.Require().NotNil(notifications)

0 commit comments

Comments
 (0)