From 026fcb09a4b45c7764eb6c38f76c3cc10a9dba39 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rich=CE=9Brd?= Date: Thu, 22 Jul 2021 13:41:49 -0400 Subject: [PATCH] feat: user status (#2276) * feat: user status * fix: sql filename and null pointer exceptions * fix: lint * refactor: remove StatusUpdate from database.go * fix: adding missing status updates persistence methods * fix: code review * Update version and bindata, and lint * fix: failing test * fix: code review * fix update statement --- VERSION | 2 +- appdatabase/migrations/bindata.go | 464 ++++++++---------- .../sql/1625872445_user_status.up.sql | 9 + multiaccounts/accounts/database.go | 32 +- multiaccounts/accounts/database_test.go | 1 + multiaccounts/migrations/bindata.go | 144 ++---- protocol/communities/community.go | 9 + protocol/communities_messenger_test.go | 50 +- protocol/message_validator.go | 18 + protocol/messenger.go | 16 +- protocol/messenger_communities.go | 31 +- protocol/messenger_response.go | 31 +- protocol/messenger_status_updates.go | 250 ++++++++++ protocol/persistence.go | 57 +++ .../application_metadata_message.pb.go | 76 +-- .../application_metadata_message.proto | 1 + protocol/protobuf/status_update.pb.go | 131 +++++ protocol/protobuf/status_update.proto | 19 + protocol/status_update.go | 18 + protocol/v1/status_message.go | 2 + services/ext/api.go | 25 +- 21 files changed, 977 insertions(+), 409 deletions(-) create mode 100644 appdatabase/migrations/sql/1625872445_user_status.up.sql create mode 100644 protocol/messenger_status_updates.go create mode 100644 protocol/protobuf/status_update.pb.go create mode 100644 protocol/protobuf/status_update.proto create mode 100644 protocol/status_update.go diff --git a/VERSION b/VERSION index 83dcd12cb..2a0490562 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -0.83.0 +0.83.1 diff --git a/appdatabase/migrations/bindata.go b/appdatabase/migrations/bindata.go index 75ad7b34b..75f3a4d42 100644 --- a/appdatabase/migrations/bindata.go +++ b/appdatabase/migrations/bindata.go @@ -1,52 +1,53 @@ -// Code generated by go-bindata. DO NOT EDIT. +// Code generated by go-bindata. // sources: -// 0001_app.down.sql (356B) -// 0001_app.up.sql (2.967kB) -// 0002_tokens.down.sql (19B) -// 0002_tokens.up.sql (248B) -// 0003_settings.down.sql (118B) -// 0003_settings.up.sql (1.311kB) -// 0004_pending_stickers.down.sql (0) -// 0004_pending_stickers.up.sql (61B) -// 0005_waku_mode.down.sql (0) -// 0005_waku_mode.up.sql (146B) -// 0006_appearance.up.sql (67B) -// 0007_enable_waku_default.up.sql (38B) -// 0008_add_push_notifications.up.sql (349B) -// 0009_enable_sending_push_notifications.down.sql (49B) -// 0009_enable_sending_push_notifications.up.sql (49B) -// 0010_add_block_mentions.down.sql (83B) -// 0010_add_block_mentions.up.sql (89B) -// 0011_allow_webview_permission_requests.down.sql (0) -// 0011_allow_webview_permission_requests.up.sql (88B) -// 0012_pending_transactions.down.sql (33B) -// 0012_pending_transactions.up.sql (321B) -// 0013_favourites.down.sql (23B) -// 0013_favourites.up.sql (132B) -// 0014_add_use_mailservers.down.sql (0) -// 0014_add_use_mailservers.up.sql (111B) -// 0015_link_previews.down.sql (0) -// 0015_link_previews.up.sql (203B) -// 0016_local_notifications_preferences.down.sql (43B) -// 0016_local_notifications_preferences.up.sql (204B) -// 0017_bookmarks.down.sql (22B) -// 0017_bookmarks.up.sql (147B) -// 0018_profile_pictures_visibility.up.sql (84B) -// 0019_blocks_ranges_extra_data.up.sql (89B) -// 0020_metrics.up.sql (235B) -// 0021_add_session_id_to_metrics.up.sql (55B) -// 0022_pending_transfers.up.sql (706B) -// 1618237885_settings_anon_metrics_should_send.up.sql (80B) -// 1618395756_contacts_only.up.sql (136B) -// 1622184614_add_default_sync_period.up.sql (125B) -// doc.go (74B) +// 0001_app.down.sql +// 0001_app.up.sql +// 0002_tokens.down.sql +// 0002_tokens.up.sql +// 0003_settings.down.sql +// 0003_settings.up.sql +// 0004_pending_stickers.down.sql +// 0004_pending_stickers.up.sql +// 0005_waku_mode.down.sql +// 0005_waku_mode.up.sql +// 0006_appearance.up.sql +// 0007_enable_waku_default.up.sql +// 0008_add_push_notifications.up.sql +// 0009_enable_sending_push_notifications.down.sql +// 0009_enable_sending_push_notifications.up.sql +// 0010_add_block_mentions.down.sql +// 0010_add_block_mentions.up.sql +// 0011_allow_webview_permission_requests.down.sql +// 0011_allow_webview_permission_requests.up.sql +// 0012_pending_transactions.down.sql +// 0012_pending_transactions.up.sql +// 0013_favourites.down.sql +// 0013_favourites.up.sql +// 0014_add_use_mailservers.down.sql +// 0014_add_use_mailservers.up.sql +// 0015_link_previews.down.sql +// 0015_link_previews.up.sql +// 0016_local_notifications_preferences.down.sql +// 0016_local_notifications_preferences.up.sql +// 0017_bookmarks.down.sql +// 0017_bookmarks.up.sql +// 0018_profile_pictures_visibility.up.sql +// 0019_blocks_ranges_extra_data.up.sql +// 0020_metrics.up.sql +// 0021_add_session_id_to_metrics.up.sql +// 0022_pending_transfers.up.sql +// 1618237885_settings_anon_metrics_should_send.up.sql +// 1618395756_contacts_only.up.sql +// 1622184614_add_default_sync_period.up.sql +// 1625872445_user_status.up.sql +// doc.go +// DO NOT EDIT! package migrations import ( "bytes" "compress/gzip" - "crypto/sha256" "fmt" "io" "io/ioutil" @@ -59,7 +60,7 @@ import ( func bindataRead(data []byte, name string) ([]byte, error) { gz, err := gzip.NewReader(bytes.NewBuffer(data)) if err != nil { - return nil, fmt.Errorf("read %q: %v", name, err) + return nil, fmt.Errorf("Read %q: %v", name, err) } var buf bytes.Buffer @@ -67,7 +68,7 @@ func bindataRead(data []byte, name string) ([]byte, error) { clErr := gz.Close() if err != nil { - return nil, fmt.Errorf("read %q: %v", name, err) + return nil, fmt.Errorf("Read %q: %v", name, err) } if clErr != nil { return nil, err @@ -77,9 +78,8 @@ func bindataRead(data []byte, name string) ([]byte, error) { } type asset struct { - bytes []byte - info os.FileInfo - digest [sha256.Size]byte + bytes []byte + info os.FileInfo } type bindataFileInfo struct { @@ -123,8 +123,8 @@ func _0001_appDownSql() (*asset, error) { return nil, err } - info := bindataFileInfo{name: "0001_app.down.sql", size: 356, mode: os.FileMode(0644), modTime: time.Unix(1599559876, 0)} - a := &asset{bytes: bytes, info: info, digest: [32]uint8{0xb5, 0x25, 0xa0, 0xf8, 0x7d, 0x2d, 0xd, 0xcf, 0x18, 0xe4, 0x73, 0xc3, 0x95, 0xf5, 0x24, 0x20, 0xa9, 0xe6, 0x9e, 0x1d, 0x93, 0xe5, 0xc5, 0xad, 0x93, 0x8f, 0x5e, 0x40, 0xb5, 0x30, 0xaa, 0x25}} + info := bindataFileInfo{name: "0001_app.down.sql", size: 356, mode: os.FileMode(436), modTime: time.Unix(1619724270, 0)} + a := &asset{bytes: bytes, info: info} return a, nil } @@ -143,8 +143,8 @@ func _0001_appUpSql() (*asset, error) { return nil, err } - info := bindataFileInfo{name: "0001_app.up.sql", size: 2967, mode: os.FileMode(0644), modTime: time.Unix(1599559876, 0)} - a := &asset{bytes: bytes, info: info, digest: [32]uint8{0xf7, 0x3a, 0xa7, 0xf2, 0x8f, 0xfa, 0x82, 0x7c, 0xc5, 0x49, 0xac, 0xac, 0xf, 0xc, 0x77, 0xe2, 0xba, 0xe8, 0x4d, 0xe, 0x6f, 0x5d, 0x2c, 0x2c, 0x18, 0x80, 0xc2, 0x1d, 0xe, 0x25, 0xe, 0x18}} + info := bindataFileInfo{name: "0001_app.up.sql", size: 2967, mode: os.FileMode(436), modTime: time.Unix(1619724270, 0)} + a := &asset{bytes: bytes, info: info} return a, nil } @@ -163,8 +163,8 @@ func _0002_tokensDownSql() (*asset, error) { return nil, err } - info := bindataFileInfo{name: "0002_tokens.down.sql", size: 19, mode: os.FileMode(0644), modTime: time.Unix(1599559876, 0)} - a := &asset{bytes: bytes, info: info, digest: [32]uint8{0xd1, 0x31, 0x2, 0xcc, 0x2f, 0x38, 0x90, 0xf7, 0x58, 0x37, 0x47, 0xf4, 0x18, 0xf7, 0x72, 0x74, 0x67, 0x14, 0x7e, 0xf3, 0xb1, 0xd6, 0x5f, 0xb0, 0xd5, 0xe7, 0x91, 0xf4, 0x26, 0x77, 0x8e, 0x68}} + info := bindataFileInfo{name: "0002_tokens.down.sql", size: 19, mode: os.FileMode(436), modTime: time.Unix(1619724270, 0)} + a := &asset{bytes: bytes, info: info} return a, nil } @@ -183,8 +183,8 @@ func _0002_tokensUpSql() (*asset, error) { return nil, err } - info := bindataFileInfo{name: "0002_tokens.up.sql", size: 248, mode: os.FileMode(0644), modTime: time.Unix(1599559876, 0)} - a := &asset{bytes: bytes, info: info, digest: [32]uint8{0xcc, 0xd6, 0xde, 0xd3, 0x7b, 0xee, 0x92, 0x11, 0x38, 0xa4, 0xeb, 0x84, 0xca, 0xcb, 0x37, 0x75, 0x5, 0x77, 0x7f, 0x14, 0x39, 0xee, 0xa1, 0x8b, 0xd4, 0x5c, 0x6e, 0x55, 0x6, 0x50, 0x16, 0xd4}} + info := bindataFileInfo{name: "0002_tokens.up.sql", size: 248, mode: os.FileMode(436), modTime: time.Unix(1619724270, 0)} + a := &asset{bytes: bytes, info: info} return a, nil } @@ -203,8 +203,8 @@ func _0003_settingsDownSql() (*asset, error) { return nil, err } - info := bindataFileInfo{name: "0003_settings.down.sql", size: 118, mode: os.FileMode(0644), modTime: time.Unix(1599559876, 0)} - a := &asset{bytes: bytes, info: info, digest: [32]uint8{0xe5, 0xa6, 0xf5, 0xc0, 0x60, 0x64, 0x77, 0xe2, 0xe7, 0x3c, 0x9b, 0xb1, 0x52, 0xa9, 0x95, 0x16, 0xf8, 0x60, 0x2f, 0xa5, 0xeb, 0x46, 0xb9, 0xb9, 0x8f, 0x4c, 0xf4, 0xfd, 0xbb, 0xe7, 0xe5, 0xe5}} + info := bindataFileInfo{name: "0003_settings.down.sql", size: 118, mode: os.FileMode(436), modTime: time.Unix(1619724270, 0)} + a := &asset{bytes: bytes, info: info} return a, nil } @@ -223,8 +223,8 @@ func _0003_settingsUpSql() (*asset, error) { return nil, err } - info := bindataFileInfo{name: "0003_settings.up.sql", size: 1311, mode: os.FileMode(0644), modTime: time.Unix(1599559876, 0)} - a := &asset{bytes: bytes, info: info, digest: [32]uint8{0xea, 0x35, 0x0, 0xeb, 0xe2, 0x33, 0x68, 0xb9, 0xf4, 0xf6, 0x8e, 0x9e, 0x10, 0xe9, 0x58, 0x68, 0x28, 0xb, 0xcd, 0xec, 0x74, 0x71, 0xa7, 0x9a, 0x5a, 0x77, 0x59, 0xb1, 0x13, 0x1c, 0xa1, 0x5b}} + info := bindataFileInfo{name: "0003_settings.up.sql", size: 1311, mode: os.FileMode(436), modTime: time.Unix(1619724270, 0)} + a := &asset{bytes: bytes, info: info} return a, nil } @@ -243,8 +243,8 @@ func _0004_pending_stickersDownSql() (*asset, error) { return nil, err } - info := bindataFileInfo{name: "0004_pending_stickers.down.sql", size: 0, mode: os.FileMode(0644), modTime: time.Unix(1599559876, 0)} - a := &asset{bytes: bytes, info: info, digest: [32]uint8{0xe3, 0xb0, 0xc4, 0x42, 0x98, 0xfc, 0x1c, 0x14, 0x9a, 0xfb, 0xf4, 0xc8, 0x99, 0x6f, 0xb9, 0x24, 0x27, 0xae, 0x41, 0xe4, 0x64, 0x9b, 0x93, 0x4c, 0xa4, 0x95, 0x99, 0x1b, 0x78, 0x52, 0xb8, 0x55}} + info := bindataFileInfo{name: "0004_pending_stickers.down.sql", size: 0, mode: os.FileMode(436), modTime: time.Unix(1619724270, 0)} + a := &asset{bytes: bytes, info: info} return a, nil } @@ -263,8 +263,8 @@ func _0004_pending_stickersUpSql() (*asset, error) { return nil, err } - info := bindataFileInfo{name: "0004_pending_stickers.up.sql", size: 61, mode: os.FileMode(0644), modTime: time.Unix(1599559876, 0)} - a := &asset{bytes: bytes, info: info, digest: [32]uint8{0x3c, 0xed, 0x25, 0xdf, 0x75, 0x2, 0x6c, 0xf0, 0xa2, 0xa8, 0x37, 0x62, 0x65, 0xad, 0xfd, 0x98, 0xa0, 0x9d, 0x63, 0x94, 0xdf, 0x6b, 0x46, 0xe0, 0x68, 0xec, 0x9c, 0x7f, 0x77, 0xdd, 0xb3, 0x6}} + info := bindataFileInfo{name: "0004_pending_stickers.up.sql", size: 61, mode: os.FileMode(436), modTime: time.Unix(1619724270, 0)} + a := &asset{bytes: bytes, info: info} return a, nil } @@ -283,8 +283,8 @@ func _0005_waku_modeDownSql() (*asset, error) { return nil, err } - info := bindataFileInfo{name: "0005_waku_mode.down.sql", size: 0, mode: os.FileMode(0644), modTime: time.Unix(1599559876, 0)} - a := &asset{bytes: bytes, info: info, digest: [32]uint8{0xe3, 0xb0, 0xc4, 0x42, 0x98, 0xfc, 0x1c, 0x14, 0x9a, 0xfb, 0xf4, 0xc8, 0x99, 0x6f, 0xb9, 0x24, 0x27, 0xae, 0x41, 0xe4, 0x64, 0x9b, 0x93, 0x4c, 0xa4, 0x95, 0x99, 0x1b, 0x78, 0x52, 0xb8, 0x55}} + info := bindataFileInfo{name: "0005_waku_mode.down.sql", size: 0, mode: os.FileMode(436), modTime: time.Unix(1619724270, 0)} + a := &asset{bytes: bytes, info: info} return a, nil } @@ -303,8 +303,8 @@ func _0005_waku_modeUpSql() (*asset, error) { return nil, err } - info := bindataFileInfo{name: "0005_waku_mode.up.sql", size: 146, mode: os.FileMode(0644), modTime: time.Unix(1599559876, 0)} - a := &asset{bytes: bytes, info: info, digest: [32]uint8{0xa6, 0x91, 0xc, 0xd7, 0x89, 0x61, 0x2e, 0x4c, 0x5a, 0xb6, 0x67, 0xd1, 0xc1, 0x42, 0x24, 0x38, 0xd6, 0x1b, 0x75, 0x41, 0x9c, 0x23, 0xb0, 0xca, 0x5c, 0xf1, 0x5c, 0xd0, 0x13, 0x92, 0x3e, 0xe1}} + info := bindataFileInfo{name: "0005_waku_mode.up.sql", size: 146, mode: os.FileMode(436), modTime: time.Unix(1619724270, 0)} + a := &asset{bytes: bytes, info: info} return a, nil } @@ -323,8 +323,8 @@ func _0006_appearanceUpSql() (*asset, error) { return nil, err } - info := bindataFileInfo{name: "0006_appearance.up.sql", size: 67, mode: os.FileMode(0644), modTime: time.Unix(1609934130, 0)} - a := &asset{bytes: bytes, info: info, digest: [32]uint8{0xae, 0x6, 0x25, 0x6c, 0xe4, 0x9d, 0xa7, 0x72, 0xe8, 0xbc, 0xe4, 0x1f, 0x1e, 0x2d, 0x7c, 0xb7, 0xf6, 0xa3, 0xec, 0x3b, 0x4e, 0x93, 0x2e, 0xa4, 0xec, 0x6f, 0xe5, 0x95, 0x94, 0xe8, 0x4, 0xfb}} + info := bindataFileInfo{name: "0006_appearance.up.sql", size: 67, mode: os.FileMode(436), modTime: time.Unix(1619724270, 0)} + a := &asset{bytes: bytes, info: info} return a, nil } @@ -343,8 +343,8 @@ func _0007_enable_waku_defaultUpSql() (*asset, error) { return nil, err } - info := bindataFileInfo{name: "0007_enable_waku_default.up.sql", size: 38, mode: os.FileMode(0644), modTime: time.Unix(1609934130, 0)} - a := &asset{bytes: bytes, info: info, digest: [32]uint8{0xd4, 0x42, 0xb6, 0xe5, 0x48, 0x41, 0xeb, 0xc0, 0x7e, 0x3b, 0xe6, 0x8e, 0x96, 0x33, 0x20, 0x92, 0x24, 0x5a, 0x60, 0xfa, 0xa0, 0x3, 0x5e, 0x76, 0x4b, 0x89, 0xaa, 0x37, 0x66, 0xbc, 0x26, 0x11}} + info := bindataFileInfo{name: "0007_enable_waku_default.up.sql", size: 38, mode: os.FileMode(436), modTime: time.Unix(1619724270, 0)} + a := &asset{bytes: bytes, info: info} return a, nil } @@ -363,8 +363,8 @@ func _0008_add_push_notificationsUpSql() (*asset, error) { return nil, err } - info := bindataFileInfo{name: "0008_add_push_notifications.up.sql", size: 349, mode: os.FileMode(0644), modTime: time.Unix(1611588835, 0)} - a := &asset{bytes: bytes, info: info, digest: [32]uint8{0x5a, 0x0, 0xbf, 0xd0, 0xdd, 0xcd, 0x73, 0xe0, 0x7c, 0x56, 0xef, 0xdc, 0x57, 0x61, 0x94, 0x64, 0x70, 0xb9, 0xfa, 0xa1, 0x2a, 0x36, 0xc, 0x2f, 0xf8, 0x95, 0xa, 0x57, 0x3e, 0x7a, 0xd7, 0x12}} + info := bindataFileInfo{name: "0008_add_push_notifications.up.sql", size: 349, mode: os.FileMode(436), modTime: time.Unix(1619724270, 0)} + a := &asset{bytes: bytes, info: info} return a, nil } @@ -383,8 +383,8 @@ func _0009_enable_sending_push_notificationsDownSql() (*asset, error) { return nil, err } - info := bindataFileInfo{name: "0009_enable_sending_push_notifications.down.sql", size: 49, mode: os.FileMode(0644), modTime: time.Unix(1611588835, 0)} - a := &asset{bytes: bytes, info: info, digest: [32]uint8{0xe9, 0xae, 0x1b, 0x41, 0xcb, 0x9c, 0x2c, 0x93, 0xc6, 0x2a, 0x77, 0x3, 0xb9, 0x51, 0xe0, 0x68, 0x68, 0x0, 0xf7, 0x5b, 0xb3, 0x1e, 0x94, 0x44, 0xba, 0x9c, 0xd0, 0x3b, 0x80, 0x21, 0x6f, 0xb5}} + info := bindataFileInfo{name: "0009_enable_sending_push_notifications.down.sql", size: 49, mode: os.FileMode(436), modTime: time.Unix(1619724270, 0)} + a := &asset{bytes: bytes, info: info} return a, nil } @@ -403,8 +403,8 @@ func _0009_enable_sending_push_notificationsUpSql() (*asset, error) { return nil, err } - info := bindataFileInfo{name: "0009_enable_sending_push_notifications.up.sql", size: 49, mode: os.FileMode(0644), modTime: time.Unix(1611588835, 0)} - a := &asset{bytes: bytes, info: info, digest: [32]uint8{0x1b, 0x80, 0xe4, 0x9c, 0xc8, 0xb8, 0xd5, 0xef, 0xce, 0x74, 0x9b, 0x7b, 0xdd, 0xa, 0x99, 0x1e, 0xef, 0x7f, 0xb8, 0x99, 0x84, 0x4, 0x0, 0x6b, 0x1d, 0x2c, 0xa, 0xf8, 0x2c, 0x4f, 0xb5, 0x44}} + info := bindataFileInfo{name: "0009_enable_sending_push_notifications.up.sql", size: 49, mode: os.FileMode(436), modTime: time.Unix(1619724270, 0)} + a := &asset{bytes: bytes, info: info} return a, nil } @@ -423,8 +423,8 @@ func _0010_add_block_mentionsDownSql() (*asset, error) { return nil, err } - info := bindataFileInfo{name: "0010_add_block_mentions.down.sql", size: 83, mode: os.FileMode(0644), modTime: time.Unix(1611588835, 0)} - a := &asset{bytes: bytes, info: info, digest: [32]uint8{0x6d, 0x9e, 0x27, 0x1e, 0xba, 0x9f, 0xca, 0xae, 0x98, 0x2e, 0x6e, 0xe3, 0xdd, 0xac, 0x73, 0x34, 0x4e, 0x69, 0x92, 0xb5, 0xf6, 0x9, 0xab, 0x50, 0x35, 0xd, 0xee, 0xeb, 0x3e, 0xcc, 0x7e, 0xce}} + info := bindataFileInfo{name: "0010_add_block_mentions.down.sql", size: 83, mode: os.FileMode(436), modTime: time.Unix(1619724270, 0)} + a := &asset{bytes: bytes, info: info} return a, nil } @@ -443,8 +443,8 @@ func _0010_add_block_mentionsUpSql() (*asset, error) { return nil, err } - info := bindataFileInfo{name: "0010_add_block_mentions.up.sql", size: 89, mode: os.FileMode(0644), modTime: time.Unix(1611588835, 0)} - a := &asset{bytes: bytes, info: info, digest: [32]uint8{0xd7, 0x23, 0x85, 0xa2, 0xb5, 0xb6, 0xb4, 0x3f, 0xdc, 0x4e, 0xff, 0xe2, 0x6b, 0x66, 0x68, 0x5e, 0xb2, 0xb4, 0x14, 0xb2, 0x1b, 0x4d, 0xb1, 0xce, 0xf7, 0x6, 0x58, 0xa7, 0xaf, 0x93, 0x3f, 0x25}} + info := bindataFileInfo{name: "0010_add_block_mentions.up.sql", size: 89, mode: os.FileMode(436), modTime: time.Unix(1619724270, 0)} + a := &asset{bytes: bytes, info: info} return a, nil } @@ -463,8 +463,8 @@ func _0011_allow_webview_permission_requestsDownSql() (*asset, error) { return nil, err } - info := bindataFileInfo{name: "0011_allow_webview_permission_requests.down.sql", size: 0, mode: os.FileMode(0644), modTime: time.Unix(1611588835, 0)} - a := &asset{bytes: bytes, info: info, digest: [32]uint8{0xe3, 0xb0, 0xc4, 0x42, 0x98, 0xfc, 0x1c, 0x14, 0x9a, 0xfb, 0xf4, 0xc8, 0x99, 0x6f, 0xb9, 0x24, 0x27, 0xae, 0x41, 0xe4, 0x64, 0x9b, 0x93, 0x4c, 0xa4, 0x95, 0x99, 0x1b, 0x78, 0x52, 0xb8, 0x55}} + info := bindataFileInfo{name: "0011_allow_webview_permission_requests.down.sql", size: 0, mode: os.FileMode(436), modTime: time.Unix(1619724270, 0)} + a := &asset{bytes: bytes, info: info} return a, nil } @@ -483,8 +483,8 @@ func _0011_allow_webview_permission_requestsUpSql() (*asset, error) { return nil, err } - info := bindataFileInfo{name: "0011_allow_webview_permission_requests.up.sql", size: 88, mode: os.FileMode(0644), modTime: time.Unix(1611588835, 0)} - a := &asset{bytes: bytes, info: info, digest: [32]uint8{0x43, 0x5f, 0x22, 0x4c, 0x98, 0x1d, 0xc6, 0xf4, 0x89, 0xaf, 0xf4, 0x44, 0xba, 0xf8, 0x28, 0xa7, 0xb5, 0xb9, 0xf0, 0xf2, 0xcb, 0x5, 0x59, 0x7a, 0xc, 0xdf, 0xd3, 0x38, 0xa4, 0xb8, 0x98, 0xc2}} + info := bindataFileInfo{name: "0011_allow_webview_permission_requests.up.sql", size: 88, mode: os.FileMode(436), modTime: time.Unix(1619724270, 0)} + a := &asset{bytes: bytes, info: info} return a, nil } @@ -503,8 +503,8 @@ func _0012_pending_transactionsDownSql() (*asset, error) { return nil, err } - info := bindataFileInfo{name: "0012_pending_transactions.down.sql", size: 33, mode: os.FileMode(0644), modTime: time.Unix(1611588835, 0)} - a := &asset{bytes: bytes, info: info, digest: [32]uint8{0x7e, 0x41, 0xfe, 0x5c, 0xd8, 0xc3, 0x29, 0xfd, 0x31, 0x78, 0x99, 0x7a, 0xeb, 0x17, 0x62, 0x88, 0x41, 0xb3, 0xe7, 0xb5, 0x5, 0x0, 0x90, 0xa1, 0x7, 0x1a, 0x23, 0x88, 0x81, 0xba, 0x56, 0x9d}} + info := bindataFileInfo{name: "0012_pending_transactions.down.sql", size: 33, mode: os.FileMode(436), modTime: time.Unix(1619724270, 0)} + a := &asset{bytes: bytes, info: info} return a, nil } @@ -523,8 +523,8 @@ func _0012_pending_transactionsUpSql() (*asset, error) { return nil, err } - info := bindataFileInfo{name: "0012_pending_transactions.up.sql", size: 321, mode: os.FileMode(0644), modTime: time.Unix(1611588835, 0)} - a := &asset{bytes: bytes, info: info, digest: [32]uint8{0xd, 0x17, 0xff, 0xd7, 0xa7, 0x49, 0x1e, 0x7b, 0x34, 0x63, 0x7c, 0x53, 0xaa, 0x6b, 0x2d, 0xc8, 0xe0, 0x82, 0x21, 0x90, 0x3a, 0x94, 0xf1, 0xa6, 0xe4, 0x70, 0xe5, 0x85, 0x1a, 0x48, 0x25, 0xb}} + info := bindataFileInfo{name: "0012_pending_transactions.up.sql", size: 321, mode: os.FileMode(436), modTime: time.Unix(1619724270, 0)} + a := &asset{bytes: bytes, info: info} return a, nil } @@ -543,8 +543,8 @@ func _0013_favouritesDownSql() (*asset, error) { return nil, err } - info := bindataFileInfo{name: "0013_favourites.down.sql", size: 23, mode: os.FileMode(0644), modTime: time.Unix(1611588835, 0)} - a := &asset{bytes: bytes, info: info, digest: [32]uint8{0x32, 0xf8, 0x55, 0x13, 0x4f, 0x4a, 0x19, 0x83, 0x9c, 0xda, 0x34, 0xb8, 0x3, 0x54, 0x82, 0x1e, 0x99, 0x36, 0x6b, 0x42, 0x3, 0xf6, 0x43, 0xde, 0xe6, 0x32, 0xb6, 0xdf, 0xe2, 0x59, 0x8c, 0x84}} + info := bindataFileInfo{name: "0013_favourites.down.sql", size: 23, mode: os.FileMode(436), modTime: time.Unix(1619724270, 0)} + a := &asset{bytes: bytes, info: info} return a, nil } @@ -563,8 +563,8 @@ func _0013_favouritesUpSql() (*asset, error) { return nil, err } - info := bindataFileInfo{name: "0013_favourites.up.sql", size: 132, mode: os.FileMode(0644), modTime: time.Unix(1611588835, 0)} - a := &asset{bytes: bytes, info: info, digest: [32]uint8{0xbe, 0x1, 0x27, 0x38, 0x76, 0xf5, 0xcb, 0x61, 0xda, 0x5b, 0xce, 0xd9, 0x8b, 0x18, 0x77, 0x61, 0x84, 0xe7, 0x22, 0xe2, 0x13, 0x99, 0xab, 0x32, 0xbc, 0xbe, 0xed, 0x1f, 0x2f, 0xb0, 0xe4, 0x8d}} + info := bindataFileInfo{name: "0013_favourites.up.sql", size: 132, mode: os.FileMode(436), modTime: time.Unix(1619724270, 0)} + a := &asset{bytes: bytes, info: info} return a, nil } @@ -583,8 +583,8 @@ func _0014_add_use_mailserversDownSql() (*asset, error) { return nil, err } - info := bindataFileInfo{name: "0014_add_use_mailservers.down.sql", size: 0, mode: os.FileMode(0644), modTime: time.Unix(1611588835, 0)} - a := &asset{bytes: bytes, info: info, digest: [32]uint8{0xe3, 0xb0, 0xc4, 0x42, 0x98, 0xfc, 0x1c, 0x14, 0x9a, 0xfb, 0xf4, 0xc8, 0x99, 0x6f, 0xb9, 0x24, 0x27, 0xae, 0x41, 0xe4, 0x64, 0x9b, 0x93, 0x4c, 0xa4, 0x95, 0x99, 0x1b, 0x78, 0x52, 0xb8, 0x55}} + info := bindataFileInfo{name: "0014_add_use_mailservers.down.sql", size: 0, mode: os.FileMode(436), modTime: time.Unix(1619724270, 0)} + a := &asset{bytes: bytes, info: info} return a, nil } @@ -603,8 +603,8 @@ func _0014_add_use_mailserversUpSql() (*asset, error) { return nil, err } - info := bindataFileInfo{name: "0014_add_use_mailservers.up.sql", size: 111, mode: os.FileMode(0644), modTime: time.Unix(1611588835, 0)} - a := &asset{bytes: bytes, info: info, digest: [32]uint8{0xc9, 0xba, 0x65, 0xbf, 0x1b, 0xc9, 0x6d, 0x45, 0xf2, 0xf5, 0x30, 0x7c, 0xc1, 0xde, 0xb8, 0xe3, 0x3f, 0xa9, 0x2f, 0x9f, 0xea, 0x1, 0x29, 0x29, 0x65, 0xe7, 0x38, 0xab, 0xa4, 0x62, 0xf, 0xd0}} + info := bindataFileInfo{name: "0014_add_use_mailservers.up.sql", size: 111, mode: os.FileMode(436), modTime: time.Unix(1619724270, 0)} + a := &asset{bytes: bytes, info: info} return a, nil } @@ -623,8 +623,8 @@ func _0015_link_previewsDownSql() (*asset, error) { return nil, err } - info := bindataFileInfo{name: "0015_link_previews.down.sql", size: 0, mode: os.FileMode(0644), modTime: time.Unix(1617280156, 0)} - a := &asset{bytes: bytes, info: info, digest: [32]uint8{0xe3, 0xb0, 0xc4, 0x42, 0x98, 0xfc, 0x1c, 0x14, 0x9a, 0xfb, 0xf4, 0xc8, 0x99, 0x6f, 0xb9, 0x24, 0x27, 0xae, 0x41, 0xe4, 0x64, 0x9b, 0x93, 0x4c, 0xa4, 0x95, 0x99, 0x1b, 0x78, 0x52, 0xb8, 0x55}} + info := bindataFileInfo{name: "0015_link_previews.down.sql", size: 0, mode: os.FileMode(436), modTime: time.Unix(1619724270, 0)} + a := &asset{bytes: bytes, info: info} return a, nil } @@ -643,8 +643,8 @@ func _0015_link_previewsUpSql() (*asset, error) { return nil, err } - info := bindataFileInfo{name: "0015_link_previews.up.sql", size: 203, mode: os.FileMode(0644), modTime: time.Unix(1617280156, 0)} - a := &asset{bytes: bytes, info: info, digest: [32]uint8{0xb1, 0xf7, 0x38, 0x25, 0xa6, 0xfc, 0x6b, 0x9, 0xe4, 0xd9, 0xbf, 0x58, 0x7b, 0x80, 0xd8, 0x48, 0x63, 0xde, 0xa5, 0x5e, 0x30, 0xa3, 0xeb, 0x68, 0x8e, 0x6a, 0x9f, 0xfd, 0xf4, 0x46, 0x41, 0x34}} + info := bindataFileInfo{name: "0015_link_previews.up.sql", size: 203, mode: os.FileMode(436), modTime: time.Unix(1619724270, 0)} + a := &asset{bytes: bytes, info: info} return a, nil } @@ -663,8 +663,8 @@ func _0016_local_notifications_preferencesDownSql() (*asset, error) { return nil, err } - info := bindataFileInfo{name: "0016_local_notifications_preferences.down.sql", size: 43, mode: os.FileMode(0644), modTime: time.Unix(1617280156, 0)} - a := &asset{bytes: bytes, info: info, digest: [32]uint8{0xe0, 0x50, 0xc7, 0xdd, 0x53, 0x9c, 0x5d, 0x1e, 0xb5, 0x71, 0x25, 0x50, 0x58, 0xcf, 0x6d, 0xbe, 0x5a, 0x8, 0x12, 0xc9, 0x13, 0xd, 0x9a, 0x3d, 0x4b, 0x7a, 0x2f, 0x1b, 0xe5, 0x23, 0x52, 0x78}} + info := bindataFileInfo{name: "0016_local_notifications_preferences.down.sql", size: 43, mode: os.FileMode(436), modTime: time.Unix(1619724270, 0)} + a := &asset{bytes: bytes, info: info} return a, nil } @@ -683,8 +683,8 @@ func _0016_local_notifications_preferencesUpSql() (*asset, error) { return nil, err } - info := bindataFileInfo{name: "0016_local_notifications_preferences.up.sql", size: 204, mode: os.FileMode(0644), modTime: time.Unix(1617280156, 0)} - a := &asset{bytes: bytes, info: info, digest: [32]uint8{0x3f, 0x3a, 0x16, 0x25, 0xdf, 0xba, 0x62, 0xd3, 0x81, 0x73, 0xc, 0x10, 0x85, 0xbc, 0x8d, 0xe, 0x1d, 0x62, 0xcb, 0xb, 0x6d, 0x8c, 0x4f, 0x63, 0x5f, 0xe2, 0xd, 0xc5, 0x46, 0xa8, 0x35, 0x5b}} + info := bindataFileInfo{name: "0016_local_notifications_preferences.up.sql", size: 204, mode: os.FileMode(436), modTime: time.Unix(1619724270, 0)} + a := &asset{bytes: bytes, info: info} return a, nil } @@ -703,8 +703,8 @@ func _0017_bookmarksDownSql() (*asset, error) { return nil, err } - info := bindataFileInfo{name: "0017_bookmarks.down.sql", size: 22, mode: os.FileMode(0644), modTime: time.Unix(1617280156, 0)} - a := &asset{bytes: bytes, info: info, digest: [32]uint8{0x9a, 0x13, 0x2a, 0x44, 0xb0, 0x3, 0x18, 0x63, 0xb8, 0x33, 0xda, 0x3a, 0xeb, 0xb8, 0xcb, 0xd1, 0x98, 0x29, 0xa7, 0xf0, 0x6, 0x9d, 0xc9, 0x62, 0xe7, 0x89, 0x7f, 0x77, 0xaf, 0xec, 0x6b, 0x8f}} + info := bindataFileInfo{name: "0017_bookmarks.down.sql", size: 22, mode: os.FileMode(436), modTime: time.Unix(1619724270, 0)} + a := &asset{bytes: bytes, info: info} return a, nil } @@ -723,8 +723,8 @@ func _0017_bookmarksUpSql() (*asset, error) { return nil, err } - info := bindataFileInfo{name: "0017_bookmarks.up.sql", size: 147, mode: os.FileMode(0644), modTime: time.Unix(1617280156, 0)} - a := &asset{bytes: bytes, info: info, digest: [32]uint8{0xbc, 0x47, 0xe1, 0xe3, 0xd8, 0xc6, 0x4, 0x6d, 0x5f, 0x2f, 0xa, 0x51, 0xa6, 0x8c, 0x6a, 0xe0, 0x3d, 0x8c, 0x91, 0x47, 0xbc, 0x1, 0x75, 0x46, 0x92, 0x2, 0x18, 0x6e, 0xe3, 0x4f, 0x18, 0x57}} + info := bindataFileInfo{name: "0017_bookmarks.up.sql", size: 147, mode: os.FileMode(436), modTime: time.Unix(1619724270, 0)} + a := &asset{bytes: bytes, info: info} return a, nil } @@ -743,8 +743,8 @@ func _0018_profile_pictures_visibilityUpSql() (*asset, error) { return nil, err } - info := bindataFileInfo{name: "0018_profile_pictures_visibility.up.sql", size: 84, mode: os.FileMode(0644), modTime: time.Unix(1617280156, 0)} - a := &asset{bytes: bytes, info: info, digest: [32]uint8{0xc9, 0xe3, 0xc5, 0xec, 0x83, 0x55, 0x45, 0x57, 0x7a, 0xaa, 0xd2, 0xa7, 0x59, 0xa7, 0x87, 0xef, 0x63, 0x19, 0x9c, 0x46, 0x9c, 0xc5, 0x32, 0x89, 0xa4, 0x68, 0x70, 0xd8, 0x83, 0x43, 0xa4, 0x72}} + info := bindataFileInfo{name: "0018_profile_pictures_visibility.up.sql", size: 84, mode: os.FileMode(436), modTime: time.Unix(1619724270, 0)} + a := &asset{bytes: bytes, info: info} return a, nil } @@ -763,8 +763,8 @@ func _0019_blocks_ranges_extra_dataUpSql() (*asset, error) { return nil, err } - info := bindataFileInfo{name: "0019_blocks_ranges_extra_data.up.sql", size: 89, mode: os.FileMode(0644), modTime: time.Unix(1617280156, 0)} - a := &asset{bytes: bytes, info: info, digest: [32]uint8{0xa3, 0x96, 0x32, 0x58, 0xf0, 0xb9, 0xe1, 0x70, 0x81, 0xca, 0x8d, 0x45, 0x57, 0x8a, 0x7, 0x5d, 0x9e, 0x2a, 0x30, 0xb, 0xad, 0x5f, 0xf8, 0xd4, 0x30, 0x94, 0x73, 0x37, 0x8d, 0xc1, 0x9a, 0xed}} + info := bindataFileInfo{name: "0019_blocks_ranges_extra_data.up.sql", size: 89, mode: os.FileMode(436), modTime: time.Unix(1619724270, 0)} + a := &asset{bytes: bytes, info: info} return a, nil } @@ -783,8 +783,8 @@ func _0020_metricsUpSql() (*asset, error) { return nil, err } - info := bindataFileInfo{name: "0020_metrics.up.sql", size: 235, mode: os.FileMode(0644), modTime: time.Unix(1617280156, 0)} - a := &asset{bytes: bytes, info: info, digest: [32]uint8{0xe8, 0x32, 0xbc, 0xb6, 0x9b, 0x5a, 0x8f, 0x9f, 0x4c, 0x90, 0x81, 0x3e, 0x2e, 0xd1, 0x23, 0xcd, 0xf1, 0x83, 0x35, 0xca, 0x66, 0x87, 0x52, 0x4e, 0x30, 0x3e, 0x4f, 0xa8, 0xfd, 0x30, 0x16, 0xbd}} + info := bindataFileInfo{name: "0020_metrics.up.sql", size: 235, mode: os.FileMode(436), modTime: time.Unix(1619724270, 0)} + a := &asset{bytes: bytes, info: info} return a, nil } @@ -803,8 +803,8 @@ func _0021_add_session_id_to_metricsUpSql() (*asset, error) { return nil, err } - info := bindataFileInfo{name: "0021_add_session_id_to_metrics.up.sql", size: 55, mode: os.FileMode(0644), modTime: time.Unix(1618913882, 0)} - a := &asset{bytes: bytes, info: info, digest: [32]uint8{0xb7, 0x81, 0xfc, 0x97, 0xd1, 0x8b, 0xea, 0x8e, 0xd7, 0xc2, 0x53, 0x62, 0xe9, 0xbc, 0xf, 0x8c, 0x46, 0x41, 0x41, 0xb7, 0x6, 0x35, 0xf5, 0xba, 0xbb, 0x28, 0x50, 0x48, 0xbf, 0x36, 0x90, 0x5c}} + info := bindataFileInfo{name: "0021_add_session_id_to_metrics.up.sql", size: 55, mode: os.FileMode(436), modTime: time.Unix(1619724270, 0)} + a := &asset{bytes: bytes, info: info} return a, nil } @@ -823,8 +823,8 @@ func _0022_pending_transfersUpSql() (*asset, error) { return nil, err } - info := bindataFileInfo{name: "0022_pending_transfers.up.sql", size: 706, mode: os.FileMode(0644), modTime: time.Unix(1621583900, 0)} - a := &asset{bytes: bytes, info: info, digest: [32]uint8{0x6a, 0x9, 0xe6, 0x6, 0xae, 0x60, 0xdd, 0xbb, 0x76, 0xac, 0xe0, 0x57, 0x30, 0x67, 0x37, 0x93, 0x40, 0x13, 0xec, 0xf2, 0x6e, 0x61, 0xa, 0x14, 0xb2, 0xb1, 0xbd, 0x91, 0xf8, 0x89, 0xb3, 0xe3}} + info := bindataFileInfo{name: "0022_pending_transfers.up.sql", size: 706, mode: os.FileMode(436), modTime: time.Unix(1619724270, 0)} + a := &asset{bytes: bytes, info: info} return a, nil } @@ -843,8 +843,8 @@ func _1618237885_settings_anon_metrics_should_sendUpSql() (*asset, error) { return nil, err } - info := bindataFileInfo{name: "1618237885_settings_anon_metrics_should_send.up.sql", size: 80, mode: os.FileMode(0644), modTime: time.Unix(1618913882, 0)} - a := &asset{bytes: bytes, info: info, digest: [32]uint8{0xea, 0x6c, 0x1d, 0x1f, 0x54, 0x62, 0x18, 0x22, 0x5c, 0xa7, 0x8c, 0x59, 0x24, 0xd3, 0x4d, 0x55, 0xc4, 0x2a, 0x9e, 0x4c, 0x37, 0x6b, 0xfd, 0xac, 0xec, 0xb7, 0x68, 0x21, 0x26, 0x26, 0xf3, 0x92}} + info := bindataFileInfo{name: "1618237885_settings_anon_metrics_should_send.up.sql", size: 80, mode: os.FileMode(436), modTime: time.Unix(1619724270, 0)} + a := &asset{bytes: bytes, info: info} return a, nil } @@ -863,8 +863,8 @@ func _1618395756_contacts_onlyUpSql() (*asset, error) { return nil, err } - info := bindataFileInfo{name: "1618395756_contacts_only.up.sql", size: 136, mode: os.FileMode(0644), modTime: time.Unix(1618913882, 0)} - a := &asset{bytes: bytes, info: info, digest: [32]uint8{0x1, 0xe3, 0xd0, 0xe7, 0xf2, 0x6e, 0xbf, 0x27, 0xf6, 0xe2, 0x2e, 0x16, 0x4b, 0x52, 0x3b, 0xcf, 0x63, 0x52, 0xfc, 0x1d, 0x43, 0xba, 0x42, 0xf9, 0x1e, 0x1e, 0x39, 0x40, 0xed, 0x0, 0x20, 0xa8}} + info := bindataFileInfo{name: "1618395756_contacts_only.up.sql", size: 136, mode: os.FileMode(436), modTime: time.Unix(1619724270, 0)} + a := &asset{bytes: bytes, info: info} return a, nil } @@ -883,8 +883,28 @@ func _1622184614_add_default_sync_periodUpSql() (*asset, error) { return nil, err } - info := bindataFileInfo{name: "1622184614_add_default_sync_period.up.sql", size: 125, mode: os.FileMode(0644), modTime: time.Unix(1625056983, 0)} - a := &asset{bytes: bytes, info: info, digest: [32]uint8{0x60, 0x39, 0xeb, 0x8f, 0xdc, 0x1, 0x56, 0xc1, 0x9b, 0xaa, 0xda, 0x44, 0xe0, 0xdb, 0xda, 0x2c, 0xe7, 0x71, 0x8d, 0xbc, 0xc1, 0x9a, 0x4f, 0x48, 0xe0, 0x5e, 0x81, 0x1e, 0x8e, 0x6a, 0x4d, 0x3}} + info := bindataFileInfo{name: "1622184614_add_default_sync_period.up.sql", size: 125, mode: os.FileMode(436), modTime: time.Unix(1623875362, 0)} + a := &asset{bytes: bytes, info: info} + return a, nil +} + +var __1625872445_user_statusUpSql = []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\x84\x8e\x41\x4b\xc3\x40\x10\x85\xef\xfb\x2b\x1e\x3d\x29\x78\xd0\x73\xf0\xb0\x49\xa6\x50\x9c\xee\x86\x75\x02\xf6\x14\x6a\xba\x48\x69\x4d\x43\x76\x16\xec\xbf\x97\x6a\x2b\x16\x04\xaf\x33\xdf\xf7\xde\xb3\x2c\x14\x20\xb6\x64\x42\x8a\xaa\xdb\xe1\x2d\xc1\xd6\x35\x2a\xcf\xed\xd2\xa1\xcf\xd3\x14\x07\xed\x72\x8a\x53\x97\x74\xad\x39\xa1\x64\x5f\x16\xe6\x3f\x33\xc5\x61\x73\x36\xba\x3c\x6e\xd6\x1a\x13\x4a\xef\x99\xac\x43\x4d\x73\xdb\xb2\x40\x42\x4b\x85\x69\x9b\xda\xca\xaf\x90\x67\x92\x3f\xed\x47\x3c\x14\xa6\x0a\x74\x82\xcf\xbd\xd7\xc0\x8d\x01\xc6\xfc\xba\xdf\xf6\xdd\x2e\x1e\x21\xf4\x22\x68\xc2\x62\x69\xc3\x0a\x4f\xb4\x82\x77\xa8\xbc\x9b\xf3\xa2\x12\x04\x6a\xd8\x56\x74\x67\x70\x49\xd1\xe3\x18\xb1\x70\x02\xe7\x05\xae\x65\xfe\x99\x79\x7f\xa2\xfa\xfd\xa1\xdf\x5d\xfd\xbf\xae\x39\xe9\xe1\xbd\xd3\xf8\xa1\xdf\x7d\x17\x67\x36\x33\xb7\x85\xf9\x0c\x00\x00\xff\xff\xa2\xed\xdb\xfc\x5f\x01\x00\x00") + +func _1625872445_user_statusUpSqlBytes() ([]byte, error) { + return bindataRead( + __1625872445_user_statusUpSql, + "1625872445_user_status.up.sql", + ) +} + +func _1625872445_user_statusUpSql() (*asset, error) { + bytes, err := _1625872445_user_statusUpSqlBytes() + if err != nil { + return nil, err + } + + info := bindataFileInfo{name: "1625872445_user_status.up.sql", size: 351, mode: os.FileMode(436), modTime: time.Unix(1626970348, 0)} + a := &asset{bytes: bytes, info: info} return a, nil } @@ -903,8 +923,8 @@ func docGo() (*asset, error) { return nil, err } - info := bindataFileInfo{name: "doc.go", size: 74, mode: os.FileMode(0644), modTime: time.Unix(1599559876, 0)} - a := &asset{bytes: bytes, info: info, digest: [32]uint8{0xde, 0x7c, 0x28, 0xcd, 0x47, 0xf2, 0xfa, 0x7c, 0x51, 0x2d, 0xd8, 0x38, 0xb, 0xb0, 0x34, 0x9d, 0x4c, 0x62, 0xa, 0x9e, 0x28, 0xc3, 0x31, 0x23, 0xd9, 0xbb, 0x89, 0x9f, 0xa0, 0x89, 0x1f, 0xe8}} + info := bindataFileInfo{name: "doc.go", size: 74, mode: os.FileMode(436), modTime: time.Unix(1619724270, 0)} + a := &asset{bytes: bytes, info: info} return a, nil } @@ -912,8 +932,8 @@ func docGo() (*asset, error) { // It returns an error if the asset could not be found or // could not be loaded. func Asset(name string) ([]byte, error) { - canonicalName := strings.Replace(name, "\\", "/", -1) - if f, ok := _bindata[canonicalName]; ok { + cannonicalName := strings.Replace(name, "\\", "/", -1) + if f, ok := _bindata[cannonicalName]; ok { a, err := f() if err != nil { return nil, fmt.Errorf("Asset %s can't read by error: %v", name, err) @@ -923,12 +943,6 @@ func Asset(name string) ([]byte, error) { return nil, fmt.Errorf("Asset %s not found", name) } -// AssetString returns the asset contents as a string (instead of a []byte). -func AssetString(name string) (string, error) { - data, err := Asset(name) - return string(data), err -} - // MustAsset is like Asset but panics when Asset would return an error. // It simplifies safe initialization of global variables. func MustAsset(name string) []byte { @@ -940,18 +954,12 @@ func MustAsset(name string) []byte { return a } -// MustAssetString is like AssetString but panics when Asset would return an -// error. It simplifies safe initialization of global variables. -func MustAssetString(name string) string { - return string(MustAsset(name)) -} - // AssetInfo loads and returns the asset info for the given name. // It returns an error if the asset could not be found or // could not be loaded. func AssetInfo(name string) (os.FileInfo, error) { - canonicalName := strings.Replace(name, "\\", "/", -1) - if f, ok := _bindata[canonicalName]; ok { + cannonicalName := strings.Replace(name, "\\", "/", -1) + if f, ok := _bindata[cannonicalName]; ok { a, err := f() if err != nil { return nil, fmt.Errorf("AssetInfo %s can't read by error: %v", name, err) @@ -961,33 +969,6 @@ func AssetInfo(name string) (os.FileInfo, error) { return nil, fmt.Errorf("AssetInfo %s not found", name) } -// AssetDigest returns the digest of the file with the given name. It returns an -// error if the asset could not be found or the digest could not be loaded. -func AssetDigest(name string) ([sha256.Size]byte, error) { - canonicalName := strings.Replace(name, "\\", "/", -1) - if f, ok := _bindata[canonicalName]; ok { - a, err := f() - if err != nil { - return [sha256.Size]byte{}, fmt.Errorf("AssetDigest %s can't read by error: %v", name, err) - } - return a.digest, nil - } - return [sha256.Size]byte{}, fmt.Errorf("AssetDigest %s not found", name) -} - -// Digests returns a map of all known files and their checksums. -func Digests() (map[string][sha256.Size]byte, error) { - mp := make(map[string][sha256.Size]byte, len(_bindata)) - for name := range _bindata { - a, err := _bindata[name]() - if err != nil { - return nil, err - } - mp[name] = a.digest - } - return mp, nil -} - // AssetNames returns the names of the assets. func AssetNames() []string { names := make([]string, 0, len(_bindata)) @@ -1000,83 +981,45 @@ func AssetNames() []string { // _bindata is a table, holding each asset generator, mapped to its name. var _bindata = map[string]func() (*asset, error){ "0001_app.down.sql": _0001_appDownSql, - "0001_app.up.sql": _0001_appUpSql, - "0002_tokens.down.sql": _0002_tokensDownSql, - "0002_tokens.up.sql": _0002_tokensUpSql, - "0003_settings.down.sql": _0003_settingsDownSql, - "0003_settings.up.sql": _0003_settingsUpSql, - "0004_pending_stickers.down.sql": _0004_pending_stickersDownSql, - "0004_pending_stickers.up.sql": _0004_pending_stickersUpSql, - "0005_waku_mode.down.sql": _0005_waku_modeDownSql, - "0005_waku_mode.up.sql": _0005_waku_modeUpSql, - "0006_appearance.up.sql": _0006_appearanceUpSql, - "0007_enable_waku_default.up.sql": _0007_enable_waku_defaultUpSql, - "0008_add_push_notifications.up.sql": _0008_add_push_notificationsUpSql, - "0009_enable_sending_push_notifications.down.sql": _0009_enable_sending_push_notificationsDownSql, - "0009_enable_sending_push_notifications.up.sql": _0009_enable_sending_push_notificationsUpSql, - "0010_add_block_mentions.down.sql": _0010_add_block_mentionsDownSql, - "0010_add_block_mentions.up.sql": _0010_add_block_mentionsUpSql, - "0011_allow_webview_permission_requests.down.sql": _0011_allow_webview_permission_requestsDownSql, - "0011_allow_webview_permission_requests.up.sql": _0011_allow_webview_permission_requestsUpSql, - "0012_pending_transactions.down.sql": _0012_pending_transactionsDownSql, - "0012_pending_transactions.up.sql": _0012_pending_transactionsUpSql, - "0013_favourites.down.sql": _0013_favouritesDownSql, - "0013_favourites.up.sql": _0013_favouritesUpSql, - "0014_add_use_mailservers.down.sql": _0014_add_use_mailserversDownSql, - "0014_add_use_mailservers.up.sql": _0014_add_use_mailserversUpSql, - "0015_link_previews.down.sql": _0015_link_previewsDownSql, - "0015_link_previews.up.sql": _0015_link_previewsUpSql, - "0016_local_notifications_preferences.down.sql": _0016_local_notifications_preferencesDownSql, - "0016_local_notifications_preferences.up.sql": _0016_local_notifications_preferencesUpSql, - "0017_bookmarks.down.sql": _0017_bookmarksDownSql, - "0017_bookmarks.up.sql": _0017_bookmarksUpSql, - "0018_profile_pictures_visibility.up.sql": _0018_profile_pictures_visibilityUpSql, - "0019_blocks_ranges_extra_data.up.sql": _0019_blocks_ranges_extra_dataUpSql, - "0020_metrics.up.sql": _0020_metricsUpSql, - "0021_add_session_id_to_metrics.up.sql": _0021_add_session_id_to_metricsUpSql, - "0022_pending_transfers.up.sql": _0022_pending_transfersUpSql, - "1618237885_settings_anon_metrics_should_send.up.sql": _1618237885_settings_anon_metrics_should_sendUpSql, - "1618395756_contacts_only.up.sql": _1618395756_contacts_onlyUpSql, - "1622184614_add_default_sync_period.up.sql": _1622184614_add_default_sync_periodUpSql, - + "1625872445_user_status.up.sql": _1625872445_user_statusUpSql, "doc.go": docGo, } @@ -1089,15 +1032,15 @@ var _bindata = map[string]func() (*asset, error){ // img/ // a.png // b.png -// then AssetDir("data") would return []string{"foo.txt", "img"}, -// AssetDir("data/img") would return []string{"a.png", "b.png"}, -// AssetDir("foo.txt") and AssetDir("notexist") would return an error, and +// then AssetDir("data") would return []string{"foo.txt", "img"} +// AssetDir("data/img") would return []string{"a.png", "b.png"} +// AssetDir("foo.txt") and AssetDir("notexist") would return an error // AssetDir("") will return []string{"data"}. func AssetDir(name string) ([]string, error) { node := _bintree if len(name) != 0 { - canonicalName := strings.Replace(name, "\\", "/", -1) - pathList := strings.Split(canonicalName, "/") + cannonicalName := strings.Replace(name, "\\", "/", -1) + pathList := strings.Split(cannonicalName, "/") for _, p := range pathList { node = node.Children[p] if node == nil { @@ -1119,51 +1062,51 @@ type bintree struct { Func func() (*asset, error) Children map[string]*bintree } - var _bintree = &bintree{nil, map[string]*bintree{ - "0001_app.down.sql": &bintree{_0001_appDownSql, map[string]*bintree{}}, - "0001_app.up.sql": &bintree{_0001_appUpSql, map[string]*bintree{}}, - "0002_tokens.down.sql": &bintree{_0002_tokensDownSql, map[string]*bintree{}}, - "0002_tokens.up.sql": &bintree{_0002_tokensUpSql, map[string]*bintree{}}, - "0003_settings.down.sql": &bintree{_0003_settingsDownSql, map[string]*bintree{}}, - "0003_settings.up.sql": &bintree{_0003_settingsUpSql, map[string]*bintree{}}, - "0004_pending_stickers.down.sql": &bintree{_0004_pending_stickersDownSql, map[string]*bintree{}}, - "0004_pending_stickers.up.sql": &bintree{_0004_pending_stickersUpSql, map[string]*bintree{}}, - "0005_waku_mode.down.sql": &bintree{_0005_waku_modeDownSql, map[string]*bintree{}}, - "0005_waku_mode.up.sql": &bintree{_0005_waku_modeUpSql, map[string]*bintree{}}, - "0006_appearance.up.sql": &bintree{_0006_appearanceUpSql, map[string]*bintree{}}, - "0007_enable_waku_default.up.sql": &bintree{_0007_enable_waku_defaultUpSql, map[string]*bintree{}}, - "0008_add_push_notifications.up.sql": &bintree{_0008_add_push_notificationsUpSql, map[string]*bintree{}}, - "0009_enable_sending_push_notifications.down.sql": &bintree{_0009_enable_sending_push_notificationsDownSql, map[string]*bintree{}}, - "0009_enable_sending_push_notifications.up.sql": &bintree{_0009_enable_sending_push_notificationsUpSql, map[string]*bintree{}}, - "0010_add_block_mentions.down.sql": &bintree{_0010_add_block_mentionsDownSql, map[string]*bintree{}}, - "0010_add_block_mentions.up.sql": &bintree{_0010_add_block_mentionsUpSql, map[string]*bintree{}}, - "0011_allow_webview_permission_requests.down.sql": &bintree{_0011_allow_webview_permission_requestsDownSql, map[string]*bintree{}}, - "0011_allow_webview_permission_requests.up.sql": &bintree{_0011_allow_webview_permission_requestsUpSql, map[string]*bintree{}}, - "0012_pending_transactions.down.sql": &bintree{_0012_pending_transactionsDownSql, map[string]*bintree{}}, - "0012_pending_transactions.up.sql": &bintree{_0012_pending_transactionsUpSql, map[string]*bintree{}}, - "0013_favourites.down.sql": &bintree{_0013_favouritesDownSql, map[string]*bintree{}}, - "0013_favourites.up.sql": &bintree{_0013_favouritesUpSql, map[string]*bintree{}}, - "0014_add_use_mailservers.down.sql": &bintree{_0014_add_use_mailserversDownSql, map[string]*bintree{}}, - "0014_add_use_mailservers.up.sql": &bintree{_0014_add_use_mailserversUpSql, map[string]*bintree{}}, - "0015_link_previews.down.sql": &bintree{_0015_link_previewsDownSql, map[string]*bintree{}}, - "0015_link_previews.up.sql": &bintree{_0015_link_previewsUpSql, map[string]*bintree{}}, - "0016_local_notifications_preferences.down.sql": &bintree{_0016_local_notifications_preferencesDownSql, map[string]*bintree{}}, - "0016_local_notifications_preferences.up.sql": &bintree{_0016_local_notifications_preferencesUpSql, map[string]*bintree{}}, - "0017_bookmarks.down.sql": &bintree{_0017_bookmarksDownSql, map[string]*bintree{}}, - "0017_bookmarks.up.sql": &bintree{_0017_bookmarksUpSql, map[string]*bintree{}}, - "0018_profile_pictures_visibility.up.sql": &bintree{_0018_profile_pictures_visibilityUpSql, map[string]*bintree{}}, - "0019_blocks_ranges_extra_data.up.sql": &bintree{_0019_blocks_ranges_extra_dataUpSql, map[string]*bintree{}}, - "0020_metrics.up.sql": &bintree{_0020_metricsUpSql, map[string]*bintree{}}, - "0021_add_session_id_to_metrics.up.sql": &bintree{_0021_add_session_id_to_metricsUpSql, map[string]*bintree{}}, - "0022_pending_transfers.up.sql": &bintree{_0022_pending_transfersUpSql, map[string]*bintree{}}, + "0001_app.down.sql": &bintree{_0001_appDownSql, map[string]*bintree{}}, + "0001_app.up.sql": &bintree{_0001_appUpSql, map[string]*bintree{}}, + "0002_tokens.down.sql": &bintree{_0002_tokensDownSql, map[string]*bintree{}}, + "0002_tokens.up.sql": &bintree{_0002_tokensUpSql, map[string]*bintree{}}, + "0003_settings.down.sql": &bintree{_0003_settingsDownSql, map[string]*bintree{}}, + "0003_settings.up.sql": &bintree{_0003_settingsUpSql, map[string]*bintree{}}, + "0004_pending_stickers.down.sql": &bintree{_0004_pending_stickersDownSql, map[string]*bintree{}}, + "0004_pending_stickers.up.sql": &bintree{_0004_pending_stickersUpSql, map[string]*bintree{}}, + "0005_waku_mode.down.sql": &bintree{_0005_waku_modeDownSql, map[string]*bintree{}}, + "0005_waku_mode.up.sql": &bintree{_0005_waku_modeUpSql, map[string]*bintree{}}, + "0006_appearance.up.sql": &bintree{_0006_appearanceUpSql, map[string]*bintree{}}, + "0007_enable_waku_default.up.sql": &bintree{_0007_enable_waku_defaultUpSql, map[string]*bintree{}}, + "0008_add_push_notifications.up.sql": &bintree{_0008_add_push_notificationsUpSql, map[string]*bintree{}}, + "0009_enable_sending_push_notifications.down.sql": &bintree{_0009_enable_sending_push_notificationsDownSql, map[string]*bintree{}}, + "0009_enable_sending_push_notifications.up.sql": &bintree{_0009_enable_sending_push_notificationsUpSql, map[string]*bintree{}}, + "0010_add_block_mentions.down.sql": &bintree{_0010_add_block_mentionsDownSql, map[string]*bintree{}}, + "0010_add_block_mentions.up.sql": &bintree{_0010_add_block_mentionsUpSql, map[string]*bintree{}}, + "0011_allow_webview_permission_requests.down.sql": &bintree{_0011_allow_webview_permission_requestsDownSql, map[string]*bintree{}}, + "0011_allow_webview_permission_requests.up.sql": &bintree{_0011_allow_webview_permission_requestsUpSql, map[string]*bintree{}}, + "0012_pending_transactions.down.sql": &bintree{_0012_pending_transactionsDownSql, map[string]*bintree{}}, + "0012_pending_transactions.up.sql": &bintree{_0012_pending_transactionsUpSql, map[string]*bintree{}}, + "0013_favourites.down.sql": &bintree{_0013_favouritesDownSql, map[string]*bintree{}}, + "0013_favourites.up.sql": &bintree{_0013_favouritesUpSql, map[string]*bintree{}}, + "0014_add_use_mailservers.down.sql": &bintree{_0014_add_use_mailserversDownSql, map[string]*bintree{}}, + "0014_add_use_mailservers.up.sql": &bintree{_0014_add_use_mailserversUpSql, map[string]*bintree{}}, + "0015_link_previews.down.sql": &bintree{_0015_link_previewsDownSql, map[string]*bintree{}}, + "0015_link_previews.up.sql": &bintree{_0015_link_previewsUpSql, map[string]*bintree{}}, + "0016_local_notifications_preferences.down.sql": &bintree{_0016_local_notifications_preferencesDownSql, map[string]*bintree{}}, + "0016_local_notifications_preferences.up.sql": &bintree{_0016_local_notifications_preferencesUpSql, map[string]*bintree{}}, + "0017_bookmarks.down.sql": &bintree{_0017_bookmarksDownSql, map[string]*bintree{}}, + "0017_bookmarks.up.sql": &bintree{_0017_bookmarksUpSql, map[string]*bintree{}}, + "0018_profile_pictures_visibility.up.sql": &bintree{_0018_profile_pictures_visibilityUpSql, map[string]*bintree{}}, + "0019_blocks_ranges_extra_data.up.sql": &bintree{_0019_blocks_ranges_extra_dataUpSql, map[string]*bintree{}}, + "0020_metrics.up.sql": &bintree{_0020_metricsUpSql, map[string]*bintree{}}, + "0021_add_session_id_to_metrics.up.sql": &bintree{_0021_add_session_id_to_metricsUpSql, map[string]*bintree{}}, + "0022_pending_transfers.up.sql": &bintree{_0022_pending_transfersUpSql, map[string]*bintree{}}, "1618237885_settings_anon_metrics_should_send.up.sql": &bintree{_1618237885_settings_anon_metrics_should_sendUpSql, map[string]*bintree{}}, - "1618395756_contacts_only.up.sql": &bintree{_1618395756_contacts_onlyUpSql, map[string]*bintree{}}, - "1622184614_add_default_sync_period.up.sql": &bintree{_1622184614_add_default_sync_periodUpSql, map[string]*bintree{}}, + "1618395756_contacts_only.up.sql": &bintree{_1618395756_contacts_onlyUpSql, map[string]*bintree{}}, + "1622184614_add_default_sync_period.up.sql": &bintree{_1622184614_add_default_sync_periodUpSql, map[string]*bintree{}}, + "1625872445_user_status.up.sql": &bintree{_1625872445_user_statusUpSql, map[string]*bintree{}}, "doc.go": &bintree{docGo, map[string]*bintree{}}, }} -// RestoreAsset restores an asset under the given directory. +// RestoreAsset restores an asset under the given directory func RestoreAsset(dir, name string) error { data, err := Asset(name) if err != nil { @@ -1181,10 +1124,14 @@ func RestoreAsset(dir, name string) error { if err != nil { return err } - return os.Chtimes(_filePath(dir, name), info.ModTime(), info.ModTime()) + err = os.Chtimes(_filePath(dir, name), info.ModTime(), info.ModTime()) + if err != nil { + return err + } + return nil } -// RestoreAssets restores an asset under the given directory recursively. +// RestoreAssets restores an asset under the given directory recursively func RestoreAssets(dir, name string) error { children, err := AssetDir(name) // File @@ -1202,6 +1149,7 @@ func RestoreAssets(dir, name string) error { } func _filePath(dir, name string) string { - canonicalName := strings.Replace(name, "\\", "/", -1) - return filepath.Join(append([]string{dir}, strings.Split(canonicalName, "/")...)...) + cannonicalName := strings.Replace(name, "\\", "/", -1) + return filepath.Join(append([]string{dir}, strings.Split(cannonicalName, "/")...)...) } + diff --git a/appdatabase/migrations/sql/1625872445_user_status.up.sql b/appdatabase/migrations/sql/1625872445_user_status.up.sql new file mode 100644 index 000000000..c23135ff8 --- /dev/null +++ b/appdatabase/migrations/sql/1625872445_user_status.up.sql @@ -0,0 +1,9 @@ +ALTER TABLE settings ADD COLUMN current_user_status BLOB; +ALTER TABLE settings ADD COLUMN send_status_updates BOOLEAN DEFAULT TRUE; +UPDATE settings SET send_status_updates = 1; +CREATE TABLE status_updates ( + public_key TEXT PRIMARY KEY ON CONFLICT REPLACE, + status_type INT NOT NULL DEFAULT 0, + clock INT NOT NULL, + custom_text TEXT DEFAULT "" +); diff --git a/multiaccounts/accounts/database.go b/multiaccounts/accounts/database.go index 85abb3e83..b053c9195 100644 --- a/multiaccounts/accounts/database.go +++ b/multiaccounts/accounts/database.go @@ -118,6 +118,8 @@ type Settings struct { WalletVisibleTokens *json.RawMessage `json:"wallet/visible-tokens,omitempty"` WakuBloomFilterMode bool `json:"waku-bloom-filter-mode,omitempty"` WebViewAllowPermissionRequests bool `json:"webview-allow-permission-requests?,omitempty"` + SendStatusUpdates bool `json:"send-status-updates?,omitempty"` + CurrentUserStatus *json.RawMessage `json:"current-user-status"` } func NewDB(db *sql.DB) *Database { @@ -386,6 +388,15 @@ func (db *Database) SaveSetting(setting string, value interface{}) error { return ErrInvalidConfig } update, err = db.db.Prepare("UPDATE settings SET anon_metrics_should_send = ? WHERE synthetic_id = 'id'") + case "current-user-status": + value = &sqlite.JSONBlob{Data: value} + update, err = db.db.Prepare("UPDATE settings SET current_user_status = ? WHERE synthetic_id = 'id'") + case "send-status-updates?": + _, ok := value.(bool) + if !ok { + return ErrInvalidConfig + } + update, err = db.db.Prepare("UPDATE settings SET send_status_updates = ? WHERE synthetic_id = 'id'") default: return ErrInvalidConfig } @@ -402,7 +413,7 @@ func (db *Database) GetNodeConfig(nodecfg interface{}) error { func (db *Database) GetSettings() (Settings, error) { var s Settings - err := db.db.QueryRow("SELECT address, anon_metrics_should_send, chaos_mode, currency, current_network, custom_bootnodes, custom_bootnodes_enabled, dapps_address, eip1581_address, fleet, hide_home_tooltip, installation_id, key_uid, keycard_instance_uid, keycard_paired_on, keycard_pairing, last_updated, latest_derived_path, link_preview_request_enabled, link_previews_enabled_sites, log_level, mnemonic, name, networks, notifications_enabled, push_notifications_server_enabled, push_notifications_from_contacts_only, remote_push_notifications_enabled, send_push_notifications, push_notifications_block_mentions, photo_path, pinned_mailservers, preferred_name, preview_privacy, public_key, remember_syncing_choice, signing_phrase, stickers_packs_installed, stickers_packs_pending, stickers_recent_stickers, syncing_on_mobile_network, default_sync_period, use_mailservers, messages_from_contacts_only, usernames, appearance, profile_pictures_visibility, wallet_root_address, wallet_set_up_passed, wallet_visible_tokens, waku_bloom_filter_mode, webview_allow_permission_requests FROM settings WHERE synthetic_id = 'id'").Scan( + err := db.db.QueryRow("SELECT address, anon_metrics_should_send, chaos_mode, currency, current_network, custom_bootnodes, custom_bootnodes_enabled, dapps_address, eip1581_address, fleet, hide_home_tooltip, installation_id, key_uid, keycard_instance_uid, keycard_paired_on, keycard_pairing, last_updated, latest_derived_path, link_preview_request_enabled, link_previews_enabled_sites, log_level, mnemonic, name, networks, notifications_enabled, push_notifications_server_enabled, push_notifications_from_contacts_only, remote_push_notifications_enabled, send_push_notifications, push_notifications_block_mentions, photo_path, pinned_mailservers, preferred_name, preview_privacy, public_key, remember_syncing_choice, signing_phrase, stickers_packs_installed, stickers_packs_pending, stickers_recent_stickers, syncing_on_mobile_network, default_sync_period, use_mailservers, messages_from_contacts_only, usernames, appearance, profile_pictures_visibility, wallet_root_address, wallet_set_up_passed, wallet_visible_tokens, waku_bloom_filter_mode, webview_allow_permission_requests, current_user_status, send_status_updates FROM settings WHERE synthetic_id = 'id'").Scan( &s.Address, &s.AnonMetricsShouldSend, &s.ChaosMode, @@ -454,7 +465,10 @@ func (db *Database) GetSettings() (Settings, error) { &s.WalletSetUpPassed, &s.WalletVisibleTokens, &s.WakuBloomFilterMode, - &s.WebViewAllowPermissionRequests) + &s.WebViewAllowPermissionRequests, + &sqlite.JSONBlob{Data: &s.CurrentUserStatus}, + &s.SendStatusUpdates, + ) return s, err } @@ -650,3 +664,17 @@ func (db *Database) AddressExists(address types.Address) (exists bool, err error err = db.db.QueryRow("SELECT EXISTS (SELECT 1 FROM accounts WHERE address = ?)", address).Scan(&exists) return exists, err } + +func (db *Database) GetCurrentStatus(status interface{}) error { + err := db.db.QueryRow("SELECT current_user_status FROM settings WHERE synthetic_id = 'id'").Scan(&sqlite.JSONBlob{Data: &status}) + if err == sql.ErrNoRows { + return nil + } + return err +} + +func (db *Database) ShouldBroadcastUserStatus() (bool, error) { + var result bool + err := db.db.QueryRow("SELECT send_status_updates FROM settings WHERE synthetic_id = 'id'").Scan(&result) + return result, err +} diff --git a/multiaccounts/accounts/database_test.go b/multiaccounts/accounts/database_test.go index fa3cc24db..90200abd2 100644 --- a/multiaccounts/accounts/database_test.go +++ b/multiaccounts/accounts/database_test.go @@ -40,6 +40,7 @@ var ( DefaultSyncPeriod: 86400, UseMailservers: true, LinkPreviewRequestEnabled: true, + SendStatusUpdates: true, WalletRootAddress: types.HexToAddress("0x3B591fd819F86D0A6a2EF2Bcb94f77807a7De1a6")} ) diff --git a/multiaccounts/migrations/bindata.go b/multiaccounts/migrations/bindata.go index e5dc39f99..c4a3894c1 100644 --- a/multiaccounts/migrations/bindata.go +++ b/multiaccounts/migrations/bindata.go @@ -1,19 +1,19 @@ -// Code generated by go-bindata. DO NOT EDIT. +// Code generated by go-bindata. // sources: -// 0001_accounts.down.sql (21B) -// 0001_accounts.up.sql (163B) -// 1605007189_identity_images.down.sql (29B) -// 1605007189_identity_images.up.sql (268B) -// 1606224181_drop_photo_path_from_accounts.down.sql (892B) -// 1606224181_drop_photo_path_from_accounts.up.sql (866B) -// doc.go (74B) +// 0001_accounts.down.sql +// 0001_accounts.up.sql +// 1605007189_identity_images.down.sql +// 1605007189_identity_images.up.sql +// 1606224181_drop_photo_path_from_accounts.down.sql +// 1606224181_drop_photo_path_from_accounts.up.sql +// doc.go +// DO NOT EDIT! package migrations import ( "bytes" "compress/gzip" - "crypto/sha256" "fmt" "io" "io/ioutil" @@ -26,7 +26,7 @@ import ( func bindataRead(data []byte, name string) ([]byte, error) { gz, err := gzip.NewReader(bytes.NewBuffer(data)) if err != nil { - return nil, fmt.Errorf("read %q: %v", name, err) + return nil, fmt.Errorf("Read %q: %v", name, err) } var buf bytes.Buffer @@ -34,7 +34,7 @@ func bindataRead(data []byte, name string) ([]byte, error) { clErr := gz.Close() if err != nil { - return nil, fmt.Errorf("read %q: %v", name, err) + return nil, fmt.Errorf("Read %q: %v", name, err) } if clErr != nil { return nil, err @@ -44,9 +44,8 @@ func bindataRead(data []byte, name string) ([]byte, error) { } type asset struct { - bytes []byte - info os.FileInfo - digest [sha256.Size]byte + bytes []byte + info os.FileInfo } type bindataFileInfo struct { @@ -90,8 +89,8 @@ func _0001_accountsDownSql() (*asset, error) { return nil, err } - info := bindataFileInfo{name: "0001_accounts.down.sql", size: 21, mode: os.FileMode(0644), modTime: time.Unix(1599559876, 0)} - a := &asset{bytes: bytes, info: info, digest: [32]uint8{0xd2, 0x61, 0x4c, 0x18, 0xfc, 0xc, 0xdf, 0x5c, 0x1f, 0x5e, 0xd3, 0xbd, 0xfa, 0x12, 0x5e, 0x8d, 0x8d, 0x8b, 0xb9, 0x5f, 0x99, 0x46, 0x63, 0xa5, 0xe3, 0xa6, 0x8a, 0x4, 0xf1, 0x73, 0x8a, 0xe9}} + info := bindataFileInfo{name: "0001_accounts.down.sql", size: 21, mode: os.FileMode(436), modTime: time.Unix(1619724270, 0)} + a := &asset{bytes: bytes, info: info} return a, nil } @@ -110,8 +109,8 @@ func _0001_accountsUpSql() (*asset, error) { return nil, err } - info := bindataFileInfo{name: "0001_accounts.up.sql", size: 163, mode: os.FileMode(0644), modTime: time.Unix(1599559876, 0)} - a := &asset{bytes: bytes, info: info, digest: [32]uint8{0xf2, 0xfa, 0x99, 0x8e, 0x96, 0xb3, 0x13, 0x6c, 0x1f, 0x6, 0x27, 0xc5, 0xd2, 0xd4, 0xe0, 0xa5, 0x26, 0x82, 0xa7, 0x26, 0xf2, 0x68, 0x9d, 0xed, 0x9c, 0x3d, 0xbb, 0xdc, 0x37, 0x28, 0xbc, 0x1}} + info := bindataFileInfo{name: "0001_accounts.up.sql", size: 163, mode: os.FileMode(436), modTime: time.Unix(1619724270, 0)} + a := &asset{bytes: bytes, info: info} return a, nil } @@ -130,8 +129,8 @@ func _1605007189_identity_imagesDownSql() (*asset, error) { return nil, err } - info := bindataFileInfo{name: "1605007189_identity_images.down.sql", size: 29, mode: os.FileMode(0644), modTime: time.Unix(1617280156, 0)} - a := &asset{bytes: bytes, info: info, digest: [32]uint8{0x2f, 0xcf, 0xa7, 0xae, 0xd5, 0x4f, 0xcd, 0x14, 0x63, 0x9, 0xbe, 0x39, 0x49, 0x18, 0x96, 0xb2, 0xa3, 0x8, 0x7d, 0x41, 0xdb, 0x50, 0x5d, 0xf5, 0x4d, 0xa2, 0xd, 0x8f, 0x57, 0x79, 0x77, 0x67}} + info := bindataFileInfo{name: "1605007189_identity_images.down.sql", size: 29, mode: os.FileMode(436), modTime: time.Unix(1619724270, 0)} + a := &asset{bytes: bytes, info: info} return a, nil } @@ -150,8 +149,8 @@ func _1605007189_identity_imagesUpSql() (*asset, error) { return nil, err } - info := bindataFileInfo{name: "1605007189_identity_images.up.sql", size: 268, mode: os.FileMode(0644), modTime: time.Unix(1617280156, 0)} - a := &asset{bytes: bytes, info: info, digest: [32]uint8{0x50, 0xb6, 0xc1, 0x5c, 0x76, 0x72, 0x6b, 0x22, 0x34, 0xdc, 0x96, 0xdc, 0x2b, 0xfd, 0x2d, 0xbe, 0xcc, 0x1e, 0xd4, 0x5, 0x93, 0xd, 0xc2, 0x51, 0xf3, 0x1a, 0xef, 0x2b, 0x26, 0xa4, 0xeb, 0x65}} + info := bindataFileInfo{name: "1605007189_identity_images.up.sql", size: 268, mode: os.FileMode(436), modTime: time.Unix(1619724270, 0)} + a := &asset{bytes: bytes, info: info} return a, nil } @@ -170,8 +169,8 @@ func _1606224181_drop_photo_path_from_accountsDownSql() (*asset, error) { return nil, err } - info := bindataFileInfo{name: "1606224181_drop_photo_path_from_accounts.down.sql", size: 892, mode: os.FileMode(0644), modTime: time.Unix(1617280156, 0)} - a := &asset{bytes: bytes, info: info, digest: [32]uint8{0x90, 0x24, 0x17, 0x7, 0x80, 0x93, 0x6f, 0x8d, 0x5d, 0xaa, 0x8c, 0x79, 0x15, 0x5d, 0xb3, 0x19, 0xd7, 0xd8, 0x39, 0xf9, 0x3a, 0x63, 0x8f, 0x81, 0x15, 0xb6, 0xd6, 0x9a, 0x37, 0xa8, 0x8e, 0x9b}} + info := bindataFileInfo{name: "1606224181_drop_photo_path_from_accounts.down.sql", size: 892, mode: os.FileMode(436), modTime: time.Unix(1619724270, 0)} + a := &asset{bytes: bytes, info: info} return a, nil } @@ -190,8 +189,8 @@ func _1606224181_drop_photo_path_from_accountsUpSql() (*asset, error) { return nil, err } - info := bindataFileInfo{name: "1606224181_drop_photo_path_from_accounts.up.sql", size: 866, mode: os.FileMode(0644), modTime: time.Unix(1617280156, 0)} - a := &asset{bytes: bytes, info: info, digest: [32]uint8{0xff, 0x4c, 0x97, 0xee, 0xef, 0x82, 0xb8, 0x6c, 0x71, 0xbb, 0x50, 0x7b, 0xe6, 0xd9, 0x22, 0x31, 0x7c, 0x1a, 0xfe, 0x91, 0x28, 0xf6, 0x6, 0x36, 0xe, 0xb1, 0xf1, 0xc8, 0x25, 0xac, 0x7e, 0xd6}} + info := bindataFileInfo{name: "1606224181_drop_photo_path_from_accounts.up.sql", size: 866, mode: os.FileMode(436), modTime: time.Unix(1619724270, 0)} + a := &asset{bytes: bytes, info: info} return a, nil } @@ -210,8 +209,8 @@ func docGo() (*asset, error) { return nil, err } - info := bindataFileInfo{name: "doc.go", size: 74, mode: os.FileMode(0644), modTime: time.Unix(1599559876, 0)} - a := &asset{bytes: bytes, info: info, digest: [32]uint8{0xde, 0x7c, 0x28, 0xcd, 0x47, 0xf2, 0xfa, 0x7c, 0x51, 0x2d, 0xd8, 0x38, 0xb, 0xb0, 0x34, 0x9d, 0x4c, 0x62, 0xa, 0x9e, 0x28, 0xc3, 0x31, 0x23, 0xd9, 0xbb, 0x89, 0x9f, 0xa0, 0x89, 0x1f, 0xe8}} + info := bindataFileInfo{name: "doc.go", size: 74, mode: os.FileMode(436), modTime: time.Unix(1619724270, 0)} + a := &asset{bytes: bytes, info: info} return a, nil } @@ -219,8 +218,8 @@ func docGo() (*asset, error) { // It returns an error if the asset could not be found or // could not be loaded. func Asset(name string) ([]byte, error) { - canonicalName := strings.Replace(name, "\\", "/", -1) - if f, ok := _bindata[canonicalName]; ok { + cannonicalName := strings.Replace(name, "\\", "/", -1) + if f, ok := _bindata[cannonicalName]; ok { a, err := f() if err != nil { return nil, fmt.Errorf("Asset %s can't read by error: %v", name, err) @@ -230,12 +229,6 @@ func Asset(name string) ([]byte, error) { return nil, fmt.Errorf("Asset %s not found", name) } -// AssetString returns the asset contents as a string (instead of a []byte). -func AssetString(name string) (string, error) { - data, err := Asset(name) - return string(data), err -} - // MustAsset is like Asset but panics when Asset would return an error. // It simplifies safe initialization of global variables. func MustAsset(name string) []byte { @@ -247,18 +240,12 @@ func MustAsset(name string) []byte { return a } -// MustAssetString is like AssetString but panics when Asset would return an -// error. It simplifies safe initialization of global variables. -func MustAssetString(name string) string { - return string(MustAsset(name)) -} - // AssetInfo loads and returns the asset info for the given name. // It returns an error if the asset could not be found or // could not be loaded. func AssetInfo(name string) (os.FileInfo, error) { - canonicalName := strings.Replace(name, "\\", "/", -1) - if f, ok := _bindata[canonicalName]; ok { + cannonicalName := strings.Replace(name, "\\", "/", -1) + if f, ok := _bindata[cannonicalName]; ok { a, err := f() if err != nil { return nil, fmt.Errorf("AssetInfo %s can't read by error: %v", name, err) @@ -268,33 +255,6 @@ func AssetInfo(name string) (os.FileInfo, error) { return nil, fmt.Errorf("AssetInfo %s not found", name) } -// AssetDigest returns the digest of the file with the given name. It returns an -// error if the asset could not be found or the digest could not be loaded. -func AssetDigest(name string) ([sha256.Size]byte, error) { - canonicalName := strings.Replace(name, "\\", "/", -1) - if f, ok := _bindata[canonicalName]; ok { - a, err := f() - if err != nil { - return [sha256.Size]byte{}, fmt.Errorf("AssetDigest %s can't read by error: %v", name, err) - } - return a.digest, nil - } - return [sha256.Size]byte{}, fmt.Errorf("AssetDigest %s not found", name) -} - -// Digests returns a map of all known files and their checksums. -func Digests() (map[string][sha256.Size]byte, error) { - mp := make(map[string][sha256.Size]byte, len(_bindata)) - for name := range _bindata { - a, err := _bindata[name]() - if err != nil { - return nil, err - } - mp[name] = a.digest - } - return mp, nil -} - // AssetNames returns the names of the assets. func AssetNames() []string { names := make([]string, 0, len(_bindata)) @@ -307,17 +267,11 @@ func AssetNames() []string { // _bindata is a table, holding each asset generator, mapped to its name. var _bindata = map[string]func() (*asset, error){ "0001_accounts.down.sql": _0001_accountsDownSql, - "0001_accounts.up.sql": _0001_accountsUpSql, - "1605007189_identity_images.down.sql": _1605007189_identity_imagesDownSql, - "1605007189_identity_images.up.sql": _1605007189_identity_imagesUpSql, - "1606224181_drop_photo_path_from_accounts.down.sql": _1606224181_drop_photo_path_from_accountsDownSql, - "1606224181_drop_photo_path_from_accounts.up.sql": _1606224181_drop_photo_path_from_accountsUpSql, - "doc.go": docGo, } @@ -330,15 +284,15 @@ var _bindata = map[string]func() (*asset, error){ // img/ // a.png // b.png -// then AssetDir("data") would return []string{"foo.txt", "img"}, -// AssetDir("data/img") would return []string{"a.png", "b.png"}, -// AssetDir("foo.txt") and AssetDir("notexist") would return an error, and +// then AssetDir("data") would return []string{"foo.txt", "img"} +// AssetDir("data/img") would return []string{"a.png", "b.png"} +// AssetDir("foo.txt") and AssetDir("notexist") would return an error // AssetDir("") will return []string{"data"}. func AssetDir(name string) ([]string, error) { node := _bintree if len(name) != 0 { - canonicalName := strings.Replace(name, "\\", "/", -1) - pathList := strings.Split(canonicalName, "/") + cannonicalName := strings.Replace(name, "\\", "/", -1) + pathList := strings.Split(cannonicalName, "/") for _, p := range pathList { node = node.Children[p] if node == nil { @@ -360,18 +314,17 @@ type bintree struct { Func func() (*asset, error) Children map[string]*bintree } - var _bintree = &bintree{nil, map[string]*bintree{ - "0001_accounts.down.sql": &bintree{_0001_accountsDownSql, map[string]*bintree{}}, - "0001_accounts.up.sql": &bintree{_0001_accountsUpSql, map[string]*bintree{}}, - "1605007189_identity_images.down.sql": &bintree{_1605007189_identity_imagesDownSql, map[string]*bintree{}}, - "1605007189_identity_images.up.sql": &bintree{_1605007189_identity_imagesUpSql, map[string]*bintree{}}, + "0001_accounts.down.sql": &bintree{_0001_accountsDownSql, map[string]*bintree{}}, + "0001_accounts.up.sql": &bintree{_0001_accountsUpSql, map[string]*bintree{}}, + "1605007189_identity_images.down.sql": &bintree{_1605007189_identity_imagesDownSql, map[string]*bintree{}}, + "1605007189_identity_images.up.sql": &bintree{_1605007189_identity_imagesUpSql, map[string]*bintree{}}, "1606224181_drop_photo_path_from_accounts.down.sql": &bintree{_1606224181_drop_photo_path_from_accountsDownSql, map[string]*bintree{}}, - "1606224181_drop_photo_path_from_accounts.up.sql": &bintree{_1606224181_drop_photo_path_from_accountsUpSql, map[string]*bintree{}}, + "1606224181_drop_photo_path_from_accounts.up.sql": &bintree{_1606224181_drop_photo_path_from_accountsUpSql, map[string]*bintree{}}, "doc.go": &bintree{docGo, map[string]*bintree{}}, }} -// RestoreAsset restores an asset under the given directory. +// RestoreAsset restores an asset under the given directory func RestoreAsset(dir, name string) error { data, err := Asset(name) if err != nil { @@ -389,10 +342,14 @@ func RestoreAsset(dir, name string) error { if err != nil { return err } - return os.Chtimes(_filePath(dir, name), info.ModTime(), info.ModTime()) + err = os.Chtimes(_filePath(dir, name), info.ModTime(), info.ModTime()) + if err != nil { + return err + } + return nil } -// RestoreAssets restores an asset under the given directory recursively. +// RestoreAssets restores an asset under the given directory recursively func RestoreAssets(dir, name string) error { children, err := AssetDir(name) // File @@ -410,6 +367,7 @@ func RestoreAssets(dir, name string) error { } func _filePath(dir, name string) string { - canonicalName := strings.Replace(name, "\\", "/", -1) - return filepath.Join(append([]string{dir}, strings.Split(canonicalName, "/")...)...) + cannonicalName := strings.Replace(name, "\\", "/", -1) + return filepath.Join(append([]string{dir}, strings.Split(cannonicalName, "/")...)...) } + diff --git a/protocol/communities/community.go b/protocol/communities/community.go index dc5dbd918..f6fcf5bd7 100644 --- a/protocol/communities/community.go +++ b/protocol/communities/community.go @@ -854,6 +854,15 @@ func (o *Community) IDString() string { return types.EncodeHex(o.ID()) } +func (o *Community) StatusUpdatesChannelID() string { + return o.IDString() + "-ping" +} + +func (o *Community) DefaultFilters() []string { + cID := o.IDString() + return []string{cID, cID + "-ping"} +} + func (o *Community) PrivateKey() *ecdsa.PrivateKey { return o.config.PrivateKey } diff --git a/protocol/communities_messenger_test.go b/protocol/communities_messenger_test.go index ef504fcc1..bd4595c6b 100644 --- a/protocol/communities_messenger_test.go +++ b/protocol/communities_messenger_test.go @@ -4,6 +4,7 @@ import ( "bytes" "context" "crypto/ecdsa" + "encoding/json" "errors" "io/ioutil" "strings" @@ -16,6 +17,8 @@ import ( gethbridge "github.com/status-im/status-go/eth-node/bridge/geth" "github.com/status-im/status-go/eth-node/crypto" "github.com/status-im/status-go/eth-node/types" + "github.com/status-im/status-go/multiaccounts/accounts" + "github.com/status-im/status-go/params" "github.com/status-im/status-go/protocol/common" "github.com/status-im/status-go/protocol/communities" "github.com/status-im/status-go/protocol/protobuf" @@ -73,6 +76,36 @@ func (s *MessengerCommunitiesSuite) newMessengerWithOptions(shh types.Waku, priv err = m.Init() s.Require().NoError(err) + config := params.NodeConfig{ + NetworkID: 10, + DataDir: "test", + } + + networks := json.RawMessage("{}") + settings := accounts.Settings{ + Address: types.HexToAddress("0x1122334455667788990011223344556677889900"), + AnonMetricsShouldSend: false, + CurrentNetwork: "mainnet_rpc", + DappsAddress: types.HexToAddress("0x1122334455667788990011223344556677889900"), + InstallationID: "d3efcff6-cffa-560e-a547-21d3858cbc51", + KeyUID: "0x1122334455667788990011223344556677889900", + LatestDerivedPath: 0, + Name: "Test", + Networks: &networks, + PhotoPath: "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADIAAAAyCAIAAACRXR/mAAAAjklEQVR4nOzXwQmFMBAAUZXUYh32ZB32ZB02sxYQQSZGsod55/91WFgSS0RM+SyjA56ZRZhFmEWYRRT6h+M6G16zrxv6fdJpmUWYRbxsYr13dKfanpN0WmYRZhGzXz6AWYRZRIfbaX26fT9Jk07LLMIsosPt9I/dTDotswizCG+nhFmEWYRZhFnEHQAA///z1CFkYamgfQAAAABJRU5ErkJggg==", + PreviewPrivacy: false, + PublicKey: "0x04112233445566778899001122334455667788990011223344556677889900112233445566778899001122334455667788990011223344556677889900", + SigningPhrase: "yurt joey vibe", + SendPushNotifications: true, + ProfilePicturesVisibility: 1, + DefaultSyncPeriod: 86400, + UseMailservers: true, + LinkPreviewRequestEnabled: true, + SendStatusUpdates: true, + WalletRootAddress: types.HexToAddress("0x1122334455667788990011223344556677889900")} + + _ = m.settings.CreateSettings(settings, config) + return m } @@ -146,6 +179,7 @@ func (s *MessengerCommunitiesSuite) TestRetrieveCommunity() { } func (s *MessengerCommunitiesSuite) TestJoinCommunity() { + ctx := context.Background() description := &requests.CreateCommunity{ Membership: protobuf.CommunityPermissions_NO_MEMBERSHIP, @@ -245,7 +279,7 @@ func (s *MessengerCommunitiesSuite) TestJoinCommunity() { s.Require().Equal(community.IDString(), response.Messages()[0].CommunityID) // We join the org - response, err = s.alice.JoinCommunity(community.ID()) + response, err = s.alice.JoinCommunity(ctx, community.ID()) s.Require().NoError(err) s.Require().NotNil(response) s.Require().Len(response.Communities(), 1) @@ -440,8 +474,10 @@ func (s *MessengerCommunitiesSuite) TestPostToCommunityChat() { s.Require().Len(communities, 2) s.Require().Len(response.Communities(), 1) + ctx := context.Background() + // We join the org - response, err = s.alice.JoinCommunity(community.ID()) + response, err = s.alice.JoinCommunity(ctx, community.ID()) s.Require().NoError(err) s.Require().NotNil(response) s.Require().Len(response.Communities(), 1) @@ -454,7 +490,7 @@ func (s *MessengerCommunitiesSuite) TestPostToCommunityChat() { inputMessage.ContentType = protobuf.ChatMessage_TEXT_PLAIN inputMessage.Text = "some text" - _, err = s.alice.SendChatMessage(context.Background(), inputMessage) + _, err = s.alice.SendChatMessage(ctx, inputMessage) s.NoError(err) // Pull message and make sure org is received @@ -476,6 +512,8 @@ func (s *MessengerCommunitiesSuite) TestPostToCommunityChat() { } func (s *MessengerCommunitiesSuite) TestImportCommunity() { + ctx := context.Background() + description := &requests.CreateCommunity{ Membership: protobuf.CommunityPermissions_NO_MEMBERSHIP, Name: "status", @@ -503,7 +541,7 @@ func (s *MessengerCommunitiesSuite) TestImportCommunity() { privateKey, err := s.bob.ExportCommunity(community.ID()) s.Require().NoError(err) - _, err = s.alice.ImportCommunity(privateKey) + _, err = s.alice.ImportCommunity(ctx, privateKey) s.Require().NoError(err) // Invite user on bob side @@ -539,6 +577,8 @@ func (s *MessengerCommunitiesSuite) TestImportCommunity() { } func (s *MessengerCommunitiesSuite) TestRequestAccess() { + ctx := context.Background() + description := &requests.CreateCommunity{ Membership: protobuf.CommunityPermissions_ON_REQUEST, Name: "status", @@ -562,7 +602,7 @@ func (s *MessengerCommunitiesSuite) TestRequestAccess() { message.CommunityID = community.IDString() // We send a community link to alice - response, err = s.bob.SendChatMessage(context.Background(), message) + response, err = s.bob.SendChatMessage(ctx, message) s.Require().NoError(err) s.Require().NotNil(response) diff --git a/protocol/message_validator.go b/protocol/message_validator.go index 6b3dd6d04..703541b61 100644 --- a/protocol/message_validator.go +++ b/protocol/message_validator.go @@ -11,6 +11,7 @@ import ( ) const maxChatMessageTextLength = 4096 +const maxStatusMessageText = 128 // maxWhisperDrift is how many milliseconds we allow the clock value to differ // from whisperTimestamp @@ -39,6 +40,23 @@ func ValidateMembershipUpdateMessage(message *protocol.MembershipUpdateMessage, return nil } +func ValidateStatusUpdate(message protobuf.StatusUpdate) error { + if message.Clock == 0 { + return errors.New("clock can't be 0") + } + + if message.StatusType == protobuf.StatusUpdate_UNKNOWN_STATUS_TYPE { + return errors.New("unknown status type") + } + + if len([]rune(message.CustomText)) > maxStatusMessageText { + return fmt.Errorf("custom text shouldn't be longer than %d", maxStatusMessageText) + } + + return nil + +} + func ValidateEditMessage(message protobuf.EditMessage) error { if message.Clock == 0 { return errors.New("clock can't be 0") diff --git a/protocol/messenger.go b/protocol/messenger.go index 68b832352..288527a99 100644 --- a/protocol/messenger.go +++ b/protocol/messenger.go @@ -458,6 +458,8 @@ func (m *Messenger) Start() (*MessengerResponse, error) { m.watchConnectionChange() m.watchExpiredEmojis() m.watchIdentityImageChanges() + m.broadcastLatestUserStatus() + if err := m.cleanTopics(); err != nil { return nil, err } @@ -1021,7 +1023,7 @@ func (m *Messenger) Init() error { if err != nil { return err } - // uspert profile chat + // upsert profile chat err = m.ensureMyOwnProfileChat() if err != nil { return err @@ -2571,6 +2573,16 @@ func (m *Messenger) handleRetrievedMessages(chatWithMessages map[transport.Filte continue } + case protobuf.StatusUpdate: + p := msg.ParsedMessage.Interface().(protobuf.StatusUpdate) + logger.Debug("Handling StatusUpdate", zap.Any("message", p)) + err = m.HandleStatusUpdate(messageState, p) + if err != nil { + logger.Warn("failed to handle StatusMessage", zap.Error(err)) + allMessagesProcessed = false + continue + } + case protobuf.SyncInstallationContact: if !common.IsPubKeyEqual(messageState.CurrentMessageState.PublicKey, &m.identity.PublicKey) { logger.Warn("not coming from us, ignoring") @@ -2858,7 +2870,7 @@ func (m *Messenger) handleRetrievedMessages(chatWithMessages map[transport.Filte // Process any community changes for _, changes := range messageState.Response.CommunityChanges { if changes.ShouldMemberJoin { - response, err := m.joinCommunity(changes.Community.ID()) + response, err := m.joinCommunity(context.TODO(), changes.Community.ID()) if err != nil { logger.Error("cannot join community", zap.Error(err)) continue diff --git a/protocol/messenger_communities.go b/protocol/messenger_communities.go index dab35850b..c86bc9c5f 100644 --- a/protocol/messenger_communities.go +++ b/protocol/messenger_communities.go @@ -131,12 +131,12 @@ func (m *Messenger) JoinedCommunities() ([]*communities.Community, error) { return m.communitiesManager.Joined() } -func (m *Messenger) JoinCommunity(communityID types.HexBytes) (*MessengerResponse, error) { +func (m *Messenger) JoinCommunity(ctx context.Context, communityID types.HexBytes) (*MessengerResponse, error) { - return m.joinCommunity(communityID) + return m.joinCommunity(ctx, communityID) } -func (m *Messenger) joinCommunity(communityID types.HexBytes) (*MessengerResponse, error) { +func (m *Messenger) joinCommunity(ctx context.Context, communityID types.HexBytes) (*MessengerResponse, error) { response := &MessengerResponse{} community, err := m.communitiesManager.JoinCommunity(communityID) @@ -144,7 +144,7 @@ func (m *Messenger) joinCommunity(communityID types.HexBytes) (*MessengerRespons return nil, err } - chatIDs := []string{community.IDString()} + chatIDs := community.DefaultFilters() chats := CreateCommunityChats(community, m.getTimesource()) response.AddChats(chats) @@ -179,7 +179,16 @@ func (m *Messenger) joinCommunity(communityID types.HexBytes) (*MessengerRespons response.AddCommunity(community) - return response, m.saveChats(chats) + if err = m.saveChats(chats); err != nil { + return nil, err + } + + err = m.sendCurrentUserStatusToCommunity(ctx, community) + if err != nil { + return nil, err + } + + return response, nil } func (m *Messenger) SetMuted(communityID types.HexBytes, muted bool) error { @@ -461,6 +470,12 @@ func (m *Messenger) CreateCommunity(request *requests.CreateCommunity) (*Messeng return nil, err } + // Init the default community filters + _, err = m.transport.InitPublicFilters(community.DefaultFilters()) + if err != nil { + return nil, err + } + response := &MessengerResponse{} response.AddCommunity(community) @@ -487,14 +502,14 @@ func (m *Messenger) ExportCommunity(id types.HexBytes) (*ecdsa.PrivateKey, error return m.communitiesManager.ExportCommunity(id) } -func (m *Messenger) ImportCommunity(key *ecdsa.PrivateKey) (*MessengerResponse, error) { +func (m *Messenger) ImportCommunity(ctx context.Context, key *ecdsa.PrivateKey) (*MessengerResponse, error) { community, err := m.communitiesManager.ImportCommunity(key) if err != nil { return nil, err } // Load filters - _, err = m.transport.InitPublicFilters([]string{community.IDString()}) + _, err = m.transport.InitPublicFilters(community.DefaultFilters()) if err != nil { return nil, err } @@ -509,7 +524,7 @@ func (m *Messenger) ImportCommunity(key *ecdsa.PrivateKey) (*MessengerResponse, return nil, err } - return m.JoinCommunity(community.ID()) + return m.JoinCommunity(ctx, community.ID()) } func (m *Messenger) InviteUsersToCommunity(request *requests.InviteUsersToCommunity) (*MessengerResponse, error) { diff --git a/protocol/messenger_response.go b/protocol/messenger_response.go index bca1e43f0..67ee5c3fa 100644 --- a/protocol/messenger_response.go +++ b/protocol/messenger_response.go @@ -28,6 +28,8 @@ type MessengerResponse struct { activityCenterNotifications map[string]*ActivityCenterNotification messages map[string]*common.Message pinMessages map[string]*common.PinMessage + currentStatus *UserStatus + statusUpdates map[string]UserStatus } func (r *MessengerResponse) MarshalJSON() ([]byte, error) { @@ -48,6 +50,8 @@ func (r *MessengerResponse) MarshalJSON() ([]byte, error) { Notifications []*localnotifications.Notification `json:"notifications"` Communities []*communities.Community `json:"communities,omitempty"` ActivityCenterNotifications []*ActivityCenterNotification `json:"activityCenterNotifications,omitempty"` + CurrentStatus *UserStatus `json:"currentStatus,omitempty"` + StatusUpdates []UserStatus `json:"statusUpdates,omitempty"` }{ Contacts: r.Contacts, Installations: r.Installations, @@ -56,6 +60,7 @@ func (r *MessengerResponse) MarshalJSON() ([]byte, error) { CommunityChanges: r.CommunityChanges, RequestsToJoinCommunity: r.RequestsToJoinCommunity, Mailservers: r.Mailservers, + CurrentStatus: r.currentStatus, } responseItem.Messages = r.Messages() @@ -65,6 +70,7 @@ func (r *MessengerResponse) MarshalJSON() ([]byte, error) { responseItem.RemovedChats = r.RemovedChats() responseItem.ActivityCenterNotifications = r.ActivityCenterNotifications() responseItem.PinMessages = r.PinMessages() + responseItem.StatusUpdates = r.StatusUpdates() return json.Marshal(responseItem) } @@ -109,6 +115,15 @@ func (r *MessengerResponse) PinMessages() []*common.PinMessage { return pinMessages } +func (r *MessengerResponse) StatusUpdates() []UserStatus { + var userStatus []UserStatus + for pk, s := range r.statusUpdates { + s.PublicKey = pk + userStatus = append(userStatus, s) + } + return userStatus +} + func (r *MessengerResponse) IsEmpty() bool { return len(r.chats)+ len(r.messages)+ @@ -122,8 +137,10 @@ func (r *MessengerResponse) IsEmpty() bool { len(r.removedChats)+ len(r.Mailservers)+ len(r.notifications)+ + len(r.statusUpdates)+ len(r.activityCenterNotifications)+ - len(r.RequestsToJoinCommunity) == 0 + len(r.RequestsToJoinCommunity) == 0 && + r.currentStatus == nil } // Merge takes another response and appends the new Chats & new Messages and replaces @@ -246,6 +263,18 @@ func (r *MessengerResponse) AddPinMessages(pms []*common.PinMessage) { } } +func (r *MessengerResponse) SetCurrentStatus(status UserStatus) { + r.currentStatus = &status +} + +func (r *MessengerResponse) AddStatusUpdate(upd UserStatus) { + if r.statusUpdates == nil { + r.statusUpdates = make(map[string]UserStatus) + } + + r.statusUpdates[upd.PublicKey] = upd +} + func (r *MessengerResponse) Messages() []*common.Message { var ms []*common.Message for _, m := range r.messages { diff --git a/protocol/messenger_status_updates.go b/protocol/messenger_status_updates.go new file mode 100644 index 000000000..b73f06f55 --- /dev/null +++ b/protocol/messenger_status_updates.go @@ -0,0 +1,250 @@ +package protocol + +import ( + "context" + "fmt" + "time" + + "github.com/golang/protobuf/proto" + "go.uber.org/zap" + + "github.com/status-im/status-go/protocol/common" + "github.com/status-im/status-go/protocol/communities" + "github.com/status-im/status-go/protocol/protobuf" + "github.com/status-im/status-go/protocol/transport" +) + +func (m *Messenger) GetCurrentUserStatus() (*UserStatus, error) { + + status := &UserStatus{ + StatusType: int(protobuf.StatusUpdate_ONLINE), + Clock: 0, + CustomText: "", + } + + err := m.settings.GetCurrentStatus(status) + if err != nil { + m.logger.Debug("Error obtaining latest status", zap.Error(err)) + return nil, err + } + + return status, nil +} + +func (m *Messenger) sendUserStatus(ctx context.Context, status UserStatus) error { + shouldBroadcastUserStatus, err := m.settings.ShouldBroadcastUserStatus() + if err != nil { + return err + } + + if !shouldBroadcastUserStatus { + m.logger.Debug("user status should not be broadcasted") + return nil + } + + status.Clock = uint64(time.Now().Unix()) + + err = m.settings.SaveSetting("current-user-status", status) + if err != nil { + return err + } + + statusUpdate := &protobuf.StatusUpdate{ + Clock: status.Clock, + StatusType: protobuf.StatusUpdate_StatusType(status.StatusType), + CustomText: status.CustomText, + } + + encodedMessage, err := proto.Marshal(statusUpdate) + if err != nil { + return err + } + + contactCodeTopic := transport.ContactCodeTopic(&m.identity.PublicKey) + + rawMessage := common.RawMessage{ + LocalChatID: contactCodeTopic, + Payload: encodedMessage, + MessageType: protobuf.ApplicationMetadataMessage_STATUS_UPDATE, + ResendAutomatically: true, + } + + _, err = m.sender.SendPublic(ctx, contactCodeTopic, rawMessage) + if err != nil { + return err + } + + joinedCommunities, err := m.communitiesManager.Joined() + if err != nil { + return err + } + for _, community := range joinedCommunities { + rawMessage.LocalChatID = community.StatusUpdatesChannelID() + _, err = m.sender.SendPublic(ctx, rawMessage.LocalChatID, rawMessage) + if err != nil { + return err + } + } + + return nil +} + +func (m *Messenger) sendCurrentUserStatus(ctx context.Context) { + err := m.persistence.CleanOlderStatusUpdates() + if err != nil { + m.logger.Debug("Error cleaning status updates", zap.Error(err)) + return + } + + shouldBroadcastUserStatus, err := m.settings.ShouldBroadcastUserStatus() + if err != nil { + m.logger.Debug("Error while getting status broadcast setting", zap.Error(err)) + return + } + + if !shouldBroadcastUserStatus { + m.logger.Debug("user status should not be broadcasted") + return + } + + currStatus, err := m.GetCurrentUserStatus() + if err != nil { + m.logger.Debug("Error obtaining latest status", zap.Error(err)) + return + } + + if err := m.sendUserStatus(ctx, *currStatus); err != nil { + m.logger.Debug("Error when sending the latest user status", zap.Error(err)) + } +} + +func (m *Messenger) sendCurrentUserStatusToCommunity(ctx context.Context, community *communities.Community) error { + shouldBroadcastUserStatus, err := m.settings.ShouldBroadcastUserStatus() + if err != nil { + return err + } + + if !shouldBroadcastUserStatus { + m.logger.Debug("user status should not be broadcasted") + return nil + } + + status, err := m.GetCurrentUserStatus() + if err != nil { + m.logger.Debug("Error obtaining latest status", zap.Error(err)) + return err + } + + status.Clock = uint64(time.Now().Unix()) + + err = m.settings.SaveSetting("current-user-status", status) + if err != nil { + return err + } + + statusUpdate := &protobuf.StatusUpdate{ + Clock: status.Clock, + StatusType: protobuf.StatusUpdate_StatusType(status.StatusType), + CustomText: status.CustomText, + } + + encodedMessage, err := proto.Marshal(statusUpdate) + if err != nil { + return err + } + + rawMessage := common.RawMessage{ + LocalChatID: community.StatusUpdatesChannelID(), + Payload: encodedMessage, + MessageType: protobuf.ApplicationMetadataMessage_STATUS_UPDATE, + ResendAutomatically: true, + } + + _, err = m.sender.SendPublic(ctx, rawMessage.LocalChatID, rawMessage) + if err != nil { + return err + } + + return nil +} + +func (m *Messenger) broadcastLatestUserStatus() { + m.logger.Debug("broadcasting user status") + ctx := context.Background() + m.sendCurrentUserStatus(ctx) + go func() { + for { + select { + case <-time.After(5 * time.Minute): + m.sendCurrentUserStatus(ctx) + case <-m.quit: + return + } + } + }() +} + +func (m *Messenger) SetUserStatus(ctx context.Context, newStatus int, newCustomText string) error { + if len([]rune(newCustomText)) > maxStatusMessageText { + return fmt.Errorf("custom text shouldn't be longer than %d", maxStatusMessageText) + } + + if newStatus != int(protobuf.StatusUpdate_ONLINE) && newStatus != int(protobuf.StatusUpdate_DO_NOT_DISTURB) { + return fmt.Errorf("unknown status type") + } + + currStatus, err := m.GetCurrentUserStatus() + if err != nil { + m.logger.Debug("Error obtaining latest status", zap.Error(err)) + return err + } + + if newStatus == currStatus.StatusType && newCustomText == currStatus.CustomText { + m.logger.Debug("Status type did not change") + return nil + } + + currStatus.StatusType = newStatus + currStatus.CustomText = newCustomText + + return m.sendUserStatus(ctx, *currStatus) +} + +func (m *Messenger) HandleStatusUpdate(state *ReceivedMessageState, statusMessage protobuf.StatusUpdate) error { + if err := ValidateStatusUpdate(statusMessage); err != nil { + return err + } + + if common.IsPubKeyEqual(state.CurrentMessageState.PublicKey, &m.identity.PublicKey) { // Status message is ours + currentStatus, err := m.GetCurrentUserStatus() + if err != nil { + m.logger.Debug("Error obtaining latest status", zap.Error(err)) + return err + } + + if currentStatus.Clock >= statusMessage.Clock { + return nil // older status message, or status does not change ignoring it + } + newStatus := ToUserStatus(statusMessage) + err = m.settings.SaveSetting("current-user-status", newStatus) + if err != nil { + return err + } + state.Response.SetCurrentStatus(newStatus) + } else { + statusUpdate := ToUserStatus(statusMessage) + statusUpdate.PublicKey = state.CurrentMessageState.Contact.ID + + err := m.persistence.InsertStatusUpdate(statusUpdate) + if err != nil { + return err + } + state.Response.AddStatusUpdate(statusUpdate) + } + + return nil +} + +func (m *Messenger) StatusUpdates() ([]UserStatus, error) { + return m.persistence.StatusUpdates() +} diff --git a/protocol/persistence.go b/protocol/persistence.go index 290dc29a3..1be2a5b33 100644 --- a/protocol/persistence.go +++ b/protocol/persistence.go @@ -843,3 +843,60 @@ func (db sqlitePersistence) SaveWhenChatIdentityLastPublished(chatID string, has return nil } + +func (db sqlitePersistence) InsertStatusUpdate(userStatus UserStatus) error { + _, err := db.db.Exec(`INSERT INTO status_updates( + public_key, + status_type, + clock, + custom_text) + VALUES (?, ?, ?, ?)`, + userStatus.PublicKey, + userStatus.StatusType, + userStatus.Clock, + userStatus.CustomText, + ) + + return err +} + +func (db sqlitePersistence) CleanOlderStatusUpdates() error { + now := time.Now() + oneHourAgo := now.Add(time.Duration(-1) * time.Hour) + _, err := db.db.Exec(`DELETE FROM status_updates WHERE clock < ?`, + uint64(oneHourAgo.Unix()), + ) + + return err +} + +func (db sqlitePersistence) StatusUpdates() (statusUpdates []UserStatus, err error) { + rows, err := db.db.Query(` + SELECT + public_key, + status_type, + clock, + custom_text + FROM status_updates + `) + if err != nil { + return + } + defer rows.Close() + + for rows.Next() { + var userStatus UserStatus + err = rows.Scan( + &userStatus.PublicKey, + &userStatus.StatusType, + &userStatus.Clock, + &userStatus.CustomText, + ) + if err != nil { + return + } + statusUpdates = append(statusUpdates, userStatus) + } + + return +} diff --git a/protocol/protobuf/application_metadata_message.pb.go b/protocol/protobuf/application_metadata_message.pb.go index 9308e31b5..5e141d456 100644 --- a/protocol/protobuf/application_metadata_message.pb.go +++ b/protocol/protobuf/application_metadata_message.pb.go @@ -53,6 +53,7 @@ const ( ApplicationMetadataMessage_COMMUNITY_REQUEST_TO_JOIN ApplicationMetadataMessage_Type = 27 ApplicationMetadataMessage_PIN_MESSAGE ApplicationMetadataMessage_Type = 28 ApplicationMetadataMessage_EDIT_MESSAGE ApplicationMetadataMessage_Type = 29 + ApplicationMetadataMessage_STATUS_UPDATE ApplicationMetadataMessage_Type = 30 ) var ApplicationMetadataMessage_Type_name = map[int32]string{ @@ -86,6 +87,7 @@ var ApplicationMetadataMessage_Type_name = map[int32]string{ 27: "COMMUNITY_REQUEST_TO_JOIN", 28: "PIN_MESSAGE", 29: "EDIT_MESSAGE", + 30: "STATUS_UPDATE", } var ApplicationMetadataMessage_Type_value = map[string]int32{ @@ -119,6 +121,7 @@ var ApplicationMetadataMessage_Type_value = map[string]int32{ "COMMUNITY_REQUEST_TO_JOIN": 27, "PIN_MESSAGE": 28, "EDIT_MESSAGE": 29, + "STATUS_UPDATE": 30, } func (x ApplicationMetadataMessage_Type) String() string { @@ -197,40 +200,41 @@ func init() { } var fileDescriptor_ad09a6406fcf24c7 = []byte{ - // 553 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x84, 0x93, 0x4d, 0x53, 0xdb, 0x3e, - 0x10, 0xc6, 0xff, 0x01, 0xfe, 0x04, 0x96, 0x37, 0xb1, 0x40, 0x09, 0xef, 0x34, 0xed, 0xb4, 0xb4, - 0x9d, 0xc9, 0xa1, 0x3d, 0xf7, 0x20, 0xe4, 0x05, 0x44, 0x63, 0xc9, 0x48, 0x32, 0x9d, 0x9c, 0x34, - 0xa6, 0xb8, 0x0c, 0x33, 0x40, 0x3c, 0x60, 0x0e, 0x7c, 0xdc, 0x7e, 0x8a, 0x5e, 0x3b, 0x76, 0x12, - 0x0c, 0x25, 0x94, 0x93, 0x47, 0xcf, 0xf3, 0xdb, 0x95, 0xf7, 0x91, 0x04, 0xcd, 0x24, 0xcb, 0x2e, - 0xce, 0x7f, 0x24, 0xf9, 0x79, 0xf7, 0xca, 0x5f, 0xa6, 0x79, 0x72, 0x9a, 0xe4, 0x89, 0xbf, 0x4c, - 0x6f, 0x6e, 0x92, 0xb3, 0xb4, 0x95, 0x5d, 0x77, 0xf3, 0x2e, 0x4e, 0x94, 0x9f, 0x93, 0xdb, 0x9f, - 0xcd, 0xdf, 0x75, 0x58, 0xe5, 0x55, 0x41, 0xd8, 0xe7, 0xc3, 0x1e, 0x8e, 0xeb, 0x30, 0x79, 0x73, - 0x7e, 0x76, 0x95, 0xe4, 0xb7, 0xd7, 0x69, 0xa3, 0xb6, 0x5d, 0xdb, 0x99, 0x36, 0x95, 0x80, 0x0d, - 0xa8, 0x67, 0xc9, 0xdd, 0x45, 0x37, 0x39, 0x6d, 0x8c, 0x94, 0xde, 0x60, 0x89, 0x5f, 0x61, 0x2c, - 0xbf, 0xcb, 0xd2, 0xc6, 0xe8, 0x76, 0x6d, 0x67, 0xf6, 0xf3, 0x87, 0xd6, 0x60, 0xbf, 0xd6, 0xf3, - 0x7b, 0xb5, 0xdc, 0x5d, 0x96, 0x9a, 0xb2, 0xac, 0xf9, 0x6b, 0x1c, 0xc6, 0x8a, 0x25, 0x4e, 0x41, - 0x3d, 0x56, 0xdf, 0x94, 0xfe, 0xae, 0xd8, 0x7f, 0xc8, 0x60, 0x5a, 0x1c, 0x70, 0xe7, 0x43, 0xb2, - 0x96, 0xef, 0x13, 0xab, 0x21, 0xc2, 0xac, 0xd0, 0xca, 0x71, 0xe1, 0x7c, 0x1c, 0x05, 0xdc, 0x11, - 0x1b, 0xc1, 0x0d, 0x58, 0x09, 0x29, 0xdc, 0x25, 0x63, 0x0f, 0x64, 0xd4, 0x97, 0xef, 0x4b, 0x46, - 0x71, 0x09, 0xe6, 0x23, 0x2e, 0x8d, 0x97, 0xca, 0x3a, 0xde, 0x6e, 0x73, 0x27, 0xb5, 0x62, 0x63, - 0x85, 0x6c, 0x3b, 0x4a, 0x3c, 0x96, 0xff, 0xc7, 0x37, 0xb0, 0x65, 0xe8, 0x28, 0x26, 0xeb, 0x3c, - 0x0f, 0x02, 0x43, 0xd6, 0xfa, 0x3d, 0x6d, 0xbc, 0x33, 0x5c, 0x59, 0x2e, 0x4a, 0x68, 0x1c, 0x3f, - 0xc2, 0x3b, 0x2e, 0x04, 0x45, 0xce, 0xbf, 0xc4, 0xd6, 0xf1, 0x13, 0xbc, 0x0f, 0x48, 0xb4, 0xa5, - 0xa2, 0x17, 0xe1, 0x09, 0x5c, 0x86, 0x85, 0x01, 0xf4, 0xd0, 0x98, 0xc4, 0x45, 0x60, 0x96, 0x54, - 0xf0, 0x48, 0x05, 0xdc, 0x82, 0xb5, 0xbf, 0x7b, 0x3f, 0x04, 0xa6, 0x8a, 0x68, 0x9e, 0x0c, 0xe9, - 0xfb, 0x01, 0xb2, 0xe9, 0xe1, 0x36, 0x17, 0x42, 0xc7, 0xca, 0xb1, 0x19, 0x7c, 0x0d, 0x1b, 0x4f, - 0xed, 0x28, 0xde, 0x6d, 0x4b, 0xe1, 0x8b, 0x73, 0x61, 0xb3, 0xb8, 0x09, 0xab, 0x83, 0xf3, 0x10, - 0x3a, 0x20, 0xcf, 0x83, 0x63, 0x32, 0x4e, 0x5a, 0x0a, 0x49, 0x39, 0x36, 0x87, 0x4d, 0xd8, 0x8c, - 0x62, 0x7b, 0xe0, 0x95, 0x76, 0x72, 0x4f, 0x8a, 0x5e, 0x0b, 0x43, 0xfb, 0xd2, 0x3a, 0xd3, 0x8b, - 0x9c, 0x15, 0x09, 0xfd, 0x9b, 0xf1, 0x86, 0x6c, 0xa4, 0x95, 0x25, 0x36, 0x8f, 0x6b, 0xb0, 0xfc, - 0x14, 0x3e, 0x8a, 0xc9, 0x74, 0x18, 0xe2, 0x5b, 0xd8, 0x7e, 0xc6, 0xac, 0x5a, 0x2c, 0x14, 0x53, - 0x0f, 0xdb, 0xaf, 0xcc, 0x8f, 0x2d, 0x16, 0x23, 0x0d, 0xb3, 0xfb, 0xe5, 0x4b, 0xc5, 0x15, 0xa4, - 0x50, 0x1f, 0x4a, 0x6f, 0xa8, 0x9f, 0xf3, 0x2b, 0x5c, 0x81, 0xa5, 0x7d, 0xa3, 0xe3, 0xa8, 0x8c, - 0xc5, 0x4b, 0x75, 0x2c, 0x5d, 0x6f, 0xba, 0x65, 0x9c, 0x87, 0x99, 0x9e, 0x18, 0x90, 0x72, 0xd2, - 0x75, 0x58, 0xa3, 0xa0, 0x85, 0x0e, 0xc3, 0x58, 0x49, 0xd7, 0xf1, 0x01, 0x59, 0x61, 0x64, 0x54, - 0xd2, 0x2b, 0xd8, 0x80, 0xc5, 0xca, 0x7a, 0xd0, 0x67, 0xb5, 0xf8, 0xeb, 0xca, 0xb9, 0x3f, 0x6d, - 0xed, 0x0f, 0xb5, 0x54, 0x6c, 0x0d, 0xe7, 0x60, 0x2a, 0x92, 0xea, 0xfe, 0xda, 0xaf, 0x17, 0x6f, - 0x87, 0x02, 0x59, 0xbd, 0x9d, 0x8d, 0x93, 0xf1, 0xf2, 0x4d, 0x7e, 0xf9, 0x13, 0x00, 0x00, 0xff, - 0xff, 0x44, 0x65, 0xa6, 0x41, 0x30, 0x04, 0x00, 0x00, + // 562 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x84, 0x53, 0xdd, 0x4e, 0x1b, 0x3d, + 0x10, 0xfd, 0x02, 0x7c, 0xfc, 0x0c, 0x7f, 0x66, 0x80, 0x12, 0xfe, 0x69, 0x5a, 0xb5, 0xb4, 0x95, + 0x72, 0xd1, 0x5e, 0xf7, 0xc2, 0x78, 0x07, 0x30, 0xcd, 0xda, 0x8b, 0xed, 0xa5, 0xca, 0x95, 0xb5, + 0x94, 0x14, 0x21, 0x01, 0x59, 0xc1, 0x72, 0xc1, 0x2b, 0xf4, 0x79, 0xfb, 0x00, 0x95, 0x37, 0x09, + 0x0b, 0x05, 0xca, 0x95, 0xe5, 0x73, 0xce, 0xcc, 0x78, 0xce, 0x78, 0xa0, 0x91, 0xe5, 0xf9, 0xf9, + 0xd9, 0x8f, 0xac, 0x38, 0xeb, 0x5e, 0xfa, 0x8b, 0x4e, 0x91, 0x9d, 0x64, 0x45, 0xe6, 0x2f, 0x3a, + 0xd7, 0xd7, 0xd9, 0x69, 0xa7, 0x99, 0x5f, 0x75, 0x8b, 0x2e, 0x8e, 0x97, 0xc7, 0xf1, 0xcd, 0xcf, + 0xc6, 0xaf, 0x71, 0x58, 0xe1, 0x55, 0x40, 0xdc, 0xd7, 0xc7, 0x3d, 0x39, 0xae, 0xc1, 0xc4, 0xf5, + 0xd9, 0xe9, 0x65, 0x56, 0xdc, 0x5c, 0x75, 0xea, 0xb5, 0xad, 0xda, 0xf6, 0x94, 0xa9, 0x00, 0xac, + 0xc3, 0x58, 0x9e, 0xdd, 0x9e, 0x77, 0xb3, 0x93, 0xfa, 0x50, 0xc9, 0x0d, 0xae, 0xf8, 0x15, 0x46, + 0x8a, 0xdb, 0xbc, 0x53, 0x1f, 0xde, 0xaa, 0x6d, 0xcf, 0x7c, 0xfe, 0xd0, 0x1c, 0xd4, 0x6b, 0x3e, + 0x5f, 0xab, 0xe9, 0x6e, 0xf3, 0x8e, 0x29, 0xc3, 0x1a, 0xbf, 0x47, 0x61, 0x24, 0x5c, 0x71, 0x12, + 0xc6, 0x52, 0xf5, 0x4d, 0xe9, 0xef, 0x8a, 0xfd, 0x87, 0x0c, 0xa6, 0xc4, 0x3e, 0x77, 0x3e, 0x26, + 0x6b, 0xf9, 0x1e, 0xb1, 0x1a, 0x22, 0xcc, 0x08, 0xad, 0x1c, 0x17, 0xce, 0xa7, 0x49, 0xc4, 0x1d, + 0xb1, 0x21, 0x5c, 0x87, 0xe5, 0x98, 0xe2, 0x1d, 0x32, 0x76, 0x5f, 0x26, 0x7d, 0xf8, 0x2e, 0x64, + 0x18, 0x17, 0x61, 0x2e, 0xe1, 0xd2, 0x78, 0xa9, 0xac, 0xe3, 0xad, 0x16, 0x77, 0x52, 0x2b, 0x36, + 0x12, 0x60, 0xdb, 0x56, 0xe2, 0x21, 0xfc, 0x3f, 0xbe, 0x81, 0x4d, 0x43, 0x87, 0x29, 0x59, 0xe7, + 0x79, 0x14, 0x19, 0xb2, 0xd6, 0xef, 0x6a, 0xe3, 0x9d, 0xe1, 0xca, 0x72, 0x51, 0x8a, 0x46, 0xf1, + 0x23, 0xbc, 0xe3, 0x42, 0x50, 0xe2, 0xfc, 0x4b, 0xda, 0x31, 0xfc, 0x04, 0xef, 0x23, 0x12, 0x2d, + 0xa9, 0xe8, 0x45, 0xf1, 0x38, 0x2e, 0xc1, 0xfc, 0x40, 0x74, 0x9f, 0x98, 0xc0, 0x05, 0x60, 0x96, + 0x54, 0xf4, 0x00, 0x05, 0xdc, 0x84, 0xd5, 0xbf, 0x73, 0xdf, 0x17, 0x4c, 0x06, 0x6b, 0x1e, 0x35, + 0xe9, 0xfb, 0x06, 0xb2, 0xa9, 0xa7, 0x69, 0x2e, 0x84, 0x4e, 0x95, 0x63, 0xd3, 0xf8, 0x1a, 0xd6, + 0x1f, 0xd3, 0x49, 0xba, 0xd3, 0x92, 0xc2, 0x87, 0xb9, 0xb0, 0x19, 0xdc, 0x80, 0x95, 0xc1, 0x3c, + 0x84, 0x8e, 0xc8, 0xf3, 0xe8, 0x88, 0x8c, 0x93, 0x96, 0x62, 0x52, 0x8e, 0xcd, 0x62, 0x03, 0x36, + 0x92, 0xd4, 0xee, 0x7b, 0xa5, 0x9d, 0xdc, 0x95, 0xa2, 0x97, 0xc2, 0xd0, 0x9e, 0xb4, 0xce, 0xf4, + 0x2c, 0x67, 0xc1, 0xa1, 0x7f, 0x6b, 0xbc, 0x21, 0x9b, 0x68, 0x65, 0x89, 0xcd, 0xe1, 0x2a, 0x2c, + 0x3d, 0x16, 0x1f, 0xa6, 0x64, 0xda, 0x0c, 0xf1, 0x2d, 0x6c, 0x3d, 0x43, 0x56, 0x29, 0xe6, 0x43, + 0xd7, 0x4f, 0xd5, 0x2b, 0xfd, 0x63, 0x0b, 0xa1, 0xa5, 0xa7, 0xe8, 0x7e, 0xf8, 0x62, 0xf8, 0x82, + 0x14, 0xeb, 0x03, 0xe9, 0x0d, 0xf5, 0x7d, 0x7e, 0x85, 0xcb, 0xb0, 0xb8, 0x67, 0x74, 0x9a, 0x94, + 0xb6, 0x78, 0xa9, 0x8e, 0xa4, 0xeb, 0x75, 0xb7, 0x84, 0x73, 0x30, 0xdd, 0x03, 0x23, 0x52, 0x4e, + 0xba, 0x36, 0xab, 0x07, 0xb5, 0xd0, 0x71, 0x9c, 0x2a, 0xe9, 0xda, 0x3e, 0x22, 0x2b, 0x8c, 0x4c, + 0x4a, 0xf5, 0x32, 0xd6, 0x61, 0xa1, 0xa2, 0xee, 0xe5, 0x59, 0x09, 0xaf, 0xae, 0x98, 0xbb, 0x69, + 0x6b, 0x7f, 0xa0, 0xa5, 0x62, 0xab, 0x38, 0x0b, 0x93, 0x89, 0x54, 0x77, 0xdf, 0x7e, 0x2d, 0xec, + 0x0e, 0x45, 0xb2, 0xda, 0x9d, 0xf5, 0xf0, 0x12, 0xeb, 0xb8, 0x4b, 0xed, 0x60, 0x75, 0x36, 0x8e, + 0x47, 0xcb, 0x35, 0xfd, 0xf2, 0x27, 0x00, 0x00, 0xff, 0xff, 0x55, 0x1d, 0x56, 0x78, 0x43, 0x04, + 0x00, 0x00, } diff --git a/protocol/protobuf/application_metadata_message.proto b/protocol/protobuf/application_metadata_message.proto index 710089b33..ddcaaa949 100644 --- a/protocol/protobuf/application_metadata_message.proto +++ b/protocol/protobuf/application_metadata_message.proto @@ -43,5 +43,6 @@ message ApplicationMetadataMessage { COMMUNITY_REQUEST_TO_JOIN = 27; PIN_MESSAGE = 28; EDIT_MESSAGE = 29; + STATUS_UPDATE = 30; } } diff --git a/protocol/protobuf/status_update.pb.go b/protocol/protobuf/status_update.pb.go new file mode 100644 index 000000000..42538eadc --- /dev/null +++ b/protocol/protobuf/status_update.pb.go @@ -0,0 +1,131 @@ +// Code generated by protoc-gen-go. DO NOT EDIT. +// source: status_update.proto + +package protobuf + +import ( + fmt "fmt" + proto "github.com/golang/protobuf/proto" + math "math" +) + +// Reference imports to suppress errors if they are not otherwise used. +var _ = proto.Marshal +var _ = fmt.Errorf +var _ = math.Inf + +// This is a compile-time assertion to ensure that this generated file +// is compatible with the proto package it is being compiled against. +// A compilation error at this line likely means your copy of the +// proto package needs to be updated. +const _ = proto.ProtoPackageIsVersion3 // please upgrade the proto package + +type StatusUpdate_StatusType int32 + +const ( + StatusUpdate_UNKNOWN_STATUS_TYPE StatusUpdate_StatusType = 0 + StatusUpdate_ONLINE StatusUpdate_StatusType = 1 + StatusUpdate_DO_NOT_DISTURB StatusUpdate_StatusType = 2 +) + +var StatusUpdate_StatusType_name = map[int32]string{ + 0: "UNKNOWN_STATUS_TYPE", + 1: "ONLINE", + 2: "DO_NOT_DISTURB", +} + +var StatusUpdate_StatusType_value = map[string]int32{ + "UNKNOWN_STATUS_TYPE": 0, + "ONLINE": 1, + "DO_NOT_DISTURB": 2, +} + +func (x StatusUpdate_StatusType) String() string { + return proto.EnumName(StatusUpdate_StatusType_name, int32(x)) +} + +func (StatusUpdate_StatusType) EnumDescriptor() ([]byte, []int) { + return fileDescriptor_911acd91e62cd3d7, []int{0, 0} +} + +type StatusUpdate struct { + Clock uint64 `protobuf:"varint,1,opt,name=clock,proto3" json:"clock,omitempty"` + StatusType StatusUpdate_StatusType `protobuf:"varint,2,opt,name=status_type,json=statusType,proto3,enum=protobuf.StatusUpdate_StatusType" json:"status_type,omitempty"` + CustomText string `protobuf:"bytes,3,opt,name=custom_text,json=customText,proto3" json:"custom_text,omitempty"` + XXX_NoUnkeyedLiteral struct{} `json:"-"` + XXX_unrecognized []byte `json:"-"` + XXX_sizecache int32 `json:"-"` +} + +func (m *StatusUpdate) Reset() { *m = StatusUpdate{} } +func (m *StatusUpdate) String() string { return proto.CompactTextString(m) } +func (*StatusUpdate) ProtoMessage() {} +func (*StatusUpdate) Descriptor() ([]byte, []int) { + return fileDescriptor_911acd91e62cd3d7, []int{0} +} + +func (m *StatusUpdate) XXX_Unmarshal(b []byte) error { + return xxx_messageInfo_StatusUpdate.Unmarshal(m, b) +} +func (m *StatusUpdate) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + return xxx_messageInfo_StatusUpdate.Marshal(b, m, deterministic) +} +func (m *StatusUpdate) XXX_Merge(src proto.Message) { + xxx_messageInfo_StatusUpdate.Merge(m, src) +} +func (m *StatusUpdate) XXX_Size() int { + return xxx_messageInfo_StatusUpdate.Size(m) +} +func (m *StatusUpdate) XXX_DiscardUnknown() { + xxx_messageInfo_StatusUpdate.DiscardUnknown(m) +} + +var xxx_messageInfo_StatusUpdate proto.InternalMessageInfo + +func (m *StatusUpdate) GetClock() uint64 { + if m != nil { + return m.Clock + } + return 0 +} + +func (m *StatusUpdate) GetStatusType() StatusUpdate_StatusType { + if m != nil { + return m.StatusType + } + return StatusUpdate_UNKNOWN_STATUS_TYPE +} + +func (m *StatusUpdate) GetCustomText() string { + if m != nil { + return m.CustomText + } + return "" +} + +func init() { + proto.RegisterEnum("protobuf.StatusUpdate_StatusType", StatusUpdate_StatusType_name, StatusUpdate_StatusType_value) + proto.RegisterType((*StatusUpdate)(nil), "protobuf.StatusUpdate") +} + +func init() { + proto.RegisterFile("status_update.proto", fileDescriptor_911acd91e62cd3d7) +} + +var fileDescriptor_911acd91e62cd3d7 = []byte{ + // 213 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe2, 0x12, 0x2e, 0x2e, 0x49, 0x2c, + 0x29, 0x2d, 0x8e, 0x2f, 0x2d, 0x48, 0x49, 0x2c, 0x49, 0xd5, 0x2b, 0x28, 0xca, 0x2f, 0xc9, 0x17, + 0xe2, 0x00, 0x53, 0x49, 0xa5, 0x69, 0x4a, 0x17, 0x18, 0xb9, 0x78, 0x82, 0xc1, 0x2a, 0x42, 0xc1, + 0x0a, 0x84, 0x44, 0xb8, 0x58, 0x93, 0x73, 0xf2, 0x93, 0xb3, 0x25, 0x18, 0x15, 0x18, 0x35, 0x58, + 0x82, 0x20, 0x1c, 0x21, 0x27, 0x2e, 0x6e, 0xa8, 0x39, 0x25, 0x95, 0x05, 0xa9, 0x12, 0x4c, 0x0a, + 0x8c, 0x1a, 0x7c, 0x46, 0x8a, 0x7a, 0x30, 0x63, 0xf4, 0x90, 0x8d, 0x80, 0x72, 0x42, 0x2a, 0x0b, + 0x52, 0x83, 0xb8, 0x8a, 0xe1, 0x6c, 0x21, 0x79, 0x2e, 0xee, 0xe4, 0xd2, 0xe2, 0x92, 0xfc, 0xdc, + 0xf8, 0x92, 0xd4, 0x8a, 0x12, 0x09, 0x66, 0x05, 0x46, 0x0d, 0xce, 0x20, 0x2e, 0x88, 0x50, 0x48, + 0x6a, 0x45, 0x89, 0x92, 0x2b, 0x17, 0x17, 0x42, 0xab, 0x90, 0x38, 0x97, 0x70, 0xa8, 0x9f, 0xb7, + 0x9f, 0x7f, 0xb8, 0x5f, 0x7c, 0x70, 0x88, 0x63, 0x48, 0x68, 0x70, 0x7c, 0x48, 0x64, 0x80, 0xab, + 0x00, 0x83, 0x10, 0x17, 0x17, 0x9b, 0xbf, 0x9f, 0x8f, 0xa7, 0x9f, 0xab, 0x00, 0xa3, 0x90, 0x10, + 0x17, 0x9f, 0x8b, 0x7f, 0xbc, 0x9f, 0x7f, 0x48, 0xbc, 0x8b, 0x67, 0x70, 0x48, 0x68, 0x90, 0x93, + 0x00, 0x53, 0x12, 0x1b, 0xd8, 0x55, 0xc6, 0x80, 0x00, 0x00, 0x00, 0xff, 0xff, 0xf5, 0x6f, 0xd8, + 0x56, 0xfa, 0x00, 0x00, 0x00, +} diff --git a/protocol/protobuf/status_update.proto b/protocol/protobuf/status_update.proto new file mode 100644 index 000000000..6178f8709 --- /dev/null +++ b/protocol/protobuf/status_update.proto @@ -0,0 +1,19 @@ +syntax = "proto3"; + +package protobuf; + +message StatusUpdate { + + uint64 clock = 1; + + StatusType status_type = 2; + + string custom_text = 3; + + enum StatusType { + UNKNOWN_STATUS_TYPE = 0; + ONLINE = 1; + DO_NOT_DISTURB = 2; + }; + +} \ No newline at end of file diff --git a/protocol/status_update.go b/protocol/status_update.go new file mode 100644 index 000000000..da0f66b29 --- /dev/null +++ b/protocol/status_update.go @@ -0,0 +1,18 @@ +package protocol + +import "github.com/status-im/status-go/protocol/protobuf" + +type UserStatus struct { + PublicKey string `json:"publicKey,omitempty"` + StatusType int `json:"statusType"` + Clock uint64 `json:"clock"` + CustomText string `json:"text"` +} + +func ToUserStatus(msg protobuf.StatusUpdate) UserStatus { + return UserStatus{ + StatusType: int(msg.StatusType), + Clock: msg.Clock, + CustomText: msg.CustomText, + } +} diff --git a/protocol/v1/status_message.go b/protocol/v1/status_message.go index f91425524..63c6f8fa4 100644 --- a/protocol/v1/status_message.go +++ b/protocol/v1/status_message.go @@ -232,6 +232,8 @@ func (m *StatusMessage) HandleApplication() error { return m.unmarshalProtobufData(new(protobuf.CommunityRequestToJoin)) case protobuf.ApplicationMetadataMessage_EDIT_MESSAGE: return m.unmarshalProtobufData(new(protobuf.EditMessage)) + case protobuf.ApplicationMetadataMessage_STATUS_UPDATE: + return m.unmarshalProtobufData(new(protobuf.StatusUpdate)) case protobuf.ApplicationMetadataMessage_PUSH_NOTIFICATION_REGISTRATION: // This message is a bit different as it's encrypted, so we pass it straight through v := reflect.ValueOf(m.UnwrappedPayload) diff --git a/services/ext/api.go b/services/ext/api.go index 2af3cbf88..f8c7d75e5 100644 --- a/services/ext/api.go +++ b/services/ext/api.go @@ -336,7 +336,7 @@ func (api *PublicAPI) JoinedCommunities(parent context.Context) ([]*communities. // JoinCommunity joins a community with the given ID func (api *PublicAPI) JoinCommunity(parent context.Context, communityID types.HexBytes) (*protocol.MessengerResponse, error) { - return api.service.messenger.JoinCommunity(communityID) + return api.service.messenger.JoinCommunity(parent, communityID) } // LeaveCommunity leaves a commuity with the given ID @@ -364,13 +364,13 @@ func (api *PublicAPI) ExportCommunity(id types.HexBytes) (types.HexBytes, error) } // ImportCommunity imports a community with the given private key in hex -func (api *PublicAPI) ImportCommunity(hexPrivateKey string) (*protocol.MessengerResponse, error) { +func (api *PublicAPI) ImportCommunity(ctx context.Context, hexPrivateKey string) (*protocol.MessengerResponse, error) { // Strip the 0x from the beginning privateKey, err := crypto.HexToECDSA(hexPrivateKey[2:]) if err != nil { return nil, err } - return api.service.messenger.ImportCommunity(privateKey) + return api.service.messenger.ImportCommunity(ctx, privateKey) } @@ -469,6 +469,10 @@ type ApplicationPinnedMessagesResponse struct { Cursor string `json:"cursor"` } +type ApplicationStatusUpdatesResponse struct { + StatusUpdates []protocol.UserStatus `json:"statusUpdates"` +} + func (api *PublicAPI) ChatMessages(chatID, cursor string, limit int) (*ApplicationMessagesResponse, error) { messages, cursor, err := api.service.messenger.MessageByChatID(chatID, cursor, limit) if err != nil { @@ -493,10 +497,25 @@ func (api *PublicAPI) ChatPinnedMessages(chatID, cursor string, limit int) (*App }, nil } +func (api *PublicAPI) StatusUpdates() (*ApplicationStatusUpdatesResponse, error) { + statusUpdates, err := api.service.messenger.StatusUpdates() + if err != nil { + return nil, err + } + + return &ApplicationStatusUpdatesResponse{ + StatusUpdates: statusUpdates, + }, nil +} + func (api *PublicAPI) StartMessenger() (*protocol.MessengerResponse, error) { return api.service.StartMessenger() } +func (api *PublicAPI) SetUserStatus(ctx context.Context, status int, customText string) error { + return api.service.messenger.SetUserStatus(ctx, status, customText) +} + func (api *PublicAPI) DeleteMessage(id string) error { return api.service.messenger.DeleteMessage(id) }