Merge branch 'feature/push-notification-mentions' into develop
This commit is contained in:
commit
19a82f68ad
|
@ -15,6 +15,8 @@
|
||||||
// 0008_add_push_notifications.up.sql (349B)
|
// 0008_add_push_notifications.up.sql (349B)
|
||||||
// 0009_enable_sending_push_notifications.down.sql (49B)
|
// 0009_enable_sending_push_notifications.down.sql (49B)
|
||||||
// 0009_enable_sending_push_notifications.up.sql (49B)
|
// 0009_enable_sending_push_notifications.up.sql (49B)
|
||||||
|
// 0010_add_block_mentions.down.sql (83B)
|
||||||
|
// 0010_add_block_mentions.up.sql (89B)
|
||||||
// doc.go (74B)
|
// doc.go (74B)
|
||||||
|
|
||||||
package migrations
|
package migrations
|
||||||
|
@ -359,7 +361,7 @@ func _0009_enable_sending_push_notificationsDownSql() (*asset, error) {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
info := bindataFileInfo{name: "0009_enable_sending_push_notifications.down.sql", size: 49, mode: os.FileMode(0644), modTime: time.Unix(1597918101, 0)}
|
info := bindataFileInfo{name: "0009_enable_sending_push_notifications.down.sql", size: 49, mode: os.FileMode(0644), modTime: time.Unix(1598949727, 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}}
|
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}}
|
||||||
return a, nil
|
return a, nil
|
||||||
}
|
}
|
||||||
|
@ -379,11 +381,51 @@ func _0009_enable_sending_push_notificationsUpSql() (*asset, error) {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
info := bindataFileInfo{name: "0009_enable_sending_push_notifications.up.sql", size: 49, mode: os.FileMode(0644), modTime: time.Unix(1597918090, 0)}
|
info := bindataFileInfo{name: "0009_enable_sending_push_notifications.up.sql", size: 49, mode: os.FileMode(0644), modTime: time.Unix(1598949727, 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}}
|
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}}
|
||||||
return a, nil
|
return a, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var __0010_add_block_mentionsDownSql = []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\x72\xf4\x09\x71\x0d\x52\x28\x4e\x2d\x29\xc9\xcc\x4b\x2f\x56\x70\x74\x71\x51\x70\xf6\xf7\x09\xf5\xf5\x53\x28\x28\x2d\xce\x88\xcf\xcb\x2f\xc9\x4c\xcb\x4c\x4e\x2c\xc9\xcc\xcf\x2b\x8e\x4f\xca\xc9\x4f\xce\x8e\xcf\x4d\xcd\x03\x73\x15\x9c\xfc\xfd\x7d\x5c\x1d\xfd\x14\x5c\x5c\xdd\x1c\x43\x7d\x42\x14\xdc\x1c\x7d\x82\x5d\xad\xb9\x00\x01\x00\x00\xff\xff\xa8\x45\x75\x3b\x53\x00\x00\x00")
|
||||||
|
|
||||||
|
func _0010_add_block_mentionsDownSqlBytes() ([]byte, error) {
|
||||||
|
return bindataRead(
|
||||||
|
__0010_add_block_mentionsDownSql,
|
||||||
|
"0010_add_block_mentions.down.sql",
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
func _0010_add_block_mentionsDownSql() (*asset, error) {
|
||||||
|
bytes, err := _0010_add_block_mentionsDownSqlBytes()
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
info := bindataFileInfo{name: "0010_add_block_mentions.down.sql", size: 83, mode: os.FileMode(0644), modTime: time.Unix(1599117686, 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}}
|
||||||
|
return a, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
var __0010_add_block_mentionsUpSql = []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\x1c\xc7\x31\x0a\x42\x31\x0c\x06\xe0\xdd\x53\xfc\xf7\x70\xca\xb3\x79\x53\x7c\x05\x6d\xe7\xa2\xa5\x6a\x50\x53\x21\xf1\xfe\x82\xe3\x47\x52\xf8\x84\x42\x8b\x30\x7c\x44\xa8\xdd\x1d\x94\x12\x0e\x59\xea\x71\xc3\xe7\xeb\x8f\x66\x33\xf4\xa6\xfd\x12\x3a\xcd\xdb\xf5\x35\xfb\xb3\xbd\x87\xfd\x89\x25\x67\x61\xda\x90\x78\xa5\x2a\x05\x2b\xc9\x99\xf7\xbb\x5f\x00\x00\x00\xff\xff\x2b\x4e\x3f\xc5\x59\x00\x00\x00")
|
||||||
|
|
||||||
|
func _0010_add_block_mentionsUpSqlBytes() ([]byte, error) {
|
||||||
|
return bindataRead(
|
||||||
|
__0010_add_block_mentionsUpSql,
|
||||||
|
"0010_add_block_mentions.up.sql",
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
func _0010_add_block_mentionsUpSql() (*asset, error) {
|
||||||
|
bytes, err := _0010_add_block_mentionsUpSqlBytes()
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
info := bindataFileInfo{name: "0010_add_block_mentions.up.sql", size: 89, mode: os.FileMode(0644), modTime: time.Unix(1599118789, 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}}
|
||||||
|
return a, nil
|
||||||
|
}
|
||||||
|
|
||||||
var _docGo = []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\x2c\xc9\xb1\x0d\xc4\x20\x0c\x05\xd0\x9e\x29\xfe\x02\xd8\xfd\x6d\xe3\x4b\xac\x2f\x44\x82\x09\x78\x7f\xa5\x49\xfd\xa6\x1d\xdd\xe8\xd8\xcf\x55\x8a\x2a\xe3\x47\x1f\xbe\x2c\x1d\x8c\xfa\x6f\xe3\xb4\x34\xd4\xd9\x89\xbb\x71\x59\xb6\x18\x1b\x35\x20\xa2\x9f\x0a\x03\xa2\xe5\x0d\x00\x00\xff\xff\x60\xcd\x06\xbe\x4a\x00\x00\x00")
|
var _docGo = []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\x2c\xc9\xb1\x0d\xc4\x20\x0c\x05\xd0\x9e\x29\xfe\x02\xd8\xfd\x6d\xe3\x4b\xac\x2f\x44\x82\x09\x78\x7f\xa5\x49\xfd\xa6\x1d\xdd\xe8\xd8\xcf\x55\x8a\x2a\xe3\x47\x1f\xbe\x2c\x1d\x8c\xfa\x6f\xe3\xb4\x34\xd4\xd9\x89\xbb\x71\x59\xb6\x18\x1b\x35\x20\xa2\x9f\x0a\x03\xa2\xe5\x0d\x00\x00\xff\xff\x60\xcd\x06\xbe\x4a\x00\x00\x00")
|
||||||
|
|
||||||
func docGoBytes() ([]byte, error) {
|
func docGoBytes() ([]byte, error) {
|
||||||
|
@ -525,6 +567,10 @@ var _bindata = map[string]func() (*asset, error){
|
||||||
|
|
||||||
"0009_enable_sending_push_notifications.up.sql": _0009_enable_sending_push_notificationsUpSql,
|
"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,
|
||||||
|
|
||||||
"doc.go": docGo,
|
"doc.go": docGo,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -584,7 +630,9 @@ var _bintree = &bintree{nil, map[string]*bintree{
|
||||||
"0008_add_push_notifications.up.sql": &bintree{_0008_add_push_notificationsUpSql, 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.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{}},
|
"0009_enable_sending_push_notifications.up.sql": &bintree{_0009_enable_sending_push_notificationsUpSql, map[string]*bintree{}},
|
||||||
"doc.go": &bintree{docGo, 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{}},
|
||||||
|
"doc.go": &bintree{docGo, map[string]*bintree{}},
|
||||||
}}
|
}}
|
||||||
|
|
||||||
// RestoreAsset restores an asset under the given directory.
|
// RestoreAsset restores an asset under the given directory.
|
||||||
|
|
|
@ -0,0 +1 @@
|
||||||
|
ALTER settings ADD COLUMN push_notifications_block_mentions BOOLEAN DEFAULT FALSE;
|
|
@ -0,0 +1 @@
|
||||||
|
ALTER TABLE settings ADD COLUMN push_notifications_block_mentions BOOLEAN DEFAULT FALSE;
|
|
@ -70,7 +70,9 @@ type Settings struct {
|
||||||
PushNotificationsServerEnabled bool `json:"push-notifications-server-enabled?,omitempty"`
|
PushNotificationsServerEnabled bool `json:"push-notifications-server-enabled?,omitempty"`
|
||||||
// PushNotificationsFromContactsOnly indicates whether we should only receive push notifications from contacts
|
// PushNotificationsFromContactsOnly indicates whether we should only receive push notifications from contacts
|
||||||
PushNotificationsFromContactsOnly bool `json:"push-notifications-from-contacts-only?,omitempty"`
|
PushNotificationsFromContactsOnly bool `json:"push-notifications-from-contacts-only?,omitempty"`
|
||||||
RememberSyncingChoice bool `json:"remember-syncing-choice?,omitempty"`
|
// PushNotificationsBlockMentions indicates whether we should receive notifications for mentions
|
||||||
|
PushNotificationsBlockMentions bool `json:"push-notifications-block-mentions?,omitempty"`
|
||||||
|
RememberSyncingChoice bool `json:"remember-syncing-choice?,omitempty"`
|
||||||
// RemotePushNotificationsEnabled indicates whether we should be using remote notifications (ios only for now)
|
// RemotePushNotificationsEnabled indicates whether we should be using remote notifications (ios only for now)
|
||||||
RemotePushNotificationsEnabled bool `json:"remote-push-notifications-enabled?,omitempty"`
|
RemotePushNotificationsEnabled bool `json:"remote-push-notifications-enabled?,omitempty"`
|
||||||
SigningPhrase string `json:"signing-phrase"`
|
SigningPhrase string `json:"signing-phrase"`
|
||||||
|
@ -273,6 +275,12 @@ func (db *Database) SaveSetting(setting string, value interface{}) error {
|
||||||
return ErrInvalidConfig
|
return ErrInvalidConfig
|
||||||
}
|
}
|
||||||
update, err = db.db.Prepare("UPDATE settings SET push_notifications_from_contacts_only = ? WHERE synthetic_id = 'id'")
|
update, err = db.db.Prepare("UPDATE settings SET push_notifications_from_contacts_only = ? WHERE synthetic_id = 'id'")
|
||||||
|
case "push-notifications-block-mentions?":
|
||||||
|
_, ok := value.(bool)
|
||||||
|
if !ok {
|
||||||
|
return ErrInvalidConfig
|
||||||
|
}
|
||||||
|
update, err = db.db.Prepare("UPDATE settings SET push_notifications_block_mentions = ? WHERE synthetic_id = 'id'")
|
||||||
case "send-push-notifications?":
|
case "send-push-notifications?":
|
||||||
_, ok := value.(bool)
|
_, ok := value.(bool)
|
||||||
if !ok {
|
if !ok {
|
||||||
|
@ -337,7 +345,7 @@ func (db *Database) GetNodeConfig(nodecfg interface{}) error {
|
||||||
|
|
||||||
func (db *Database) GetSettings() (Settings, error) {
|
func (db *Database) GetSettings() (Settings, error) {
|
||||||
var s Settings
|
var s Settings
|
||||||
err := db.db.QueryRow("SELECT address, 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, log_level, mnemonic, name, networks, notifications_enabled, push_notifications_server_enabled, push_notifications_from_contacts_only, remote_push_notifications_enabled, send_push_notifications, 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, usernames, appearance, wallet_root_address, wallet_set_up_passed, wallet_visible_tokens, waku_enabled, waku_bloom_filter_mode FROM settings WHERE synthetic_id = 'id'").Scan(
|
err := db.db.QueryRow("SELECT address, 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, 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, usernames, appearance, wallet_root_address, wallet_set_up_passed, wallet_visible_tokens, waku_enabled, waku_bloom_filter_mode FROM settings WHERE synthetic_id = 'id'").Scan(
|
||||||
&s.Address,
|
&s.Address,
|
||||||
&s.ChaosMode,
|
&s.ChaosMode,
|
||||||
&s.Currency,
|
&s.Currency,
|
||||||
|
@ -364,6 +372,7 @@ func (db *Database) GetSettings() (Settings, error) {
|
||||||
&s.PushNotificationsFromContactsOnly,
|
&s.PushNotificationsFromContactsOnly,
|
||||||
&s.RemotePushNotificationsEnabled,
|
&s.RemotePushNotificationsEnabled,
|
||||||
&s.SendPushNotifications,
|
&s.SendPushNotifications,
|
||||||
|
&s.PushNotificationsBlockMentions,
|
||||||
&s.PhotoPath,
|
&s.PhotoPath,
|
||||||
&s.PinnedMailserver,
|
&s.PinnedMailserver,
|
||||||
&s.PreferredName,
|
&s.PreferredName,
|
||||||
|
|
|
@ -30,50 +30,21 @@ import (
|
||||||
"github.com/status-im/status-go/whisper/v6"
|
"github.com/status-im/status-go/whisper/v6"
|
||||||
)
|
)
|
||||||
|
|
||||||
// GetFreePort asks the kernel for a free open port that is ready to use.
|
|
||||||
func getFreePort() (int, error) {
|
|
||||||
addr, err := net.ResolveTCPAddr("tcp", "localhost:0")
|
|
||||||
if err != nil {
|
|
||||||
return 0, err
|
|
||||||
}
|
|
||||||
|
|
||||||
l, err := net.ListenTCP("tcp", addr)
|
|
||||||
if err != nil {
|
|
||||||
return 0, err
|
|
||||||
}
|
|
||||||
defer l.Close()
|
|
||||||
return l.Addr().(*net.TCPAddr).Port, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
type PeerPoolSimulationSuite struct {
|
type PeerPoolSimulationSuite struct {
|
||||||
suite.Suite
|
suite.Suite
|
||||||
|
|
||||||
bootnode *p2p.Server
|
bootnode *p2p.Server
|
||||||
peers []*p2p.Server
|
peers []*p2p.Server
|
||||||
discovery []discovery.Discovery
|
discovery []discovery.Discovery
|
||||||
port uint16
|
|
||||||
rendezvousServer *server.Server
|
rendezvousServer *server.Server
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestPeerPoolSimulationSuite(t *testing.T) {
|
func TestPeerPoolSimulationSuite(t *testing.T) {
|
||||||
s := &PeerPoolSimulationSuite{}
|
s := &PeerPoolSimulationSuite{}
|
||||||
port, err := getFreePort()
|
|
||||||
if err != nil {
|
|
||||||
panic(err)
|
|
||||||
}
|
|
||||||
s.port = uint16(port)
|
|
||||||
|
|
||||||
suite.Run(t, s)
|
suite.Run(t, s)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *PeerPoolSimulationSuite) nextPort() uint16 {
|
|
||||||
port, err := getFreePort()
|
|
||||||
s.Require().NoError(err)
|
|
||||||
return uint16(port)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *PeerPoolSimulationSuite) SetupTest() {
|
func (s *PeerPoolSimulationSuite) SetupTest() {
|
||||||
bootnodePort := s.nextPort()
|
|
||||||
key, _ := crypto.GenerateKey()
|
key, _ := crypto.GenerateKey()
|
||||||
name := common.MakeName("bootnode", "1.0")
|
name := common.MakeName("bootnode", "1.0")
|
||||||
// 127.0.0.1 is invalidated by discovery v5
|
// 127.0.0.1 is invalidated by discovery v5
|
||||||
|
@ -81,13 +52,14 @@ func (s *PeerPoolSimulationSuite) SetupTest() {
|
||||||
Config: p2p.Config{
|
Config: p2p.Config{
|
||||||
MaxPeers: 10,
|
MaxPeers: 10,
|
||||||
Name: name,
|
Name: name,
|
||||||
ListenAddr: fmt.Sprintf("0.0.0.0:%d", bootnodePort),
|
ListenAddr: ":0",
|
||||||
PrivateKey: key,
|
PrivateKey: key,
|
||||||
DiscoveryV5: true,
|
DiscoveryV5: true,
|
||||||
NoDiscovery: true,
|
NoDiscovery: true,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
s.Require().NoError(s.bootnode.Start())
|
s.Require().NoError(s.bootnode.Start())
|
||||||
|
bootnodePort := uint16(s.bootnode.NodeInfo().Ports.Listener)
|
||||||
bootnodeV5 := discv5.NewNode(s.bootnode.DiscV5.Self().ID, net.ParseIP("127.0.0.1"), bootnodePort, bootnodePort)
|
bootnodeV5 := discv5.NewNode(s.bootnode.DiscV5.Self().ID, net.ParseIP("127.0.0.1"), bootnodePort, bootnodePort)
|
||||||
|
|
||||||
// 1 peer to initiate connection, 1 peer as a first candidate, 1 peer - for failover
|
// 1 peer to initiate connection, 1 peer as a first candidate, 1 peer - for failover
|
||||||
|
@ -100,7 +72,7 @@ func (s *PeerPoolSimulationSuite) SetupTest() {
|
||||||
Config: p2p.Config{
|
Config: p2p.Config{
|
||||||
MaxPeers: 10,
|
MaxPeers: 10,
|
||||||
Name: common.MakeName("peer-"+strconv.Itoa(i), "1.0"),
|
Name: common.MakeName("peer-"+strconv.Itoa(i), "1.0"),
|
||||||
ListenAddr: fmt.Sprintf("0.0.0.0:%d", s.nextPort()),
|
ListenAddr: ":0",
|
||||||
PrivateKey: key,
|
PrivateKey: key,
|
||||||
NoDiscovery: true,
|
NoDiscovery: true,
|
||||||
BootstrapNodesV5: []*discv5.Node{bootnodeV5},
|
BootstrapNodesV5: []*discv5.Node{bootnodeV5},
|
||||||
|
|
|
@ -8,6 +8,7 @@ import (
|
||||||
|
|
||||||
"github.com/status-im/status-go/eth-node/crypto"
|
"github.com/status-im/status-go/eth-node/crypto"
|
||||||
"github.com/status-im/status-go/eth-node/types"
|
"github.com/status-im/status-go/eth-node/types"
|
||||||
|
"github.com/status-im/status-go/protocol/common"
|
||||||
"github.com/status-im/status-go/protocol/protobuf"
|
"github.com/status-im/status-go/protocol/protobuf"
|
||||||
v1protocol "github.com/status-im/status-go/protocol/v1"
|
v1protocol "github.com/status-im/status-go/protocol/v1"
|
||||||
)
|
)
|
||||||
|
@ -50,8 +51,8 @@ type Chat struct {
|
||||||
DeletedAtClockValue uint64 `json:"deletedAtClockValue"`
|
DeletedAtClockValue uint64 `json:"deletedAtClockValue"`
|
||||||
|
|
||||||
// Denormalized fields
|
// Denormalized fields
|
||||||
UnviewedMessagesCount uint `json:"unviewedMessagesCount"`
|
UnviewedMessagesCount uint `json:"unviewedMessagesCount"`
|
||||||
LastMessage *Message `json:"lastMessage"`
|
LastMessage *common.Message `json:"lastMessage"`
|
||||||
|
|
||||||
// Group chat fields
|
// Group chat fields
|
||||||
// Members are the members who have been invited to the group chat
|
// Members are the members who have been invited to the group chat
|
||||||
|
@ -114,6 +115,16 @@ func (c *Chat) MembersAsPublicKeys() ([]*ecdsa.PublicKey, error) {
|
||||||
return stringSliceToPublicKeys(publicKeys, true)
|
return stringSliceToPublicKeys(publicKeys, true)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (c *Chat) JoinedMembersAsPublicKeys() ([]*ecdsa.PublicKey, error) {
|
||||||
|
var publicKeys []string
|
||||||
|
for _, member := range c.Members {
|
||||||
|
if member.Joined {
|
||||||
|
publicKeys = append(publicKeys, member.ID)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return stringSliceToPublicKeys(publicKeys, true)
|
||||||
|
}
|
||||||
|
|
||||||
func (c *Chat) HasMember(memberID string) bool {
|
func (c *Chat) HasMember(memberID string) bool {
|
||||||
for _, member := range c.Members {
|
for _, member := range c.Members {
|
||||||
if memberID == member.ID {
|
if memberID == member.ID {
|
||||||
|
@ -172,7 +183,7 @@ func (c *Chat) NextClockAndTimestamp(timesource TimeSource) (uint64, uint64) {
|
||||||
return clock, timestamp
|
return clock, timestamp
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Chat) UpdateFromMessage(message *Message, timesource TimeSource) error {
|
func (c *Chat) UpdateFromMessage(message *common.Message, timesource TimeSource) error {
|
||||||
c.Timestamp = int64(timesource.GetCurrentTime())
|
c.Timestamp = int64(timesource.GetCurrentTime())
|
||||||
|
|
||||||
// If the clock of the last message is lower, we set the message
|
// If the clock of the last message is lower, we set the message
|
||||||
|
|
|
@ -5,6 +5,8 @@ import (
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/stretchr/testify/suite"
|
"github.com/stretchr/testify/suite"
|
||||||
|
|
||||||
|
"github.com/status-im/status-go/protocol/common"
|
||||||
)
|
)
|
||||||
|
|
||||||
type ChatTestSuite struct {
|
type ChatTestSuite struct {
|
||||||
|
@ -75,7 +77,7 @@ func (s *ChatTestSuite) TestValidateChat() {
|
||||||
func (s *ChatTestSuite) TestUpdateFromMessage() {
|
func (s *ChatTestSuite) TestUpdateFromMessage() {
|
||||||
|
|
||||||
// Base case, clock is higher
|
// Base case, clock is higher
|
||||||
message := &Message{}
|
message := &common.Message{}
|
||||||
chat := &Chat{}
|
chat := &Chat{}
|
||||||
|
|
||||||
message.Clock = 1
|
message.Clock = 1
|
||||||
|
@ -84,7 +86,7 @@ func (s *ChatTestSuite) TestUpdateFromMessage() {
|
||||||
s.Require().Equal(uint64(1), chat.LastClockValue)
|
s.Require().Equal(uint64(1), chat.LastClockValue)
|
||||||
|
|
||||||
// Clock is lower and lastMessage is not nil
|
// Clock is lower and lastMessage is not nil
|
||||||
message = &Message{}
|
message = &common.Message{}
|
||||||
lastMessage := message
|
lastMessage := message
|
||||||
chat = &Chat{LastClockValue: 2, LastMessage: lastMessage}
|
chat = &Chat{LastClockValue: 2, LastMessage: lastMessage}
|
||||||
|
|
||||||
|
@ -94,7 +96,7 @@ func (s *ChatTestSuite) TestUpdateFromMessage() {
|
||||||
s.Require().Equal(uint64(2), chat.LastClockValue)
|
s.Require().Equal(uint64(2), chat.LastClockValue)
|
||||||
|
|
||||||
// Clock is lower and lastMessage is nil
|
// Clock is lower and lastMessage is nil
|
||||||
message = &Message{}
|
message = &common.Message{}
|
||||||
chat = &Chat{LastClockValue: 2}
|
chat = &Chat{LastClockValue: 2}
|
||||||
|
|
||||||
message.Clock = 1
|
message.Clock = 1
|
||||||
|
@ -103,7 +105,7 @@ func (s *ChatTestSuite) TestUpdateFromMessage() {
|
||||||
s.Require().Equal(uint64(2), chat.LastClockValue)
|
s.Require().Equal(uint64(2), chat.LastClockValue)
|
||||||
|
|
||||||
// Clock is higher but lastMessage has lower clock message then the receiving one
|
// Clock is higher but lastMessage has lower clock message then the receiving one
|
||||||
message = &Message{}
|
message = &common.Message{}
|
||||||
chat = &Chat{LastClockValue: 2}
|
chat = &Chat{LastClockValue: 2}
|
||||||
|
|
||||||
message.Clock = 1
|
message.Clock = 1
|
||||||
|
@ -112,7 +114,7 @@ func (s *ChatTestSuite) TestUpdateFromMessage() {
|
||||||
s.Require().Equal(uint64(2), chat.LastClockValue)
|
s.Require().Equal(uint64(2), chat.LastClockValue)
|
||||||
|
|
||||||
chat.LastClockValue = 4
|
chat.LastClockValue = 4
|
||||||
message = &Message{}
|
message = &common.Message{}
|
||||||
message.Clock = 3
|
message.Clock = 3
|
||||||
s.Require().NoError(chat.UpdateFromMessage(message, &testTimeSource{}))
|
s.Require().NoError(chat.UpdateFromMessage(message, &testTimeSource{}))
|
||||||
s.Require().Equal(chat.LastMessage, message)
|
s.Require().Equal(chat.LastMessage, message)
|
||||||
|
@ -122,7 +124,7 @@ func (s *ChatTestSuite) TestUpdateFromMessage() {
|
||||||
|
|
||||||
func (s *ChatTestSuite) TestSerializeJSON() {
|
func (s *ChatTestSuite) TestSerializeJSON() {
|
||||||
|
|
||||||
message := &Message{}
|
message := &common.Message{}
|
||||||
chat := &Chat{}
|
chat := &Chat{}
|
||||||
|
|
||||||
message.Clock = 1
|
message.Clock = 1
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
package protocol
|
package common
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"crypto/ecdsa"
|
"crypto/ecdsa"
|
||||||
|
@ -11,7 +11,9 @@ import (
|
||||||
"unicode/utf8"
|
"unicode/utf8"
|
||||||
|
|
||||||
"github.com/golang/protobuf/proto"
|
"github.com/golang/protobuf/proto"
|
||||||
|
|
||||||
"github.com/status-im/markdown"
|
"github.com/status-im/markdown"
|
||||||
|
"github.com/status-im/markdown/ast"
|
||||||
|
|
||||||
"github.com/status-im/status-go/protocol/protobuf"
|
"github.com/status-im/status-go/protocol/protobuf"
|
||||||
)
|
)
|
||||||
|
@ -117,6 +119,9 @@ type Message struct {
|
||||||
// that has been updated
|
// that has been updated
|
||||||
Replace string `json:"replace,omitempty"`
|
Replace string `json:"replace,omitempty"`
|
||||||
SigPubKey *ecdsa.PublicKey `json:"-"`
|
SigPubKey *ecdsa.PublicKey `json:"-"`
|
||||||
|
|
||||||
|
// Mentions is an array of mentions for a given message
|
||||||
|
Mentions []string
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *Message) MarshalJSON() ([]byte, error) {
|
func (m *Message) MarshalJSON() ([]byte, error) {
|
||||||
|
@ -151,6 +156,7 @@ func (m *Message) MarshalJSON() ([]byte, error) {
|
||||||
Timestamp uint64 `json:"timestamp"`
|
Timestamp uint64 `json:"timestamp"`
|
||||||
ContentType protobuf.ChatMessage_ContentType `json:"contentType"`
|
ContentType protobuf.ChatMessage_ContentType `json:"contentType"`
|
||||||
MessageType protobuf.MessageType `json:"messageType"`
|
MessageType protobuf.MessageType `json:"messageType"`
|
||||||
|
Mentions []string `json:"mentions,omitempty"`
|
||||||
}{
|
}{
|
||||||
ID: m.ID,
|
ID: m.ID,
|
||||||
WhisperTimestamp: m.WhisperTimestamp,
|
WhisperTimestamp: m.WhisperTimestamp,
|
||||||
|
@ -174,6 +180,7 @@ func (m *Message) MarshalJSON() ([]byte, error) {
|
||||||
Audio: m.Base64Audio,
|
Audio: m.Base64Audio,
|
||||||
Timestamp: m.Timestamp,
|
Timestamp: m.Timestamp,
|
||||||
ContentType: m.ContentType,
|
ContentType: m.ContentType,
|
||||||
|
Mentions: m.Mentions,
|
||||||
MessageType: m.MessageType,
|
MessageType: m.MessageType,
|
||||||
CommandParameters: m.CommandParameters,
|
CommandParameters: m.CommandParameters,
|
||||||
}
|
}
|
||||||
|
@ -295,10 +302,34 @@ func (m *Message) parseAudio() error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// implement interface of https://github.com/status-im/markdown/blob/b9fe921681227b1dace4b56364e15edb3b698308/ast/node.go#L701
|
||||||
|
type MentionNodeVisitor struct {
|
||||||
|
mentions []string
|
||||||
|
}
|
||||||
|
|
||||||
|
func (v *MentionNodeVisitor) Visit(node ast.Node, entering bool) ast.WalkStatus {
|
||||||
|
// only on entering we fetch, otherwise we go on
|
||||||
|
if !entering {
|
||||||
|
return ast.GoToNext
|
||||||
|
}
|
||||||
|
switch n := node.(type) {
|
||||||
|
case *ast.Mention:
|
||||||
|
v.mentions = append(v.mentions, string(n.Literal))
|
||||||
|
}
|
||||||
|
return ast.GoToNext
|
||||||
|
}
|
||||||
|
|
||||||
|
func extractMentions(parsedText ast.Node) []string {
|
||||||
|
visitor := &MentionNodeVisitor{}
|
||||||
|
ast.Walk(parsedText, visitor)
|
||||||
|
return visitor.mentions
|
||||||
|
}
|
||||||
|
|
||||||
// PrepareContent return the parsed content of the message, the line-count and whether
|
// PrepareContent return the parsed content of the message, the line-count and whether
|
||||||
// is a right-to-left message
|
// is a right-to-left message
|
||||||
func (m *Message) PrepareContent() error {
|
func (m *Message) PrepareContent() error {
|
||||||
parsedText := markdown.Parse([]byte(m.Text), nil)
|
parsedText := markdown.Parse([]byte(m.Text), nil)
|
||||||
|
m.Mentions = extractMentions(parsedText)
|
||||||
jsonParsedText, err := json.Marshal(parsedText)
|
jsonParsedText, err := json.Marshal(parsedText)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
|
@ -325,11 +325,13 @@ func (p *MessageProcessor) SendPublic(
|
||||||
}
|
}
|
||||||
|
|
||||||
var newMessage *types.NewMessage
|
var newMessage *types.NewMessage
|
||||||
|
|
||||||
|
messageSpec, err := p.protocol.BuildPublicMessage(p.identity, wrappedMessage)
|
||||||
|
if err != nil {
|
||||||
|
return nil, errors.Wrap(err, "failed to wrap a public message in the encryption layer")
|
||||||
|
}
|
||||||
|
|
||||||
if !rawMessage.SkipEncryption {
|
if !rawMessage.SkipEncryption {
|
||||||
messageSpec, err := p.protocol.BuildPublicMessage(p.identity, wrappedMessage)
|
|
||||||
if err != nil {
|
|
||||||
return nil, errors.Wrap(err, "failed to wrap a public message in the encryption layer")
|
|
||||||
}
|
|
||||||
newMessage, err = MessageSpecToWhisper(messageSpec)
|
newMessage, err = MessageSpecToWhisper(messageSpec)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
|
@ -354,6 +356,13 @@ func (p *MessageProcessor) SendPublic(
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
sentMessage := &SentMessage{
|
||||||
|
Spec: messageSpec,
|
||||||
|
MessageIDs: [][]byte{messageID},
|
||||||
|
}
|
||||||
|
|
||||||
|
p.notifyOnSentMessage(sentMessage)
|
||||||
|
|
||||||
p.transport.Track([][]byte{messageID}, hash, newMessage)
|
p.transport.Track([][]byte{messageID}, hash, newMessage)
|
||||||
|
|
||||||
return messageID, nil
|
return messageID, nil
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
package protocol
|
package common
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
|
@ -7,6 +7,8 @@ import (
|
||||||
|
|
||||||
"github.com/stretchr/testify/require"
|
"github.com/stretchr/testify/require"
|
||||||
|
|
||||||
|
"github.com/status-im/status-go/eth-node/crypto"
|
||||||
|
"github.com/status-im/status-go/eth-node/types"
|
||||||
"github.com/status-im/status-go/protocol/protobuf"
|
"github.com/status-im/status-go/protocol/protobuf"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -14,7 +16,7 @@ const expectedJPEG = "data:image/jpeg;base64,/9j/2wBDAAMCAgICAgMCAgIDAwMDBAYEBAQ
|
||||||
const expectedAAC = "data:audio/aac;base64,//FQgBw//NoATGF2YzUyLjcwLjAAQniptokphEFCg5qs1v9fn48+qz1rfWNhwvz+CqB5dipmq3T2PlT1Ld6sPj+19fUt1C3NKV0KowiqohZVCrdf19WMatvV3YbIvAuy/q2RafA8UiZPmZY7DdmHZtP9ri25kedWSiMKQRt79ttlod55LkuX7/f7/f7/f7/YGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYHNqo8g5qs1v9fn48+qz1rfWNhwvz+CqAAAAAAAAAAAAAAAAAAAAAAABw//FQgCNf/CFXbUZfDKFRgsYlKDegtXJH9eLkT54uRM1ckDYDcXRzZGF6Kz5Yps5fTeLY6w7gclwly+0PJL3udY3PyekTFI65bdniF3OjvHeafzZfWTs0qRMSkdll1sbb4SNT5e8vX98ytot6jEZ0NhJi2pBVP/tKV2JMyo36n9uxR2tKR+FoLCsP4SVi49kmvaSCWm5bQD96OmVQA9Q40bqnOa7rT8j9N0TlK991XdcenGTLbyS6eUnN2U1ckf14uRPni5EzVyQAAAAAAAAAAx6Q1flBp+KH2LhgH2Xx+14QB2/jcizm6ngck4vB9DoH9/Vcb7E8Dy+D/1ii1pSPwsUUUXCSsXHsk17SBfKwn2uHr6QAAAAAAAHA//FQgBt//CF3VO1KFCFWcd/r04m+O0758/tXHUlvaqEK9lvhUZXEZMXKMV/LQ6B3/mOl/Mrfs6jpD2b7f+n4yt+tm2x5ZmnpD++dZo/V9VgblI3OW/s1b8qt0h1RBiIRIIYIYQIBeCM8yy7etkwt1JAajRSoZGwwNZ07TTFTyMR1mTUVVUTW97vaDaHU5DV1snBf0mN4fraa+rf/vpdZ8FxqatGjNxPh35UuVfpNqc48W4nZ6rOO/16cTfHad8+f2rjqS3tVAAAAAAAAAAAAAAAAAAAAAAAAAAAO//FQgBm//CEXVPU+GiFsPr7x6+N6v+m+q511I4SgtYVyoyWjcMWMxkaxxDGSx1qVcarjDESt8zLQehx/lkil/GrHBy/NfJcHek0XtfanZJLHNXO2rUnFklPAlQSBS4l0pIoXIfORcXx0UYj1nTsSe1/0wXDkkFCfxWHtqRayOmWm3oS6JGdnZdtjesjByefiS8dLW1tVVVC58ijoxN3gmGFYj07+YJ6eth9fePXxvV/031XOupHCUAAAAAAAAAAAAAAAAAAAAAAAAAAA4P/xUIAcf/whN1T9NsMOEK5rxxxxXnid+f0/Ia195vi6oGH1ZVr6kjqScdSF9lt3qXH+Lxf0fo/Oe53r99IUPzybv/YWGZ7Vgk31MGw+DMp05+3y9fPERUTHlt1c9sUyoqCaD5bdXVz2wkG0hnpDmFy8r0fr3VBn/C7Rmg+L0/45EWfdocGq3HQ1uRro0GJK+vsvo837NR82s01l/n97rsWn7RYNBM3WRcDY3cJKosqMJhgdHtj9yflthd65rxxxxXnid+f0/Ia195vi6oAAAAAAAAAAAAAAAAAAAAAAAAAAAABw"
|
const expectedAAC = "data:audio/aac;base64,//FQgBw//NoATGF2YzUyLjcwLjAAQniptokphEFCg5qs1v9fn48+qz1rfWNhwvz+CqB5dipmq3T2PlT1Ld6sPj+19fUt1C3NKV0KowiqohZVCrdf19WMatvV3YbIvAuy/q2RafA8UiZPmZY7DdmHZtP9ri25kedWSiMKQRt79ttlod55LkuX7/f7/f7/f7/YGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYHNqo8g5qs1v9fn48+qz1rfWNhwvz+CqAAAAAAAAAAAAAAAAAAAAAAABw//FQgCNf/CFXbUZfDKFRgsYlKDegtXJH9eLkT54uRM1ckDYDcXRzZGF6Kz5Yps5fTeLY6w7gclwly+0PJL3udY3PyekTFI65bdniF3OjvHeafzZfWTs0qRMSkdll1sbb4SNT5e8vX98ytot6jEZ0NhJi2pBVP/tKV2JMyo36n9uxR2tKR+FoLCsP4SVi49kmvaSCWm5bQD96OmVQA9Q40bqnOa7rT8j9N0TlK991XdcenGTLbyS6eUnN2U1ckf14uRPni5EzVyQAAAAAAAAAAx6Q1flBp+KH2LhgH2Xx+14QB2/jcizm6ngck4vB9DoH9/Vcb7E8Dy+D/1ii1pSPwsUUUXCSsXHsk17SBfKwn2uHr6QAAAAAAAHA//FQgBt//CF3VO1KFCFWcd/r04m+O0758/tXHUlvaqEK9lvhUZXEZMXKMV/LQ6B3/mOl/Mrfs6jpD2b7f+n4yt+tm2x5ZmnpD++dZo/V9VgblI3OW/s1b8qt0h1RBiIRIIYIYQIBeCM8yy7etkwt1JAajRSoZGwwNZ07TTFTyMR1mTUVVUTW97vaDaHU5DV1snBf0mN4fraa+rf/vpdZ8FxqatGjNxPh35UuVfpNqc48W4nZ6rOO/16cTfHad8+f2rjqS3tVAAAAAAAAAAAAAAAAAAAAAAAAAAAO//FQgBm//CEXVPU+GiFsPr7x6+N6v+m+q511I4SgtYVyoyWjcMWMxkaxxDGSx1qVcarjDESt8zLQehx/lkil/GrHBy/NfJcHek0XtfanZJLHNXO2rUnFklPAlQSBS4l0pIoXIfORcXx0UYj1nTsSe1/0wXDkkFCfxWHtqRayOmWm3oS6JGdnZdtjesjByefiS8dLW1tVVVC58ijoxN3gmGFYj07+YJ6eth9fePXxvV/031XOupHCUAAAAAAAAAAAAAAAAAAAAAAAAAAA4P/xUIAcf/whN1T9NsMOEK5rxxxxXnid+f0/Ia195vi6oGH1ZVr6kjqScdSF9lt3qXH+Lxf0fo/Oe53r99IUPzybv/YWGZ7Vgk31MGw+DMp05+3y9fPERUTHlt1c9sUyoqCaD5bdXVz2wkG0hnpDmFy8r0fr3VBn/C7Rmg+L0/45EWfdocGq3HQ1uRro0GJK+vsvo837NR82s01l/n97rsWn7RYNBM3WRcDY3cJKosqMJhgdHtj9yflthd65rxxxxXnid+f0/Ia195vi6oAAAAAAAAAAAAAAAAAAAAAAAAAAAABw"
|
||||||
|
|
||||||
func TestPrepareContentImage(t *testing.T) {
|
func TestPrepareContentImage(t *testing.T) {
|
||||||
file, err := os.Open("../_assets/tests/test.jpg")
|
file, err := os.Open("../../_assets/tests/test.jpg")
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
defer file.Close()
|
defer file.Close()
|
||||||
|
|
||||||
|
@ -60,7 +62,7 @@ func TestGetImageMessageMIME(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestPrepareContentAudio(t *testing.T) {
|
func TestPrepareContentAudio(t *testing.T) {
|
||||||
file, err := os.Open("../_assets/tests/test.aac")
|
file, err := os.Open("../../_assets/tests/test.aac")
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
defer file.Close()
|
defer file.Close()
|
||||||
|
|
||||||
|
@ -94,3 +96,21 @@ func TestGetAudioMessageMIME(t *testing.T) {
|
||||||
_, err = getImageMessageMIME(unknown)
|
_, err = getImageMessageMIME(unknown)
|
||||||
require.Error(t, err)
|
require.Error(t, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestPrepareContentMentions(t *testing.T) {
|
||||||
|
message := &Message{}
|
||||||
|
pk1, err := crypto.GenerateKey()
|
||||||
|
require.NoError(t, err)
|
||||||
|
pk1String := types.EncodeHex(crypto.FromECDSAPub(&pk1.PublicKey))
|
||||||
|
|
||||||
|
pk2, err := crypto.GenerateKey()
|
||||||
|
require.NoError(t, err)
|
||||||
|
pk2String := types.EncodeHex(crypto.FromECDSAPub(&pk2.PublicKey))
|
||||||
|
|
||||||
|
message.Text = "hey @" + pk1String + " @" + pk2String
|
||||||
|
|
||||||
|
require.NoError(t, message.PrepareContent())
|
||||||
|
require.Len(t, message.Mentions, 2)
|
||||||
|
require.Equal(t, message.Mentions[0], pk1String)
|
||||||
|
require.Equal(t, message.Mentions[1], pk2String)
|
||||||
|
}
|
|
@ -6,6 +6,7 @@ import (
|
||||||
|
|
||||||
"github.com/status-im/status-go/eth-node/crypto"
|
"github.com/status-im/status-go/eth-node/crypto"
|
||||||
"github.com/status-im/status-go/eth-node/types"
|
"github.com/status-im/status-go/eth-node/types"
|
||||||
|
"github.com/status-im/status-go/protocol/common"
|
||||||
"github.com/status-im/status-go/protocol/protobuf"
|
"github.com/status-im/status-go/protocol/protobuf"
|
||||||
v1protocol "github.com/status-im/status-go/protocol/v1"
|
v1protocol "github.com/status-im/status-go/protocol/v1"
|
||||||
)
|
)
|
||||||
|
@ -27,7 +28,7 @@ func tsprintf(format string, params map[string]string) string {
|
||||||
return format
|
return format
|
||||||
}
|
}
|
||||||
|
|
||||||
func eventToSystemMessage(e v1protocol.MembershipUpdateEvent, translations map[protobuf.MembershipUpdateEvent_EventType]string) *Message {
|
func eventToSystemMessage(e v1protocol.MembershipUpdateEvent, translations map[protobuf.MembershipUpdateEvent_EventType]string) *common.Message {
|
||||||
var text string
|
var text string
|
||||||
switch e.Type {
|
switch e.Type {
|
||||||
case protobuf.MembershipUpdateEvent_CHAT_CREATED:
|
case protobuf.MembershipUpdateEvent_CHAT_CREATED:
|
||||||
|
@ -56,7 +57,7 @@ func eventToSystemMessage(e v1protocol.MembershipUpdateEvent, translations map[p
|
||||||
|
|
||||||
}
|
}
|
||||||
timestamp := v1protocol.TimestampInMsFromTime(time.Now())
|
timestamp := v1protocol.TimestampInMsFromTime(time.Now())
|
||||||
message := &Message{
|
message := &common.Message{
|
||||||
ChatMessage: protobuf.ChatMessage{
|
ChatMessage: protobuf.ChatMessage{
|
||||||
ChatId: e.ChatID,
|
ChatId: e.ChatID,
|
||||||
Text: text,
|
Text: text,
|
||||||
|
@ -75,8 +76,8 @@ func eventToSystemMessage(e v1protocol.MembershipUpdateEvent, translations map[p
|
||||||
return message
|
return message
|
||||||
}
|
}
|
||||||
|
|
||||||
func buildSystemMessages(events []v1protocol.MembershipUpdateEvent, translations map[protobuf.MembershipUpdateEvent_EventType]string) []*Message {
|
func buildSystemMessages(events []v1protocol.MembershipUpdateEvent, translations map[protobuf.MembershipUpdateEvent_EventType]string) []*common.Message {
|
||||||
var messages []*Message
|
var messages []*common.Message
|
||||||
|
|
||||||
for _, e := range events {
|
for _, e := range events {
|
||||||
messages = append(messages, eventToSystemMessage(e, translations))
|
messages = append(messages, eventToSystemMessage(e, translations))
|
||||||
|
|
|
@ -5,11 +5,12 @@ import (
|
||||||
|
|
||||||
"github.com/status-im/status-go/eth-node/crypto"
|
"github.com/status-im/status-go/eth-node/crypto"
|
||||||
"github.com/status-im/status-go/eth-node/types"
|
"github.com/status-im/status-go/eth-node/types"
|
||||||
|
"github.com/status-im/status-go/protocol/common"
|
||||||
"github.com/status-im/status-go/protocol/identity/alias"
|
"github.com/status-im/status-go/protocol/identity/alias"
|
||||||
"github.com/status-im/status-go/protocol/identity/identicon"
|
"github.com/status-im/status-go/protocol/identity/identicon"
|
||||||
)
|
)
|
||||||
|
|
||||||
func extendMessageFromChat(message *Message, chat *Chat, key *ecdsa.PublicKey, timesource TimeSource) error {
|
func extendMessageFromChat(message *common.Message, chat *Chat, key *ecdsa.PublicKey, timesource TimeSource) error {
|
||||||
clock, timestamp := chat.NextClockAndTimestamp(timesource)
|
clock, timestamp := chat.NextClockAndTimestamp(timesource)
|
||||||
|
|
||||||
message.LocalChatID = chat.ID
|
message.LocalChatID = chat.ID
|
||||||
|
@ -19,7 +20,7 @@ func extendMessageFromChat(message *Message, chat *Chat, key *ecdsa.PublicKey, t
|
||||||
message.SigPubKey = key
|
message.SigPubKey = key
|
||||||
message.WhisperTimestamp = timestamp
|
message.WhisperTimestamp = timestamp
|
||||||
message.Seen = true
|
message.Seen = true
|
||||||
message.OutgoingStatus = OutgoingStatusSending
|
message.OutgoingStatus = common.OutgoingStatusSending
|
||||||
|
|
||||||
identicon, err := identicon.GenerateBase64(message.From)
|
identicon, err := identicon.GenerateBase64(message.From)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
|
@ -145,7 +145,7 @@ func (m *MessageHandler) HandleMembershipUpdate(messageState *ReceivedMessageSta
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *MessageHandler) handleCommandMessage(state *ReceivedMessageState, message *Message) error {
|
func (m *MessageHandler) handleCommandMessage(state *ReceivedMessageState, message *common.Message) error {
|
||||||
message.ID = state.CurrentMessageState.MessageID
|
message.ID = state.CurrentMessageState.MessageID
|
||||||
message.From = state.CurrentMessageState.Contact.ID
|
message.From = state.CurrentMessageState.Contact.ID
|
||||||
message.Alias = state.CurrentMessageState.Contact.Alias
|
message.Alias = state.CurrentMessageState.Contact.Alias
|
||||||
|
@ -182,7 +182,7 @@ func (m *MessageHandler) handleCommandMessage(state *ReceivedMessageState, messa
|
||||||
message.OutgoingStatus = ""
|
message.OutgoingStatus = ""
|
||||||
} else {
|
} else {
|
||||||
// Our own message, mark as sent
|
// Our own message, mark as sent
|
||||||
message.OutgoingStatus = OutgoingStatusSent
|
message.OutgoingStatus = common.OutgoingStatusSent
|
||||||
}
|
}
|
||||||
|
|
||||||
err = chat.UpdateFromMessage(message, state.Timesource)
|
err = chat.UpdateFromMessage(message, state.Timesource)
|
||||||
|
@ -248,11 +248,11 @@ func (m *MessageHandler) HandleSyncInstallationContact(state *ReceivedMessageSta
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *MessageHandler) HandleSyncInstallationPublicChat(state *ReceivedMessageState, message protobuf.SyncInstallationPublicChat) error {
|
func (m *MessageHandler) HandleSyncInstallationPublicChat(state *ReceivedMessageState, message protobuf.SyncInstallationPublicChat) bool {
|
||||||
chatID := message.Id
|
chatID := message.Id
|
||||||
_, ok := state.AllChats[chatID]
|
_, ok := state.AllChats[chatID]
|
||||||
if ok {
|
if ok {
|
||||||
return nil
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
chat := CreatePublicChat(chatID, state.Timesource)
|
chat := CreatePublicChat(chatID, state.Timesource)
|
||||||
|
@ -260,7 +260,7 @@ func (m *MessageHandler) HandleSyncInstallationPublicChat(state *ReceivedMessage
|
||||||
state.AllChats[chat.ID] = &chat
|
state.AllChats[chat.ID] = &chat
|
||||||
state.ModifiedChats[chat.ID] = true
|
state.ModifiedChats[chat.ID] = true
|
||||||
|
|
||||||
return nil
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *MessageHandler) HandleContactUpdate(state *ReceivedMessageState, message protobuf.ContactUpdate) error {
|
func (m *MessageHandler) HandleContactUpdate(state *ReceivedMessageState, message protobuf.ContactUpdate) error {
|
||||||
|
@ -330,7 +330,7 @@ func (m *MessageHandler) HandleChatMessage(state *ReceivedMessageState) error {
|
||||||
logger.Warn("failed to validate message", zap.Error(err))
|
logger.Warn("failed to validate message", zap.Error(err))
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
receivedMessage := &Message{
|
receivedMessage := &common.Message{
|
||||||
ID: state.CurrentMessageState.MessageID,
|
ID: state.CurrentMessageState.MessageID,
|
||||||
ChatMessage: state.CurrentMessageState.Message,
|
ChatMessage: state.CurrentMessageState.Message,
|
||||||
From: state.CurrentMessageState.Contact.ID,
|
From: state.CurrentMessageState.Contact.ID,
|
||||||
|
@ -369,7 +369,7 @@ func (m *MessageHandler) HandleChatMessage(state *ReceivedMessageState) error {
|
||||||
chat.UnviewedMessagesCount++
|
chat.UnviewedMessagesCount++
|
||||||
} else {
|
} else {
|
||||||
// Our own message, mark as sent
|
// Our own message, mark as sent
|
||||||
receivedMessage.OutgoingStatus = OutgoingStatusSent
|
receivedMessage.OutgoingStatus = common.OutgoingStatusSent
|
||||||
}
|
}
|
||||||
|
|
||||||
err = chat.UpdateFromMessage(receivedMessage, state.Timesource)
|
err = chat.UpdateFromMessage(receivedMessage, state.Timesource)
|
||||||
|
@ -401,7 +401,7 @@ func (m *MessageHandler) HandleRequestAddressForTransaction(messageState *Receiv
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
message := &Message{
|
message := &common.Message{
|
||||||
ChatMessage: protobuf.ChatMessage{
|
ChatMessage: protobuf.ChatMessage{
|
||||||
Clock: command.Clock,
|
Clock: command.Clock,
|
||||||
Timestamp: messageState.CurrentMessageState.WhisperTimestamp,
|
Timestamp: messageState.CurrentMessageState.WhisperTimestamp,
|
||||||
|
@ -410,11 +410,11 @@ func (m *MessageHandler) HandleRequestAddressForTransaction(messageState *Receiv
|
||||||
MessageType: protobuf.MessageType_ONE_TO_ONE,
|
MessageType: protobuf.MessageType_ONE_TO_ONE,
|
||||||
ContentType: protobuf.ChatMessage_TRANSACTION_COMMAND,
|
ContentType: protobuf.ChatMessage_TRANSACTION_COMMAND,
|
||||||
},
|
},
|
||||||
CommandParameters: &CommandParameters{
|
CommandParameters: &common.CommandParameters{
|
||||||
ID: messageState.CurrentMessageState.MessageID,
|
ID: messageState.CurrentMessageState.MessageID,
|
||||||
Value: command.Value,
|
Value: command.Value,
|
||||||
Contract: command.Contract,
|
Contract: command.Contract,
|
||||||
CommandState: CommandStateRequestAddressForTransaction,
|
CommandState: common.CommandStateRequestAddressForTransaction,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
return m.handleCommandMessage(messageState, message)
|
return m.handleCommandMessage(messageState, message)
|
||||||
|
@ -425,7 +425,7 @@ func (m *MessageHandler) HandleRequestTransaction(messageState *ReceivedMessageS
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
message := &Message{
|
message := &common.Message{
|
||||||
ChatMessage: protobuf.ChatMessage{
|
ChatMessage: protobuf.ChatMessage{
|
||||||
Clock: command.Clock,
|
Clock: command.Clock,
|
||||||
Timestamp: messageState.CurrentMessageState.WhisperTimestamp,
|
Timestamp: messageState.CurrentMessageState.WhisperTimestamp,
|
||||||
|
@ -434,11 +434,11 @@ func (m *MessageHandler) HandleRequestTransaction(messageState *ReceivedMessageS
|
||||||
MessageType: protobuf.MessageType_ONE_TO_ONE,
|
MessageType: protobuf.MessageType_ONE_TO_ONE,
|
||||||
ContentType: protobuf.ChatMessage_TRANSACTION_COMMAND,
|
ContentType: protobuf.ChatMessage_TRANSACTION_COMMAND,
|
||||||
},
|
},
|
||||||
CommandParameters: &CommandParameters{
|
CommandParameters: &common.CommandParameters{
|
||||||
ID: messageState.CurrentMessageState.MessageID,
|
ID: messageState.CurrentMessageState.MessageID,
|
||||||
Value: command.Value,
|
Value: command.Value,
|
||||||
Contract: command.Contract,
|
Contract: command.Contract,
|
||||||
CommandState: CommandStateRequestTransaction,
|
CommandState: common.CommandStateRequestTransaction,
|
||||||
Address: command.Address,
|
Address: command.Address,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
@ -466,7 +466,7 @@ func (m *MessageHandler) HandleAcceptRequestAddressForTransaction(messageState *
|
||||||
return errors.New("Initial message must originate from us")
|
return errors.New("Initial message must originate from us")
|
||||||
}
|
}
|
||||||
|
|
||||||
if initialMessage.CommandParameters.CommandState != CommandStateRequestAddressForTransaction {
|
if initialMessage.CommandParameters.CommandState != common.CommandStateRequestAddressForTransaction {
|
||||||
return errors.New("Wrong state for command")
|
return errors.New("Wrong state for command")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -475,7 +475,7 @@ func (m *MessageHandler) HandleAcceptRequestAddressForTransaction(messageState *
|
||||||
initialMessage.Text = requestAddressForTransactionAcceptedMessage
|
initialMessage.Text = requestAddressForTransactionAcceptedMessage
|
||||||
initialMessage.CommandParameters.Address = command.Address
|
initialMessage.CommandParameters.Address = command.Address
|
||||||
initialMessage.Seen = false
|
initialMessage.Seen = false
|
||||||
initialMessage.CommandParameters.CommandState = CommandStateRequestAddressForTransactionAccepted
|
initialMessage.CommandParameters.CommandState = common.CommandStateRequestAddressForTransactionAccepted
|
||||||
|
|
||||||
// Hide previous message
|
// Hide previous message
|
||||||
previousMessage, err := m.persistence.MessageByCommandID(messageState.CurrentMessageState.Contact.ID, command.Id)
|
previousMessage, err := m.persistence.MessageByCommandID(messageState.CurrentMessageState.Contact.ID, command.Id)
|
||||||
|
@ -536,7 +536,7 @@ func (m *MessageHandler) HandleDeclineRequestAddressForTransaction(messageState
|
||||||
return errors.New("Initial message must originate from us")
|
return errors.New("Initial message must originate from us")
|
||||||
}
|
}
|
||||||
|
|
||||||
if oldMessage.CommandParameters.CommandState != CommandStateRequestAddressForTransaction {
|
if oldMessage.CommandParameters.CommandState != common.CommandStateRequestAddressForTransaction {
|
||||||
return errors.New("Wrong state for command")
|
return errors.New("Wrong state for command")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -544,7 +544,7 @@ func (m *MessageHandler) HandleDeclineRequestAddressForTransaction(messageState
|
||||||
oldMessage.Timestamp = messageState.CurrentMessageState.WhisperTimestamp
|
oldMessage.Timestamp = messageState.CurrentMessageState.WhisperTimestamp
|
||||||
oldMessage.Text = requestAddressForTransactionDeclinedMessage
|
oldMessage.Text = requestAddressForTransactionDeclinedMessage
|
||||||
oldMessage.Seen = false
|
oldMessage.Seen = false
|
||||||
oldMessage.CommandParameters.CommandState = CommandStateRequestAddressForTransactionDeclined
|
oldMessage.CommandParameters.CommandState = common.CommandStateRequestAddressForTransactionDeclined
|
||||||
|
|
||||||
// Hide previous message
|
// Hide previous message
|
||||||
err = m.persistence.HideMessage(command.Id)
|
err = m.persistence.HideMessage(command.Id)
|
||||||
|
@ -577,7 +577,7 @@ func (m *MessageHandler) HandleDeclineRequestTransaction(messageState *ReceivedM
|
||||||
return errors.New("Initial message must originate from us")
|
return errors.New("Initial message must originate from us")
|
||||||
}
|
}
|
||||||
|
|
||||||
if oldMessage.CommandParameters.CommandState != CommandStateRequestTransaction {
|
if oldMessage.CommandParameters.CommandState != common.CommandStateRequestTransaction {
|
||||||
return errors.New("Wrong state for command")
|
return errors.New("Wrong state for command")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -585,7 +585,7 @@ func (m *MessageHandler) HandleDeclineRequestTransaction(messageState *ReceivedM
|
||||||
oldMessage.Timestamp = messageState.CurrentMessageState.WhisperTimestamp
|
oldMessage.Timestamp = messageState.CurrentMessageState.WhisperTimestamp
|
||||||
oldMessage.Text = transactionRequestDeclinedMessage
|
oldMessage.Text = transactionRequestDeclinedMessage
|
||||||
oldMessage.Seen = false
|
oldMessage.Seen = false
|
||||||
oldMessage.CommandParameters.CommandState = CommandStateRequestTransactionDeclined
|
oldMessage.CommandParameters.CommandState = common.CommandStateRequestTransactionDeclined
|
||||||
|
|
||||||
// Hide previous message
|
// Hide previous message
|
||||||
err = m.persistence.HideMessage(command.Id)
|
err = m.persistence.HideMessage(command.Id)
|
||||||
|
|
|
@ -7,6 +7,7 @@ import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
|
"github.com/status-im/status-go/protocol/common"
|
||||||
"github.com/status-im/status-go/protocol/protobuf"
|
"github.com/status-im/status-go/protocol/protobuf"
|
||||||
|
|
||||||
"github.com/pkg/errors"
|
"github.com/pkg/errors"
|
||||||
|
@ -40,6 +41,7 @@ func (db sqlitePersistence) tableUserMessagesAllFields() string {
|
||||||
audio_type,
|
audio_type,
|
||||||
audio_duration_ms,
|
audio_duration_ms,
|
||||||
audio_base64,
|
audio_base64,
|
||||||
|
mentions,
|
||||||
command_id,
|
command_id,
|
||||||
command_value,
|
command_value,
|
||||||
command_from,
|
command_from,
|
||||||
|
@ -74,6 +76,7 @@ func (db sqlitePersistence) tableUserMessagesAllFieldsJoin() string {
|
||||||
m1.image_base64,
|
m1.image_base64,
|
||||||
COALESCE(m1.audio_duration_ms,0),
|
COALESCE(m1.audio_duration_ms,0),
|
||||||
m1.audio_base64,
|
m1.audio_base64,
|
||||||
|
m1.mentions,
|
||||||
m1.command_id,
|
m1.command_id,
|
||||||
m1.command_value,
|
m1.command_value,
|
||||||
m1.command_from,
|
m1.command_from,
|
||||||
|
@ -104,18 +107,19 @@ type scanner interface {
|
||||||
Scan(dest ...interface{}) error
|
Scan(dest ...interface{}) error
|
||||||
}
|
}
|
||||||
|
|
||||||
func (db sqlitePersistence) tableUserMessagesScanAllFields(row scanner, message *Message, others ...interface{}) error {
|
func (db sqlitePersistence) tableUserMessagesScanAllFields(row scanner, message *common.Message, others ...interface{}) error {
|
||||||
var quotedText sql.NullString
|
var quotedText sql.NullString
|
||||||
var quotedParsedText []byte
|
var quotedParsedText []byte
|
||||||
var quotedFrom sql.NullString
|
var quotedFrom sql.NullString
|
||||||
var quotedImage sql.NullString
|
var quotedImage sql.NullString
|
||||||
var quotedAudio sql.NullString
|
var quotedAudio sql.NullString
|
||||||
var quotedAudioDuration sql.NullInt64
|
var quotedAudioDuration sql.NullInt64
|
||||||
|
var serializedMentions []byte
|
||||||
var alias sql.NullString
|
var alias sql.NullString
|
||||||
var identicon sql.NullString
|
var identicon sql.NullString
|
||||||
|
|
||||||
sticker := &protobuf.StickerMessage{}
|
sticker := &protobuf.StickerMessage{}
|
||||||
command := &CommandParameters{}
|
command := &common.CommandParameters{}
|
||||||
audio := &protobuf.AudioMessage{}
|
audio := &protobuf.AudioMessage{}
|
||||||
|
|
||||||
args := []interface{}{
|
args := []interface{}{
|
||||||
|
@ -138,6 +142,7 @@ func (db sqlitePersistence) tableUserMessagesScanAllFields(row scanner, message
|
||||||
&message.Base64Image,
|
&message.Base64Image,
|
||||||
&audio.DurationMs,
|
&audio.DurationMs,
|
||||||
&message.Base64Audio,
|
&message.Base64Audio,
|
||||||
|
&serializedMentions,
|
||||||
&command.ID,
|
&command.ID,
|
||||||
&command.Value,
|
&command.Value,
|
||||||
&command.From,
|
&command.From,
|
||||||
|
@ -165,7 +170,7 @@ func (db sqlitePersistence) tableUserMessagesScanAllFields(row scanner, message
|
||||||
}
|
}
|
||||||
|
|
||||||
if quotedText.Valid {
|
if quotedText.Valid {
|
||||||
message.QuotedMessage = &QuotedMessage{
|
message.QuotedMessage = &common.QuotedMessage{
|
||||||
From: quotedFrom.String,
|
From: quotedFrom.String,
|
||||||
Text: quotedText.String,
|
Text: quotedText.String,
|
||||||
ParsedText: quotedParsedText,
|
ParsedText: quotedParsedText,
|
||||||
|
@ -177,6 +182,13 @@ func (db sqlitePersistence) tableUserMessagesScanAllFields(row scanner, message
|
||||||
message.Alias = alias.String
|
message.Alias = alias.String
|
||||||
message.Identicon = identicon.String
|
message.Identicon = identicon.String
|
||||||
|
|
||||||
|
if serializedMentions != nil {
|
||||||
|
err := json.Unmarshal(serializedMentions, &message.Mentions)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
switch message.ContentType {
|
switch message.ContentType {
|
||||||
case protobuf.ChatMessage_STICKER:
|
case protobuf.ChatMessage_STICKER:
|
||||||
message.Payload = &protobuf.ChatMessage_Sticker{Sticker: sticker}
|
message.Payload = &protobuf.ChatMessage_Sticker{Sticker: sticker}
|
||||||
|
@ -191,7 +203,7 @@ func (db sqlitePersistence) tableUserMessagesScanAllFields(row scanner, message
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (db sqlitePersistence) tableUserMessagesAllValues(message *Message) ([]interface{}, error) {
|
func (db sqlitePersistence) tableUserMessagesAllValues(message *common.Message) ([]interface{}, error) {
|
||||||
sticker := message.GetSticker()
|
sticker := message.GetSticker()
|
||||||
if sticker == nil {
|
if sticker == nil {
|
||||||
sticker = &protobuf.StickerMessage{}
|
sticker = &protobuf.StickerMessage{}
|
||||||
|
@ -209,7 +221,16 @@ func (db sqlitePersistence) tableUserMessagesAllValues(message *Message) ([]inte
|
||||||
|
|
||||||
command := message.CommandParameters
|
command := message.CommandParameters
|
||||||
if command == nil {
|
if command == nil {
|
||||||
command = &CommandParameters{}
|
command = &common.CommandParameters{}
|
||||||
|
}
|
||||||
|
|
||||||
|
var serializedMentions []byte
|
||||||
|
var err error
|
||||||
|
if len(message.Mentions) != 0 {
|
||||||
|
serializedMentions, err = json.Marshal(message.Mentions)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return []interface{}{
|
return []interface{}{
|
||||||
message.ID,
|
message.ID,
|
||||||
|
@ -235,6 +256,7 @@ func (db sqlitePersistence) tableUserMessagesAllValues(message *Message) ([]inte
|
||||||
audio.Type,
|
audio.Type,
|
||||||
audio.DurationMs,
|
audio.DurationMs,
|
||||||
message.Base64Audio,
|
message.Base64Audio,
|
||||||
|
serializedMentions,
|
||||||
command.ID,
|
command.ID,
|
||||||
command.Value,
|
command.Value,
|
||||||
command.From,
|
command.From,
|
||||||
|
@ -250,7 +272,7 @@ func (db sqlitePersistence) tableUserMessagesAllValues(message *Message) ([]inte
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (db sqlitePersistence) messageByID(tx *sql.Tx, id string) (*Message, error) {
|
func (db sqlitePersistence) messageByID(tx *sql.Tx, id string) (*common.Message, error) {
|
||||||
var err error
|
var err error
|
||||||
if tx == nil {
|
if tx == nil {
|
||||||
tx, err = db.db.BeginTx(context.Background(), &sql.TxOptions{})
|
tx, err = db.db.BeginTx(context.Background(), &sql.TxOptions{})
|
||||||
|
@ -267,7 +289,7 @@ func (db sqlitePersistence) messageByID(tx *sql.Tx, id string) (*Message, error)
|
||||||
}()
|
}()
|
||||||
}
|
}
|
||||||
|
|
||||||
var message Message
|
var message common.Message
|
||||||
|
|
||||||
allFields := db.tableUserMessagesAllFieldsJoin()
|
allFields := db.tableUserMessagesAllFieldsJoin()
|
||||||
row := tx.QueryRow(
|
row := tx.QueryRow(
|
||||||
|
@ -301,9 +323,9 @@ func (db sqlitePersistence) messageByID(tx *sql.Tx, id string) (*Message, error)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (db sqlitePersistence) MessageByCommandID(chatID, id string) (*Message, error) {
|
func (db sqlitePersistence) MessageByCommandID(chatID, id string) (*common.Message, error) {
|
||||||
|
|
||||||
var message Message
|
var message common.Message
|
||||||
|
|
||||||
allFields := db.tableUserMessagesAllFieldsJoin()
|
allFields := db.tableUserMessagesAllFieldsJoin()
|
||||||
row := db.db.QueryRow(
|
row := db.db.QueryRow(
|
||||||
|
@ -342,7 +364,7 @@ func (db sqlitePersistence) MessageByCommandID(chatID, id string) (*Message, err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (db sqlitePersistence) MessageByID(id string) (*Message, error) {
|
func (db sqlitePersistence) MessageByID(id string) (*common.Message, error) {
|
||||||
return db.messageByID(nil, id)
|
return db.messageByID(nil, id)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -377,7 +399,7 @@ func (db sqlitePersistence) MessagesExist(ids []string) (map[string]bool, error)
|
||||||
return result, nil
|
return result, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (db sqlitePersistence) MessagesByIDs(ids []string) ([]*Message, error) {
|
func (db sqlitePersistence) MessagesByIDs(ids []string) ([]*common.Message, error) {
|
||||||
if len(ids) == 0 {
|
if len(ids) == 0 {
|
||||||
return nil, nil
|
return nil, nil
|
||||||
}
|
}
|
||||||
|
@ -412,9 +434,9 @@ func (db sqlitePersistence) MessagesByIDs(ids []string) ([]*Message, error) {
|
||||||
}
|
}
|
||||||
defer rows.Close()
|
defer rows.Close()
|
||||||
|
|
||||||
var result []*Message
|
var result []*common.Message
|
||||||
for rows.Next() {
|
for rows.Next() {
|
||||||
var message Message
|
var message common.Message
|
||||||
if err := db.tableUserMessagesScanAllFields(rows, &message); err != nil {
|
if err := db.tableUserMessagesScanAllFields(rows, &message); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
@ -427,7 +449,7 @@ func (db sqlitePersistence) MessagesByIDs(ids []string) ([]*Message, error) {
|
||||||
// MessageByChatID returns all messages for a given chatID in descending order.
|
// MessageByChatID returns all messages for a given chatID in descending order.
|
||||||
// Ordering is accomplished using two concatenated values: ClockValue and ID.
|
// Ordering is accomplished using two concatenated values: ClockValue and ID.
|
||||||
// These two values are also used to compose a cursor which is returned to the result.
|
// These two values are also used to compose a cursor which is returned to the result.
|
||||||
func (db sqlitePersistence) MessageByChatID(chatID string, currCursor string, limit int) ([]*Message, string, error) {
|
func (db sqlitePersistence) MessageByChatID(chatID string, currCursor string, limit int) ([]*common.Message, string, error) {
|
||||||
cursorWhere := ""
|
cursorWhere := ""
|
||||||
if currCursor != "" {
|
if currCursor != "" {
|
||||||
cursorWhere = "AND cursor <= ?"
|
cursorWhere = "AND cursor <= ?"
|
||||||
|
@ -470,12 +492,12 @@ func (db sqlitePersistence) MessageByChatID(chatID string, currCursor string, li
|
||||||
defer rows.Close()
|
defer rows.Close()
|
||||||
|
|
||||||
var (
|
var (
|
||||||
result []*Message
|
result []*common.Message
|
||||||
cursors []string
|
cursors []string
|
||||||
)
|
)
|
||||||
for rows.Next() {
|
for rows.Next() {
|
||||||
var (
|
var (
|
||||||
message Message
|
message common.Message
|
||||||
cursor string
|
cursor string
|
||||||
)
|
)
|
||||||
if err := db.tableUserMessagesScanAllFields(rows, &message, &cursor); err != nil {
|
if err := db.tableUserMessagesScanAllFields(rows, &message, &cursor); err != nil {
|
||||||
|
@ -566,7 +588,7 @@ func (db sqlitePersistence) EmojiReactionsByChatID(chatID string, currCursor str
|
||||||
return result, nil
|
return result, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (db sqlitePersistence) SaveMessages(messages []*Message) (err error) {
|
func (db sqlitePersistence) SaveMessages(messages []*common.Message) (err error) {
|
||||||
tx, err := db.db.BeginTx(context.Background(), &sql.TxOptions{})
|
tx, err := db.db.BeginTx(context.Background(), &sql.TxOptions{})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return
|
return
|
||||||
|
|
|
@ -91,7 +91,7 @@ type RawResponse struct {
|
||||||
|
|
||||||
type MessengerResponse struct {
|
type MessengerResponse struct {
|
||||||
Chats []*Chat `json:"chats,omitempty"`
|
Chats []*Chat `json:"chats,omitempty"`
|
||||||
Messages []*Message `json:"messages,omitempty"`
|
Messages []*common.Message `json:"messages,omitempty"`
|
||||||
Contacts []*Contact `json:"contacts,omitempty"`
|
Contacts []*Contact `json:"contacts,omitempty"`
|
||||||
Installations []*multidevice.Installation `json:"installations,omitempty"`
|
Installations []*multidevice.Installation `json:"installations,omitempty"`
|
||||||
EmojiReactions []*EmojiReaction `json:"emojiReactions,omitempty"`
|
EmojiReactions []*EmojiReaction `json:"emojiReactions,omitempty"`
|
||||||
|
@ -227,7 +227,7 @@ func NewMessenger(
|
||||||
pushNotificationClientConfig.Logger = logger
|
pushNotificationClientConfig.Logger = logger
|
||||||
pushNotificationClientConfig.InstallationID = installationID
|
pushNotificationClientConfig.InstallationID = installationID
|
||||||
|
|
||||||
pushNotificationClient := pushnotificationclient.New(pushNotificationClientPersistence, pushNotificationClientConfig, processor)
|
pushNotificationClient := pushnotificationclient.New(pushNotificationClientPersistence, pushNotificationClientConfig, processor, &sqlitePersistence{db: database})
|
||||||
|
|
||||||
handler := newMessageHandler(identity, logger, &sqlitePersistence{db: database})
|
handler := newMessageHandler(identity, logger, &sqlitePersistence{db: database})
|
||||||
|
|
||||||
|
@ -1358,7 +1358,7 @@ func (m *Messenger) LeaveGroupChat(ctx context.Context, chatID string, remove bo
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *Messenger) saveChat(chat *Chat) error {
|
func (m *Messenger) saveChat(chat *Chat) error {
|
||||||
_, ok := m.allChats[chat.ID]
|
previousChat, ok := m.allChats[chat.ID]
|
||||||
if chat.OneToOne() {
|
if chat.OneToOne() {
|
||||||
name, identicon, err := generateAliasAndIdenticon(chat.ID)
|
name, identicon, err := generateAliasAndIdenticon(chat.ID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -1370,11 +1370,21 @@ func (m *Messenger) saveChat(chat *Chat) error {
|
||||||
}
|
}
|
||||||
// Sync chat if it's a new active public chat
|
// Sync chat if it's a new active public chat
|
||||||
if !ok && chat.Active && chat.Public() {
|
if !ok && chat.Active && chat.Public() {
|
||||||
|
|
||||||
if err := m.syncPublicChat(context.Background(), chat); err != nil {
|
if err := m.syncPublicChat(context.Background(), chat); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// We check if it's a new chat, or chat.Active has changed
|
||||||
|
if chat.Public() && (!ok && chat.Active) || (ok && chat.Active != previousChat.Active) {
|
||||||
|
// Re-register for push notifications, as we want to receive mentions
|
||||||
|
if err := m.reregisterForPushNotifications(); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
err := m.persistence.SaveChat(*chat)
|
err := m.persistence.SaveChat(*chat)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
|
@ -1424,7 +1434,12 @@ func (m *Messenger) DeleteChat(chatID string) error {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
delete(m.allChats, chatID)
|
chat, ok := m.allChats[chatID]
|
||||||
|
|
||||||
|
if ok && chat.Active && chat.Public() {
|
||||||
|
delete(m.allChats, chatID)
|
||||||
|
return m.reregisterForPushNotifications()
|
||||||
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
@ -1490,8 +1505,7 @@ func (m *Messenger) reregisterForPushNotifications() error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
contactIDs, mutedChatIDs := m.addedContactsAndMutedChatIDs()
|
return m.pushNotificationClient.Reregister(m.pushNotificationOptions())
|
||||||
return m.pushNotificationClient.Reregister(contactIDs, mutedChatIDs)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *Messenger) SaveContact(contact *Contact) error {
|
func (m *Messenger) SaveContact(contact *Contact) error {
|
||||||
|
@ -1649,9 +1663,18 @@ func (m *Messenger) dispatchMessage(ctx context.Context, spec common.RawMessage)
|
||||||
case ChatTypePrivateGroupChat:
|
case ChatTypePrivateGroupChat:
|
||||||
logger.Debug("sending group message", zap.String("chatName", chat.Name))
|
logger.Debug("sending group message", zap.String("chatName", chat.Name))
|
||||||
if spec.Recipients == nil {
|
if spec.Recipients == nil {
|
||||||
spec.Recipients, err = chat.MembersAsPublicKeys()
|
// Chat messages are only dispatched to users who joined
|
||||||
if err != nil {
|
if spec.MessageType == protobuf.ApplicationMetadataMessage_CHAT_MESSAGE {
|
||||||
return nil, err
|
spec.Recipients, err = chat.JoinedMembersAsPublicKeys()
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
} else {
|
||||||
|
spec.Recipients, err = chat.MembersAsPublicKeys()
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
hasPairedDevices := m.hasPairedDevices()
|
hasPairedDevices := m.hasPairedDevices()
|
||||||
|
@ -1689,7 +1712,7 @@ func (m *Messenger) dispatchMessage(ctx context.Context, spec common.RawMessage)
|
||||||
}
|
}
|
||||||
|
|
||||||
// SendChatMessage takes a minimal message and sends it based on the corresponding chat
|
// SendChatMessage takes a minimal message and sends it based on the corresponding chat
|
||||||
func (m *Messenger) SendChatMessage(ctx context.Context, message *Message) (*MessengerResponse, error) {
|
func (m *Messenger) SendChatMessage(ctx context.Context, message *common.Message) (*MessengerResponse, error) {
|
||||||
m.mutex.Lock()
|
m.mutex.Lock()
|
||||||
defer m.mutex.Unlock()
|
defer m.mutex.Unlock()
|
||||||
|
|
||||||
|
@ -1758,7 +1781,7 @@ func (m *Messenger) SendChatMessage(ctx context.Context, message *Message) (*Mes
|
||||||
|
|
||||||
id, err := m.dispatchMessage(ctx, common.RawMessage{
|
id, err := m.dispatchMessage(ctx, common.RawMessage{
|
||||||
LocalChatID: chat.ID,
|
LocalChatID: chat.ID,
|
||||||
SendPushNotification: m.featureFlags.PushNotifications && !chat.Public(),
|
SendPushNotification: m.featureFlags.PushNotifications,
|
||||||
Payload: encodedMessage,
|
Payload: encodedMessage,
|
||||||
MessageType: protobuf.ApplicationMetadataMessage_CHAT_MESSAGE,
|
MessageType: protobuf.ApplicationMetadataMessage_CHAT_MESSAGE,
|
||||||
ResendAutomatically: true,
|
ResendAutomatically: true,
|
||||||
|
@ -1778,12 +1801,12 @@ func (m *Messenger) SendChatMessage(ctx context.Context, message *Message) (*Mes
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
err = m.persistence.SaveMessages([]*Message{message})
|
err = m.persistence.SaveMessages([]*common.Message{message})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
response.Messages, err = m.pullMessagesAndResponsesFromDB([]*Message{message})
|
response.Messages, err = m.pullMessagesAndResponsesFromDB([]*common.Message{message})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
@ -2251,10 +2274,17 @@ func (m *Messenger) handleRetrievedMessages(chatWithMessages map[transport.Filte
|
||||||
|
|
||||||
p := msg.ParsedMessage.Interface().(protobuf.SyncInstallationPublicChat)
|
p := msg.ParsedMessage.Interface().(protobuf.SyncInstallationPublicChat)
|
||||||
logger.Debug("Handling SyncInstallationPublicChat", zap.Any("message", p))
|
logger.Debug("Handling SyncInstallationPublicChat", zap.Any("message", p))
|
||||||
err = m.handler.HandleSyncInstallationPublicChat(messageState, p)
|
added := m.handler.HandleSyncInstallationPublicChat(messageState, p)
|
||||||
if err != nil {
|
|
||||||
logger.Warn("failed to handle SyncInstallationPublicChat", zap.Error(err))
|
// We re-register as we want to receive mentions from the newly joined public chat
|
||||||
continue
|
if added {
|
||||||
|
logger.Debug("newly synced public chat, re-registering for push notifications")
|
||||||
|
err := m.reregisterForPushNotifications()
|
||||||
|
if err != nil {
|
||||||
|
|
||||||
|
logger.Warn("could not re-register for push notifications", zap.Error(err))
|
||||||
|
continue
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
case protobuf.RequestAddressForTransaction:
|
case protobuf.RequestAddressForTransaction:
|
||||||
|
@ -2540,7 +2570,7 @@ func (m *Messenger) ConfirmMessagesProcessed(messageIDs [][]byte) error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *Messenger) MessageByID(id string) (*Message, error) {
|
func (m *Messenger) MessageByID(id string) (*common.Message, error) {
|
||||||
return m.persistence.MessageByID(id)
|
return m.persistence.MessageByID(id)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2548,11 +2578,11 @@ func (m *Messenger) MessagesExist(ids []string) (map[string]bool, error) {
|
||||||
return m.persistence.MessagesExist(ids)
|
return m.persistence.MessagesExist(ids)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *Messenger) MessageByChatID(chatID, cursor string, limit int) ([]*Message, string, error) {
|
func (m *Messenger) MessageByChatID(chatID, cursor string, limit int) ([]*common.Message, string, error) {
|
||||||
return m.persistence.MessageByChatID(chatID, cursor, limit)
|
return m.persistence.MessageByChatID(chatID, cursor, limit)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *Messenger) SaveMessages(messages []*Message) error {
|
func (m *Messenger) SaveMessages(messages []*common.Message) error {
|
||||||
return m.persistence.SaveMessages(messages)
|
return m.persistence.SaveMessages(messages)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2733,7 +2763,7 @@ func (m *Messenger) RequestTransaction(ctx context.Context, chatID, value, contr
|
||||||
return nil, errors.New("Need to be a one-to-one chat")
|
return nil, errors.New("Need to be a one-to-one chat")
|
||||||
}
|
}
|
||||||
|
|
||||||
message := &Message{}
|
message := &common.Message{}
|
||||||
err := extendMessageFromChat(message, chat, &m.identity.PublicKey, m.transport)
|
err := extendMessageFromChat(message, chat, &m.identity.PublicKey, m.transport)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
|
@ -2760,12 +2790,12 @@ func (m *Messenger) RequestTransaction(ctx context.Context, chatID, value, contr
|
||||||
ResendAutomatically: true,
|
ResendAutomatically: true,
|
||||||
})
|
})
|
||||||
|
|
||||||
message.CommandParameters = &CommandParameters{
|
message.CommandParameters = &common.CommandParameters{
|
||||||
ID: types.EncodeHex(id),
|
ID: types.EncodeHex(id),
|
||||||
Value: value,
|
Value: value,
|
||||||
Address: address,
|
Address: address,
|
||||||
Contract: contract,
|
Contract: contract,
|
||||||
CommandState: CommandStateRequestTransaction,
|
CommandState: common.CommandStateRequestTransaction,
|
||||||
}
|
}
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -2785,13 +2815,13 @@ func (m *Messenger) RequestTransaction(ctx context.Context, chatID, value, contr
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
err = m.persistence.SaveMessages([]*Message{message})
|
err = m.persistence.SaveMessages([]*common.Message{message})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
response.Chats = []*Chat{chat}
|
response.Chats = []*Chat{chat}
|
||||||
response.Messages = []*Message{message}
|
response.Messages = []*common.Message{message}
|
||||||
return &response, m.saveChat(chat)
|
return &response, m.saveChat(chat)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2810,7 +2840,7 @@ func (m *Messenger) RequestAddressForTransaction(ctx context.Context, chatID, fr
|
||||||
return nil, errors.New("Need to be a one-to-one chat")
|
return nil, errors.New("Need to be a one-to-one chat")
|
||||||
}
|
}
|
||||||
|
|
||||||
message := &Message{}
|
message := &common.Message{}
|
||||||
err := extendMessageFromChat(message, chat, &m.identity.PublicKey, m.transport)
|
err := extendMessageFromChat(message, chat, &m.identity.PublicKey, m.transport)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
|
@ -2836,12 +2866,12 @@ func (m *Messenger) RequestAddressForTransaction(ctx context.Context, chatID, fr
|
||||||
ResendAutomatically: true,
|
ResendAutomatically: true,
|
||||||
})
|
})
|
||||||
|
|
||||||
message.CommandParameters = &CommandParameters{
|
message.CommandParameters = &common.CommandParameters{
|
||||||
ID: types.EncodeHex(id),
|
ID: types.EncodeHex(id),
|
||||||
From: from,
|
From: from,
|
||||||
Value: value,
|
Value: value,
|
||||||
Contract: contract,
|
Contract: contract,
|
||||||
CommandState: CommandStateRequestAddressForTransaction,
|
CommandState: common.CommandStateRequestAddressForTransaction,
|
||||||
}
|
}
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -2861,13 +2891,13 @@ func (m *Messenger) RequestAddressForTransaction(ctx context.Context, chatID, fr
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
err = m.persistence.SaveMessages([]*Message{message})
|
err = m.persistence.SaveMessages([]*common.Message{message})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
response.Chats = []*Chat{chat}
|
response.Chats = []*Chat{chat}
|
||||||
response.Messages = []*Message{message}
|
response.Messages = []*common.Message{message}
|
||||||
return &response, m.saveChat(chat)
|
return &response, m.saveChat(chat)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2902,7 +2932,7 @@ func (m *Messenger) AcceptRequestAddressForTransaction(ctx context.Context, mess
|
||||||
message.WhisperTimestamp = timestamp
|
message.WhisperTimestamp = timestamp
|
||||||
message.Timestamp = timestamp
|
message.Timestamp = timestamp
|
||||||
message.Text = "Request address for transaction accepted"
|
message.Text = "Request address for transaction accepted"
|
||||||
message.OutgoingStatus = OutgoingStatusSending
|
message.OutgoingStatus = common.OutgoingStatusSending
|
||||||
|
|
||||||
// Hide previous message
|
// Hide previous message
|
||||||
previousMessage, err := m.persistence.MessageByCommandID(chatID, messageID)
|
previousMessage, err := m.persistence.MessageByCommandID(chatID, messageID)
|
||||||
|
@ -2944,7 +2974,7 @@ func (m *Messenger) AcceptRequestAddressForTransaction(ctx context.Context, mess
|
||||||
|
|
||||||
message.ID = types.EncodeHex(newMessageID)
|
message.ID = types.EncodeHex(newMessageID)
|
||||||
message.CommandParameters.Address = address
|
message.CommandParameters.Address = address
|
||||||
message.CommandParameters.CommandState = CommandStateRequestAddressForTransactionAccepted
|
message.CommandParameters.CommandState = common.CommandStateRequestAddressForTransactionAccepted
|
||||||
|
|
||||||
err = message.PrepareContent()
|
err = message.PrepareContent()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -2956,13 +2986,13 @@ func (m *Messenger) AcceptRequestAddressForTransaction(ctx context.Context, mess
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
err = m.persistence.SaveMessages([]*Message{message})
|
err = m.persistence.SaveMessages([]*common.Message{message})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
response.Chats = []*Chat{chat}
|
response.Chats = []*Chat{chat}
|
||||||
response.Messages = []*Message{message}
|
response.Messages = []*common.Message{message}
|
||||||
return &response, m.saveChat(chat)
|
return &response, m.saveChat(chat)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2997,7 +3027,7 @@ func (m *Messenger) DeclineRequestTransaction(ctx context.Context, messageID str
|
||||||
message.WhisperTimestamp = timestamp
|
message.WhisperTimestamp = timestamp
|
||||||
message.Timestamp = timestamp
|
message.Timestamp = timestamp
|
||||||
message.Text = "Transaction request declined"
|
message.Text = "Transaction request declined"
|
||||||
message.OutgoingStatus = OutgoingStatusSending
|
message.OutgoingStatus = common.OutgoingStatusSending
|
||||||
message.Replace = messageID
|
message.Replace = messageID
|
||||||
|
|
||||||
err = m.persistence.HideMessage(messageID)
|
err = m.persistence.HideMessage(messageID)
|
||||||
|
@ -3026,7 +3056,7 @@ func (m *Messenger) DeclineRequestTransaction(ctx context.Context, messageID str
|
||||||
}
|
}
|
||||||
|
|
||||||
message.ID = types.EncodeHex(newMessageID)
|
message.ID = types.EncodeHex(newMessageID)
|
||||||
message.CommandParameters.CommandState = CommandStateRequestTransactionDeclined
|
message.CommandParameters.CommandState = common.CommandStateRequestTransactionDeclined
|
||||||
|
|
||||||
err = message.PrepareContent()
|
err = message.PrepareContent()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -3038,13 +3068,13 @@ func (m *Messenger) DeclineRequestTransaction(ctx context.Context, messageID str
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
err = m.persistence.SaveMessages([]*Message{message})
|
err = m.persistence.SaveMessages([]*common.Message{message})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
response.Chats = []*Chat{chat}
|
response.Chats = []*Chat{chat}
|
||||||
response.Messages = []*Message{message}
|
response.Messages = []*common.Message{message}
|
||||||
return &response, m.saveChat(chat)
|
return &response, m.saveChat(chat)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3079,7 +3109,7 @@ func (m *Messenger) DeclineRequestAddressForTransaction(ctx context.Context, mes
|
||||||
message.WhisperTimestamp = timestamp
|
message.WhisperTimestamp = timestamp
|
||||||
message.Timestamp = timestamp
|
message.Timestamp = timestamp
|
||||||
message.Text = "Request address for transaction declined"
|
message.Text = "Request address for transaction declined"
|
||||||
message.OutgoingStatus = OutgoingStatusSending
|
message.OutgoingStatus = common.OutgoingStatusSending
|
||||||
message.Replace = messageID
|
message.Replace = messageID
|
||||||
|
|
||||||
err = m.persistence.HideMessage(messageID)
|
err = m.persistence.HideMessage(messageID)
|
||||||
|
@ -3108,7 +3138,7 @@ func (m *Messenger) DeclineRequestAddressForTransaction(ctx context.Context, mes
|
||||||
}
|
}
|
||||||
|
|
||||||
message.ID = types.EncodeHex(newMessageID)
|
message.ID = types.EncodeHex(newMessageID)
|
||||||
message.CommandParameters.CommandState = CommandStateRequestAddressForTransactionDeclined
|
message.CommandParameters.CommandState = common.CommandStateRequestAddressForTransactionDeclined
|
||||||
|
|
||||||
err = message.PrepareContent()
|
err = message.PrepareContent()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -3120,13 +3150,13 @@ func (m *Messenger) DeclineRequestAddressForTransaction(ctx context.Context, mes
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
err = m.persistence.SaveMessages([]*Message{message})
|
err = m.persistence.SaveMessages([]*common.Message{message})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
response.Chats = []*Chat{chat}
|
response.Chats = []*Chat{chat}
|
||||||
response.Messages = []*Message{message}
|
response.Messages = []*common.Message{message}
|
||||||
return &response, m.saveChat(chat)
|
return &response, m.saveChat(chat)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3161,7 +3191,7 @@ func (m *Messenger) AcceptRequestTransaction(ctx context.Context, transactionHas
|
||||||
message.WhisperTimestamp = timestamp
|
message.WhisperTimestamp = timestamp
|
||||||
message.Timestamp = timestamp
|
message.Timestamp = timestamp
|
||||||
message.Text = transactionSentTxt
|
message.Text = transactionSentTxt
|
||||||
message.OutgoingStatus = OutgoingStatusSending
|
message.OutgoingStatus = common.OutgoingStatusSending
|
||||||
|
|
||||||
// Hide previous message
|
// Hide previous message
|
||||||
previousMessage, err := m.persistence.MessageByCommandID(chatID, messageID)
|
previousMessage, err := m.persistence.MessageByCommandID(chatID, messageID)
|
||||||
|
@ -3207,7 +3237,7 @@ func (m *Messenger) AcceptRequestTransaction(ctx context.Context, transactionHas
|
||||||
message.ID = types.EncodeHex(newMessageID)
|
message.ID = types.EncodeHex(newMessageID)
|
||||||
message.CommandParameters.TransactionHash = transactionHash
|
message.CommandParameters.TransactionHash = transactionHash
|
||||||
message.CommandParameters.Signature = signature
|
message.CommandParameters.Signature = signature
|
||||||
message.CommandParameters.CommandState = CommandStateTransactionSent
|
message.CommandParameters.CommandState = common.CommandStateTransactionSent
|
||||||
|
|
||||||
err = message.PrepareContent()
|
err = message.PrepareContent()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -3219,13 +3249,13 @@ func (m *Messenger) AcceptRequestTransaction(ctx context.Context, transactionHas
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
err = m.persistence.SaveMessages([]*Message{message})
|
err = m.persistence.SaveMessages([]*common.Message{message})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
response.Chats = []*Chat{chat}
|
response.Chats = []*Chat{chat}
|
||||||
response.Messages = []*Message{message}
|
response.Messages = []*common.Message{message}
|
||||||
return &response, m.saveChat(chat)
|
return &response, m.saveChat(chat)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3244,7 +3274,7 @@ func (m *Messenger) SendTransaction(ctx context.Context, chatID, value, contract
|
||||||
return nil, errors.New("Need to be a one-to-one chat")
|
return nil, errors.New("Need to be a one-to-one chat")
|
||||||
}
|
}
|
||||||
|
|
||||||
message := &Message{}
|
message := &common.Message{}
|
||||||
err := extendMessageFromChat(message, chat, &m.identity.PublicKey, m.transport)
|
err := extendMessageFromChat(message, chat, &m.identity.PublicKey, m.transport)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
|
@ -3282,12 +3312,12 @@ func (m *Messenger) SendTransaction(ctx context.Context, chatID, value, contract
|
||||||
}
|
}
|
||||||
|
|
||||||
message.ID = types.EncodeHex(newMessageID)
|
message.ID = types.EncodeHex(newMessageID)
|
||||||
message.CommandParameters = &CommandParameters{
|
message.CommandParameters = &common.CommandParameters{
|
||||||
TransactionHash: transactionHash,
|
TransactionHash: transactionHash,
|
||||||
Value: value,
|
Value: value,
|
||||||
Contract: contract,
|
Contract: contract,
|
||||||
Signature: signature,
|
Signature: signature,
|
||||||
CommandState: CommandStateTransactionSent,
|
CommandState: common.CommandStateTransactionSent,
|
||||||
}
|
}
|
||||||
|
|
||||||
err = message.PrepareContent()
|
err = message.PrepareContent()
|
||||||
|
@ -3300,13 +3330,13 @@ func (m *Messenger) SendTransaction(ctx context.Context, chatID, value, contract
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
err = m.persistence.SaveMessages([]*Message{message})
|
err = m.persistence.SaveMessages([]*common.Message{message})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
response.Chats = []*Chat{chat}
|
response.Chats = []*Chat{chat}
|
||||||
response.Messages = []*Message{message}
|
response.Messages = []*common.Message{message}
|
||||||
return &response, m.saveChat(chat)
|
return &response, m.saveChat(chat)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3335,7 +3365,7 @@ func (m *Messenger) ValidateTransactions(ctx context.Context, addresses []types.
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
for _, validationResult := range responses {
|
for _, validationResult := range responses {
|
||||||
var message *Message
|
var message *common.Message
|
||||||
chatID := contactIDFromPublicKey(validationResult.Transaction.From)
|
chatID := contactIDFromPublicKey(validationResult.Transaction.From)
|
||||||
chat, ok := m.allChats[chatID]
|
chat, ok := m.allChats[chatID]
|
||||||
if !ok {
|
if !ok {
|
||||||
|
@ -3344,7 +3374,7 @@ func (m *Messenger) ValidateTransactions(ctx context.Context, addresses []types.
|
||||||
if validationResult.Message != nil {
|
if validationResult.Message != nil {
|
||||||
message = validationResult.Message
|
message = validationResult.Message
|
||||||
} else {
|
} else {
|
||||||
message = &Message{}
|
message = &common.Message{}
|
||||||
err := extendMessageFromChat(message, chat, &m.identity.PublicKey, m.transport)
|
err := extendMessageFromChat(message, chat, &m.identity.PublicKey, m.transport)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
|
@ -3365,7 +3395,7 @@ func (m *Messenger) ValidateTransactions(ctx context.Context, addresses []types.
|
||||||
|
|
||||||
message.ID = validationResult.Transaction.MessageID
|
message.ID = validationResult.Transaction.MessageID
|
||||||
if message.CommandParameters == nil {
|
if message.CommandParameters == nil {
|
||||||
message.CommandParameters = &CommandParameters{}
|
message.CommandParameters = &common.CommandParameters{}
|
||||||
} else {
|
} else {
|
||||||
message.CommandParameters = validationResult.Message.CommandParameters
|
message.CommandParameters = validationResult.Message.CommandParameters
|
||||||
}
|
}
|
||||||
|
@ -3373,7 +3403,7 @@ func (m *Messenger) ValidateTransactions(ctx context.Context, addresses []types.
|
||||||
message.CommandParameters.Value = validationResult.Value
|
message.CommandParameters.Value = validationResult.Value
|
||||||
message.CommandParameters.Contract = validationResult.Contract
|
message.CommandParameters.Contract = validationResult.Contract
|
||||||
message.CommandParameters.Address = validationResult.Address
|
message.CommandParameters.Address = validationResult.Address
|
||||||
message.CommandParameters.CommandState = CommandStateTransactionSent
|
message.CommandParameters.CommandState = common.CommandStateTransactionSent
|
||||||
message.CommandParameters.TransactionHash = validationResult.Transaction.TransactionHash
|
message.CommandParameters.TransactionHash = validationResult.Transaction.TransactionHash
|
||||||
|
|
||||||
err = message.PrepareContent()
|
err = message.PrepareContent()
|
||||||
|
@ -3422,7 +3452,7 @@ func (m *Messenger) ValidateTransactions(ctx context.Context, addresses []types.
|
||||||
|
|
||||||
// pullMessagesAndResponsesFromDB pulls all the messages and the one that have
|
// pullMessagesAndResponsesFromDB pulls all the messages and the one that have
|
||||||
// been replied to from the database
|
// been replied to from the database
|
||||||
func (m *Messenger) pullMessagesAndResponsesFromDB(messages []*Message) ([]*Message, error) {
|
func (m *Messenger) pullMessagesAndResponsesFromDB(messages []*common.Message) ([]*common.Message, error) {
|
||||||
var messageIDs []string
|
var messageIDs []string
|
||||||
for _, message := range messages {
|
for _, message := range messages {
|
||||||
messageIDs = append(messageIDs, message.ID)
|
messageIDs = append(messageIDs, message.ID)
|
||||||
|
@ -3488,12 +3518,13 @@ func (m *Messenger) EnableSendingPushNotifications() error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *Messenger) addedContactsAndMutedChatIDs() ([]*ecdsa.PublicKey, []string) {
|
func (m *Messenger) pushNotificationOptions() *pushnotificationclient.RegistrationOptions {
|
||||||
var contactIDs []*ecdsa.PublicKey
|
var contactIDs []*ecdsa.PublicKey
|
||||||
var mutedChatIDs []string
|
var mutedChatIDs []string
|
||||||
|
var publicChatIDs []string
|
||||||
|
|
||||||
for _, contact := range m.allContacts {
|
for _, contact := range m.allContacts {
|
||||||
if contact.IsAdded() {
|
if contact.IsAdded() && !contact.IsBlocked() {
|
||||||
pk, err := contact.PublicKey()
|
pk, err := contact.PublicKey()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
m.logger.Warn("could not parse contact public key")
|
m.logger.Warn("could not parse contact public key")
|
||||||
|
@ -3508,9 +3539,16 @@ func (m *Messenger) addedContactsAndMutedChatIDs() ([]*ecdsa.PublicKey, []string
|
||||||
if chat.Muted {
|
if chat.Muted {
|
||||||
mutedChatIDs = append(mutedChatIDs, chat.ID)
|
mutedChatIDs = append(mutedChatIDs, chat.ID)
|
||||||
}
|
}
|
||||||
|
if chat.Active && chat.Public() {
|
||||||
|
publicChatIDs = append(publicChatIDs, chat.ID)
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
return contactIDs, mutedChatIDs
|
return &pushnotificationclient.RegistrationOptions{
|
||||||
|
ContactIDs: contactIDs,
|
||||||
|
MutedChatIDs: mutedChatIDs,
|
||||||
|
PublicChatIDs: publicChatIDs,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// RegisterForPushNotification register deviceToken with any push notification server enabled
|
// RegisterForPushNotification register deviceToken with any push notification server enabled
|
||||||
|
@ -3521,8 +3559,7 @@ func (m *Messenger) RegisterForPushNotifications(ctx context.Context, deviceToke
|
||||||
m.mutex.Lock()
|
m.mutex.Lock()
|
||||||
defer m.mutex.Unlock()
|
defer m.mutex.Unlock()
|
||||||
|
|
||||||
contactIDs, mutedChatIDs := m.addedContactsAndMutedChatIDs()
|
err := m.pushNotificationClient.Register(deviceToken, apnTopic, tokenType, m.pushNotificationOptions())
|
||||||
err := m.pushNotificationClient.Register(deviceToken, apnTopic, tokenType, contactIDs, mutedChatIDs)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
m.logger.Error("failed to register for push notifications", zap.Error(err))
|
m.logger.Error("failed to register for push notifications", zap.Error(err))
|
||||||
return err
|
return err
|
||||||
|
@ -3546,8 +3583,7 @@ func (m *Messenger) EnablePushNotificationsFromContactsOnly() error {
|
||||||
m.mutex.Lock()
|
m.mutex.Lock()
|
||||||
defer m.mutex.Unlock()
|
defer m.mutex.Unlock()
|
||||||
|
|
||||||
contactIDs, mutedChatIDs := m.addedContactsAndMutedChatIDs()
|
return m.pushNotificationClient.EnablePushNotificationsFromContactsOnly(m.pushNotificationOptions())
|
||||||
return m.pushNotificationClient.EnablePushNotificationsFromContactsOnly(contactIDs, mutedChatIDs)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// DisablePushNotificationsFromContactsOnly is used to indicate that we want to received push notifications from anyone
|
// DisablePushNotificationsFromContactsOnly is used to indicate that we want to received push notifications from anyone
|
||||||
|
@ -3558,8 +3594,29 @@ func (m *Messenger) DisablePushNotificationsFromContactsOnly() error {
|
||||||
m.mutex.Lock()
|
m.mutex.Lock()
|
||||||
defer m.mutex.Unlock()
|
defer m.mutex.Unlock()
|
||||||
|
|
||||||
contactIDs, mutedChatIDs := m.addedContactsAndMutedChatIDs()
|
return m.pushNotificationClient.DisablePushNotificationsFromContactsOnly(m.pushNotificationOptions())
|
||||||
return m.pushNotificationClient.DisablePushNotificationsFromContactsOnly(contactIDs, mutedChatIDs)
|
}
|
||||||
|
|
||||||
|
// EnablePushNotificationsBlockMentions is used to indicate that we dont want to received push notifications for mentions
|
||||||
|
func (m *Messenger) EnablePushNotificationsBlockMentions() error {
|
||||||
|
if m.pushNotificationClient == nil {
|
||||||
|
return errors.New("no push notification client")
|
||||||
|
}
|
||||||
|
m.mutex.Lock()
|
||||||
|
defer m.mutex.Unlock()
|
||||||
|
|
||||||
|
return m.pushNotificationClient.EnablePushNotificationsBlockMentions(m.pushNotificationOptions())
|
||||||
|
}
|
||||||
|
|
||||||
|
// DisablePushNotificationsBlockMentions is used to indicate that we want to received push notifications for mentions
|
||||||
|
func (m *Messenger) DisablePushNotificationsBlockMentions() error {
|
||||||
|
if m.pushNotificationClient == nil {
|
||||||
|
return errors.New("no push notification client")
|
||||||
|
}
|
||||||
|
m.mutex.Lock()
|
||||||
|
defer m.mutex.Unlock()
|
||||||
|
|
||||||
|
return m.pushNotificationClient.DisablePushNotificationsBlockMentions(m.pushNotificationOptions())
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetPushNotificationsServers returns the servers used for push notifications
|
// GetPushNotificationsServers returns the servers used for push notifications
|
||||||
|
|
|
@ -24,6 +24,7 @@ import (
|
||||||
"github.com/status-im/status-go/eth-node/crypto"
|
"github.com/status-im/status-go/eth-node/crypto"
|
||||||
"github.com/status-im/status-go/eth-node/types"
|
"github.com/status-im/status-go/eth-node/types"
|
||||||
enstypes "github.com/status-im/status-go/eth-node/types/ens"
|
enstypes "github.com/status-im/status-go/eth-node/types/ens"
|
||||||
|
"github.com/status-im/status-go/protocol/common"
|
||||||
"github.com/status-im/status-go/protocol/protobuf"
|
"github.com/status-im/status-go/protocol/protobuf"
|
||||||
"github.com/status-im/status-go/protocol/tt"
|
"github.com/status-im/status-go/protocol/tt"
|
||||||
v1protocol "github.com/status-im/status-go/protocol/v1"
|
v1protocol "github.com/status-im/status-go/protocol/v1"
|
||||||
|
@ -288,9 +289,9 @@ func (s *MessengerSuite) TestInit() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func buildTestMessage(chat Chat) *Message {
|
func buildTestMessage(chat Chat) *common.Message {
|
||||||
clock, timestamp := chat.NextClockAndTimestamp(&testTimeSource{})
|
clock, timestamp := chat.NextClockAndTimestamp(&testTimeSource{})
|
||||||
message := &Message{}
|
message := &common.Message{}
|
||||||
message.Text = "text-input-message"
|
message.Text = "text-input-message"
|
||||||
message.ChatId = chat.ID
|
message.ChatId = chat.ID
|
||||||
message.Clock = clock
|
message.Clock = clock
|
||||||
|
@ -322,7 +323,7 @@ func (s *MessengerSuite) TestMarkMessagesSeen() {
|
||||||
inputMessage2.ID = "2"
|
inputMessage2.ID = "2"
|
||||||
inputMessage2.Seen = false
|
inputMessage2.Seen = false
|
||||||
|
|
||||||
err = s.m.SaveMessages([]*Message{inputMessage1, inputMessage2})
|
err = s.m.SaveMessages([]*common.Message{inputMessage1, inputMessage2})
|
||||||
s.Require().NoError(err)
|
s.Require().NoError(err)
|
||||||
|
|
||||||
count, err := s.m.MarkMessagesSeen(chat.ID, []string{inputMessage1.ID})
|
count, err := s.m.MarkMessagesSeen(chat.ID, []string{inputMessage1.ID})
|
||||||
|
@ -346,7 +347,7 @@ func (s *MessengerSuite) TestMarkAllRead() {
|
||||||
inputMessage2.ID = "2"
|
inputMessage2.ID = "2"
|
||||||
inputMessage2.Seen = false
|
inputMessage2.Seen = false
|
||||||
|
|
||||||
err = s.m.SaveMessages([]*Message{inputMessage1, inputMessage2})
|
err = s.m.SaveMessages([]*common.Message{inputMessage1, inputMessage2})
|
||||||
s.Require().NoError(err)
|
s.Require().NoError(err)
|
||||||
|
|
||||||
err = s.m.MarkAllRead(chat.ID)
|
err = s.m.MarkAllRead(chat.ID)
|
||||||
|
@ -374,7 +375,7 @@ func (s *MessengerSuite) TestSendPublic() {
|
||||||
s.Require().NotEqual(uint64(0), chat.Timestamp, "it sets the timestamp")
|
s.Require().NotEqual(uint64(0), chat.Timestamp, "it sets the timestamp")
|
||||||
s.Require().Equal("0x"+hex.EncodeToString(crypto.FromECDSAPub(&s.privateKey.PublicKey)), outputMessage.From, "it sets the From field")
|
s.Require().Equal("0x"+hex.EncodeToString(crypto.FromECDSAPub(&s.privateKey.PublicKey)), outputMessage.From, "it sets the From field")
|
||||||
s.Require().True(outputMessage.Seen, "it marks the message as seen")
|
s.Require().True(outputMessage.Seen, "it marks the message as seen")
|
||||||
s.Require().Equal(outputMessage.OutgoingStatus, OutgoingStatusSending, "it marks the message as sending")
|
s.Require().Equal(outputMessage.OutgoingStatus, common.OutgoingStatusSending, "it marks the message as sending")
|
||||||
s.Require().NotEmpty(outputMessage.ID, "it sets the ID field")
|
s.Require().NotEmpty(outputMessage.ID, "it sets the ID field")
|
||||||
s.Require().Equal(protobuf.MessageType_PUBLIC_GROUP, outputMessage.MessageType)
|
s.Require().Equal(protobuf.MessageType_PUBLIC_GROUP, outputMessage.MessageType)
|
||||||
|
|
||||||
|
@ -389,7 +390,7 @@ func (s *MessengerSuite) TestSendPrivateOneToOne() {
|
||||||
pkString := hex.EncodeToString(crypto.FromECDSAPub(&recipientKey.PublicKey))
|
pkString := hex.EncodeToString(crypto.FromECDSAPub(&recipientKey.PublicKey))
|
||||||
chat := CreateOneToOneChat(pkString, &recipientKey.PublicKey, s.m.transport)
|
chat := CreateOneToOneChat(pkString, &recipientKey.PublicKey, s.m.transport)
|
||||||
|
|
||||||
inputMessage := &Message{}
|
inputMessage := &common.Message{}
|
||||||
inputMessage.ChatId = chat.ID
|
inputMessage.ChatId = chat.ID
|
||||||
chat.LastClockValue = uint64(100000000000000)
|
chat.LastClockValue = uint64(100000000000000)
|
||||||
err = s.m.SaveChat(&chat)
|
err = s.m.SaveChat(&chat)
|
||||||
|
@ -405,7 +406,7 @@ func (s *MessengerSuite) TestSendPrivateOneToOne() {
|
||||||
s.Require().NotEqual(uint64(0), chat.Timestamp, "it sets the timestamp")
|
s.Require().NotEqual(uint64(0), chat.Timestamp, "it sets the timestamp")
|
||||||
s.Require().Equal("0x"+hex.EncodeToString(crypto.FromECDSAPub(&s.privateKey.PublicKey)), outputMessage.From, "it sets the From field")
|
s.Require().Equal("0x"+hex.EncodeToString(crypto.FromECDSAPub(&s.privateKey.PublicKey)), outputMessage.From, "it sets the From field")
|
||||||
s.Require().True(outputMessage.Seen, "it marks the message as seen")
|
s.Require().True(outputMessage.Seen, "it marks the message as seen")
|
||||||
s.Require().Equal(outputMessage.OutgoingStatus, OutgoingStatusSending, "it marks the message as sending")
|
s.Require().Equal(outputMessage.OutgoingStatus, common.OutgoingStatusSending, "it marks the message as sending")
|
||||||
s.Require().NotEmpty(outputMessage.ID, "it sets the ID field")
|
s.Require().NotEmpty(outputMessage.ID, "it sets the ID field")
|
||||||
s.Require().Equal(protobuf.MessageType_ONE_TO_ONE, outputMessage.MessageType)
|
s.Require().Equal(protobuf.MessageType_ONE_TO_ONE, outputMessage.MessageType)
|
||||||
}
|
}
|
||||||
|
@ -422,13 +423,13 @@ func (s *MessengerSuite) TestSendPrivateGroup() {
|
||||||
_, err = s.m.AddMembersToGroupChat(context.Background(), chat.ID, members)
|
_, err = s.m.AddMembersToGroupChat(context.Background(), chat.ID, members)
|
||||||
s.NoError(err)
|
s.NoError(err)
|
||||||
|
|
||||||
inputMessage := &Message{}
|
inputMessage := &common.Message{}
|
||||||
inputMessage.ChatId = chat.ID
|
inputMessage.ChatId = chat.ID
|
||||||
chat.LastClockValue = uint64(100000000000000)
|
chat.LastClockValue = uint64(100000000000000)
|
||||||
err = s.m.SaveChat(chat)
|
err = s.m.SaveChat(chat)
|
||||||
s.NoError(err)
|
s.NoError(err)
|
||||||
response, err = s.m.SendChatMessage(context.Background(), inputMessage)
|
response, err = s.m.SendChatMessage(context.Background(), inputMessage)
|
||||||
s.NoError(err)
|
s.Require().NoError(err)
|
||||||
s.Require().Equal(1, len(response.Messages), "it returns the message")
|
s.Require().Equal(1, len(response.Messages), "it returns the message")
|
||||||
outputMessage := response.Messages[0]
|
outputMessage := response.Messages[0]
|
||||||
|
|
||||||
|
@ -438,7 +439,7 @@ func (s *MessengerSuite) TestSendPrivateGroup() {
|
||||||
s.Require().NotEqual(uint64(0), chat.Timestamp, "it sets the timestamp")
|
s.Require().NotEqual(uint64(0), chat.Timestamp, "it sets the timestamp")
|
||||||
s.Require().Equal("0x"+hex.EncodeToString(crypto.FromECDSAPub(&s.privateKey.PublicKey)), outputMessage.From, "it sets the From field")
|
s.Require().Equal("0x"+hex.EncodeToString(crypto.FromECDSAPub(&s.privateKey.PublicKey)), outputMessage.From, "it sets the From field")
|
||||||
s.Require().True(outputMessage.Seen, "it marks the message as seen")
|
s.Require().True(outputMessage.Seen, "it marks the message as seen")
|
||||||
s.Require().Equal(outputMessage.OutgoingStatus, OutgoingStatusSending, "it marks the message as sending")
|
s.Require().Equal(outputMessage.OutgoingStatus, common.OutgoingStatusSending, "it marks the message as sending")
|
||||||
s.Require().NotEmpty(outputMessage.ID, "it sets the ID field")
|
s.Require().NotEmpty(outputMessage.ID, "it sets the ID field")
|
||||||
s.Require().Equal(protobuf.MessageType_PRIVATE_GROUP, outputMessage.MessageType)
|
s.Require().Equal(protobuf.MessageType_PRIVATE_GROUP, outputMessage.MessageType)
|
||||||
}
|
}
|
||||||
|
@ -450,7 +451,7 @@ func (s *MessengerSuite) TestSendPrivateEmptyGroup() {
|
||||||
|
|
||||||
chat := response.Chats[0]
|
chat := response.Chats[0]
|
||||||
|
|
||||||
inputMessage := &Message{}
|
inputMessage := &common.Message{}
|
||||||
inputMessage.ChatId = chat.ID
|
inputMessage.ChatId = chat.ID
|
||||||
chat.LastClockValue = uint64(100000000000000)
|
chat.LastClockValue = uint64(100000000000000)
|
||||||
err = s.m.SaveChat(chat)
|
err = s.m.SaveChat(chat)
|
||||||
|
@ -466,7 +467,7 @@ func (s *MessengerSuite) TestSendPrivateEmptyGroup() {
|
||||||
s.Require().NotEqual(uint64(0), chat.Timestamp, "it sets the timestamp")
|
s.Require().NotEqual(uint64(0), chat.Timestamp, "it sets the timestamp")
|
||||||
s.Require().Equal("0x"+hex.EncodeToString(crypto.FromECDSAPub(&s.privateKey.PublicKey)), outputMessage.From, "it sets the From field")
|
s.Require().Equal("0x"+hex.EncodeToString(crypto.FromECDSAPub(&s.privateKey.PublicKey)), outputMessage.From, "it sets the From field")
|
||||||
s.Require().True(outputMessage.Seen, "it marks the message as seen")
|
s.Require().True(outputMessage.Seen, "it marks the message as seen")
|
||||||
s.Require().Equal(outputMessage.OutgoingStatus, OutgoingStatusSending, "it marks the message as sending")
|
s.Require().Equal(outputMessage.OutgoingStatus, common.OutgoingStatusSending, "it marks the message as sending")
|
||||||
s.Require().NotEmpty(outputMessage.ID, "it sets the ID field")
|
s.Require().NotEmpty(outputMessage.ID, "it sets the ID field")
|
||||||
s.Require().Equal(protobuf.MessageType_PRIVATE_GROUP, outputMessage.MessageType)
|
s.Require().Equal(protobuf.MessageType_PRIVATE_GROUP, outputMessage.MessageType)
|
||||||
}
|
}
|
||||||
|
@ -962,7 +963,7 @@ func (s *MessengerSuite) TestChatPersistencePublic() {
|
||||||
LastClockValue: 20,
|
LastClockValue: 20,
|
||||||
DeletedAtClockValue: 30,
|
DeletedAtClockValue: 30,
|
||||||
UnviewedMessagesCount: 40,
|
UnviewedMessagesCount: 40,
|
||||||
LastMessage: &Message{},
|
LastMessage: &common.Message{},
|
||||||
}
|
}
|
||||||
|
|
||||||
s.Require().NoError(s.m.SaveChat(&chat))
|
s.Require().NoError(s.m.SaveChat(&chat))
|
||||||
|
@ -987,7 +988,7 @@ func (s *MessengerSuite) TestDeleteChat() {
|
||||||
LastClockValue: 20,
|
LastClockValue: 20,
|
||||||
DeletedAtClockValue: 30,
|
DeletedAtClockValue: 30,
|
||||||
UnviewedMessagesCount: 40,
|
UnviewedMessagesCount: 40,
|
||||||
LastMessage: &Message{},
|
LastMessage: &common.Message{},
|
||||||
}
|
}
|
||||||
|
|
||||||
s.Require().NoError(s.m.SaveChat(&chat))
|
s.Require().NoError(s.m.SaveChat(&chat))
|
||||||
|
@ -1010,7 +1011,7 @@ func (s *MessengerSuite) TestChatPersistenceUpdate() {
|
||||||
LastClockValue: 20,
|
LastClockValue: 20,
|
||||||
DeletedAtClockValue: 30,
|
DeletedAtClockValue: 30,
|
||||||
UnviewedMessagesCount: 40,
|
UnviewedMessagesCount: 40,
|
||||||
LastMessage: &Message{},
|
LastMessage: &common.Message{},
|
||||||
}
|
}
|
||||||
|
|
||||||
s.Require().NoError(s.m.SaveChat(&chat))
|
s.Require().NoError(s.m.SaveChat(&chat))
|
||||||
|
@ -1044,7 +1045,7 @@ func (s *MessengerSuite) TestChatPersistenceOneToOne() {
|
||||||
LastClockValue: 20,
|
LastClockValue: 20,
|
||||||
DeletedAtClockValue: 30,
|
DeletedAtClockValue: 30,
|
||||||
UnviewedMessagesCount: 40,
|
UnviewedMessagesCount: 40,
|
||||||
LastMessage: &Message{},
|
LastMessage: &common.Message{},
|
||||||
}
|
}
|
||||||
contact := Contact{
|
contact := Contact{
|
||||||
ID: testPK,
|
ID: testPK,
|
||||||
|
@ -1133,7 +1134,7 @@ func (s *MessengerSuite) TestChatPersistencePrivateGroupChat() {
|
||||||
LastClockValue: 20,
|
LastClockValue: 20,
|
||||||
DeletedAtClockValue: 30,
|
DeletedAtClockValue: 30,
|
||||||
UnviewedMessagesCount: 40,
|
UnviewedMessagesCount: 40,
|
||||||
LastMessage: &Message{},
|
LastMessage: &common.Message{},
|
||||||
}
|
}
|
||||||
s.Require().NoError(s.m.SaveChat(&chat))
|
s.Require().NoError(s.m.SaveChat(&chat))
|
||||||
savedChats := s.m.Chats()
|
savedChats := s.m.Chats()
|
||||||
|
@ -1211,7 +1212,7 @@ func (s *MessengerSuite) TestBlockContact() {
|
||||||
|
|
||||||
contact.Name = "blocked"
|
contact.Name = "blocked"
|
||||||
|
|
||||||
messages := []*Message{
|
messages := []*common.Message{
|
||||||
{
|
{
|
||||||
ID: "test-1",
|
ID: "test-1",
|
||||||
LocalChatID: chat2.ID,
|
LocalChatID: chat2.ID,
|
||||||
|
@ -1479,7 +1480,7 @@ func (s *MessengerSuite) TestDeclineRequestAddressForTransaction() {
|
||||||
s.Require().Equal(value, senderMessage.CommandParameters.Value)
|
s.Require().Equal(value, senderMessage.CommandParameters.Value)
|
||||||
s.Require().Equal(contract, senderMessage.CommandParameters.Contract)
|
s.Require().Equal(contract, senderMessage.CommandParameters.Contract)
|
||||||
s.Require().Equal(initialCommandID, senderMessage.CommandParameters.ID)
|
s.Require().Equal(initialCommandID, senderMessage.CommandParameters.ID)
|
||||||
s.Require().Equal(CommandStateRequestAddressForTransaction, senderMessage.CommandParameters.CommandState)
|
s.Require().Equal(common.CommandStateRequestAddressForTransaction, senderMessage.CommandParameters.CommandState)
|
||||||
|
|
||||||
// Wait for the message to reach its destination
|
// Wait for the message to reach its destination
|
||||||
response, err = WaitOnMessengerResponse(
|
response, err = WaitOnMessengerResponse(
|
||||||
|
@ -1500,7 +1501,7 @@ func (s *MessengerSuite) TestDeclineRequestAddressForTransaction() {
|
||||||
s.Require().Equal(value, receiverMessage.CommandParameters.Value)
|
s.Require().Equal(value, receiverMessage.CommandParameters.Value)
|
||||||
s.Require().Equal(contract, receiverMessage.CommandParameters.Contract)
|
s.Require().Equal(contract, receiverMessage.CommandParameters.Contract)
|
||||||
s.Require().Equal(initialCommandID, receiverMessage.CommandParameters.ID)
|
s.Require().Equal(initialCommandID, receiverMessage.CommandParameters.ID)
|
||||||
s.Require().Equal(CommandStateRequestAddressForTransaction, receiverMessage.CommandParameters.CommandState)
|
s.Require().Equal(common.CommandStateRequestAddressForTransaction, receiverMessage.CommandParameters.CommandState)
|
||||||
|
|
||||||
// We decline the request
|
// We decline the request
|
||||||
response, err = theirMessenger.DeclineRequestAddressForTransaction(context.Background(), receiverMessage.ID)
|
response, err = theirMessenger.DeclineRequestAddressForTransaction(context.Background(), receiverMessage.ID)
|
||||||
|
@ -1514,7 +1515,7 @@ func (s *MessengerSuite) TestDeclineRequestAddressForTransaction() {
|
||||||
s.Require().NotNil(senderMessage.CommandParameters)
|
s.Require().NotNil(senderMessage.CommandParameters)
|
||||||
s.Require().Equal(value, senderMessage.CommandParameters.Value)
|
s.Require().Equal(value, senderMessage.CommandParameters.Value)
|
||||||
s.Require().Equal(contract, senderMessage.CommandParameters.Contract)
|
s.Require().Equal(contract, senderMessage.CommandParameters.Contract)
|
||||||
s.Require().Equal(CommandStateRequestAddressForTransactionDeclined, senderMessage.CommandParameters.CommandState)
|
s.Require().Equal(common.CommandStateRequestAddressForTransactionDeclined, senderMessage.CommandParameters.CommandState)
|
||||||
s.Require().Equal(initialCommandID, senderMessage.CommandParameters.ID)
|
s.Require().Equal(initialCommandID, senderMessage.CommandParameters.ID)
|
||||||
s.Require().Equal(receiverMessage.ID, senderMessage.Replace)
|
s.Require().Equal(receiverMessage.ID, senderMessage.Replace)
|
||||||
|
|
||||||
|
@ -1535,7 +1536,7 @@ func (s *MessengerSuite) TestDeclineRequestAddressForTransaction() {
|
||||||
s.Require().NotNil(receiverMessage.CommandParameters)
|
s.Require().NotNil(receiverMessage.CommandParameters)
|
||||||
s.Require().Equal(value, receiverMessage.CommandParameters.Value)
|
s.Require().Equal(value, receiverMessage.CommandParameters.Value)
|
||||||
s.Require().Equal(contract, receiverMessage.CommandParameters.Contract)
|
s.Require().Equal(contract, receiverMessage.CommandParameters.Contract)
|
||||||
s.Require().Equal(CommandStateRequestAddressForTransactionDeclined, receiverMessage.CommandParameters.CommandState)
|
s.Require().Equal(common.CommandStateRequestAddressForTransactionDeclined, receiverMessage.CommandParameters.CommandState)
|
||||||
s.Require().Equal(initialCommandID, receiverMessage.CommandParameters.ID)
|
s.Require().Equal(initialCommandID, receiverMessage.CommandParameters.ID)
|
||||||
s.Require().Equal(initialCommandID, receiverMessage.Replace)
|
s.Require().Equal(initialCommandID, receiverMessage.Replace)
|
||||||
s.Require().NoError(theirMessenger.Shutdown())
|
s.Require().NoError(theirMessenger.Shutdown())
|
||||||
|
@ -1574,7 +1575,7 @@ func (s *MessengerSuite) TestSendEthTransaction() {
|
||||||
s.Require().Equal(contract, senderMessage.CommandParameters.Contract)
|
s.Require().Equal(contract, senderMessage.CommandParameters.Contract)
|
||||||
s.Require().Equal(value, senderMessage.CommandParameters.Value)
|
s.Require().Equal(value, senderMessage.CommandParameters.Value)
|
||||||
s.Require().Equal(signature, senderMessage.CommandParameters.Signature)
|
s.Require().Equal(signature, senderMessage.CommandParameters.Signature)
|
||||||
s.Require().Equal(CommandStateTransactionSent, senderMessage.CommandParameters.CommandState)
|
s.Require().Equal(common.CommandStateTransactionSent, senderMessage.CommandParameters.CommandState)
|
||||||
s.Require().NotEmpty(senderMessage.ID)
|
s.Require().NotEmpty(senderMessage.ID)
|
||||||
s.Require().Equal("", senderMessage.Replace)
|
s.Require().Equal("", senderMessage.Replace)
|
||||||
|
|
||||||
|
@ -1638,7 +1639,7 @@ func (s *MessengerSuite) TestSendEthTransaction() {
|
||||||
s.Require().Equal(transactionHash, receiverMessage.CommandParameters.TransactionHash)
|
s.Require().Equal(transactionHash, receiverMessage.CommandParameters.TransactionHash)
|
||||||
s.Require().Equal(receiverAddressString, receiverMessage.CommandParameters.Address)
|
s.Require().Equal(receiverAddressString, receiverMessage.CommandParameters.Address)
|
||||||
s.Require().Equal("", receiverMessage.CommandParameters.ID)
|
s.Require().Equal("", receiverMessage.CommandParameters.ID)
|
||||||
s.Require().Equal(CommandStateTransactionSent, receiverMessage.CommandParameters.CommandState)
|
s.Require().Equal(common.CommandStateTransactionSent, receiverMessage.CommandParameters.CommandState)
|
||||||
s.Require().Equal(senderMessage.ID, receiverMessage.ID)
|
s.Require().Equal(senderMessage.ID, receiverMessage.ID)
|
||||||
s.Require().Equal("", receiverMessage.Replace)
|
s.Require().Equal("", receiverMessage.Replace)
|
||||||
s.Require().NoError(theirMessenger.Shutdown())
|
s.Require().NoError(theirMessenger.Shutdown())
|
||||||
|
@ -1677,7 +1678,7 @@ func (s *MessengerSuite) TestSendTokenTransaction() {
|
||||||
s.Require().Equal(value, senderMessage.CommandParameters.Value)
|
s.Require().Equal(value, senderMessage.CommandParameters.Value)
|
||||||
s.Require().Equal(contract, senderMessage.CommandParameters.Contract)
|
s.Require().Equal(contract, senderMessage.CommandParameters.Contract)
|
||||||
s.Require().Equal(signature, senderMessage.CommandParameters.Signature)
|
s.Require().Equal(signature, senderMessage.CommandParameters.Signature)
|
||||||
s.Require().Equal(CommandStateTransactionSent, senderMessage.CommandParameters.CommandState)
|
s.Require().Equal(common.CommandStateTransactionSent, senderMessage.CommandParameters.CommandState)
|
||||||
s.Require().NotEmpty(senderMessage.ID)
|
s.Require().NotEmpty(senderMessage.ID)
|
||||||
|
|
||||||
var transactions []*TransactionToValidate
|
var transactions []*TransactionToValidate
|
||||||
|
@ -1741,7 +1742,7 @@ func (s *MessengerSuite) TestSendTokenTransaction() {
|
||||||
s.Require().Equal(transactionHash, receiverMessage.CommandParameters.TransactionHash)
|
s.Require().Equal(transactionHash, receiverMessage.CommandParameters.TransactionHash)
|
||||||
s.Require().Equal(receiverAddressString, receiverMessage.CommandParameters.Address)
|
s.Require().Equal(receiverAddressString, receiverMessage.CommandParameters.Address)
|
||||||
s.Require().Equal("", receiverMessage.CommandParameters.ID)
|
s.Require().Equal("", receiverMessage.CommandParameters.ID)
|
||||||
s.Require().Equal(CommandStateTransactionSent, receiverMessage.CommandParameters.CommandState)
|
s.Require().Equal(common.CommandStateTransactionSent, receiverMessage.CommandParameters.CommandState)
|
||||||
s.Require().Equal(senderMessage.ID, receiverMessage.ID)
|
s.Require().Equal(senderMessage.ID, receiverMessage.ID)
|
||||||
s.Require().Equal(senderMessage.Replace, senderMessage.Replace)
|
s.Require().Equal(senderMessage.Replace, senderMessage.Replace)
|
||||||
s.Require().NoError(theirMessenger.Shutdown())
|
s.Require().NoError(theirMessenger.Shutdown())
|
||||||
|
@ -1775,7 +1776,7 @@ func (s *MessengerSuite) TestAcceptRequestAddressForTransaction() {
|
||||||
s.Require().Equal(value, senderMessage.CommandParameters.Value)
|
s.Require().Equal(value, senderMessage.CommandParameters.Value)
|
||||||
s.Require().Equal(contract, senderMessage.CommandParameters.Contract)
|
s.Require().Equal(contract, senderMessage.CommandParameters.Contract)
|
||||||
s.Require().Equal(initialCommandID, senderMessage.CommandParameters.ID)
|
s.Require().Equal(initialCommandID, senderMessage.CommandParameters.ID)
|
||||||
s.Require().Equal(CommandStateRequestAddressForTransaction, senderMessage.CommandParameters.CommandState)
|
s.Require().Equal(common.CommandStateRequestAddressForTransaction, senderMessage.CommandParameters.CommandState)
|
||||||
|
|
||||||
// Wait for the message to reach its destination
|
// Wait for the message to reach its destination
|
||||||
response, err = WaitOnMessengerResponse(
|
response, err = WaitOnMessengerResponse(
|
||||||
|
@ -1796,7 +1797,7 @@ func (s *MessengerSuite) TestAcceptRequestAddressForTransaction() {
|
||||||
s.Require().Equal(value, receiverMessage.CommandParameters.Value)
|
s.Require().Equal(value, receiverMessage.CommandParameters.Value)
|
||||||
s.Require().Equal(contract, receiverMessage.CommandParameters.Contract)
|
s.Require().Equal(contract, receiverMessage.CommandParameters.Contract)
|
||||||
s.Require().Equal(initialCommandID, receiverMessage.CommandParameters.ID)
|
s.Require().Equal(initialCommandID, receiverMessage.CommandParameters.ID)
|
||||||
s.Require().Equal(CommandStateRequestAddressForTransaction, receiverMessage.CommandParameters.CommandState)
|
s.Require().Equal(common.CommandStateRequestAddressForTransaction, receiverMessage.CommandParameters.CommandState)
|
||||||
|
|
||||||
// We accept the request
|
// We accept the request
|
||||||
response, err = theirMessenger.AcceptRequestAddressForTransaction(context.Background(), receiverMessage.ID, "some-address")
|
response, err = theirMessenger.AcceptRequestAddressForTransaction(context.Background(), receiverMessage.ID, "some-address")
|
||||||
|
@ -1810,7 +1811,7 @@ func (s *MessengerSuite) TestAcceptRequestAddressForTransaction() {
|
||||||
s.Require().NotNil(senderMessage.CommandParameters)
|
s.Require().NotNil(senderMessage.CommandParameters)
|
||||||
s.Require().Equal(value, senderMessage.CommandParameters.Value)
|
s.Require().Equal(value, senderMessage.CommandParameters.Value)
|
||||||
s.Require().Equal(contract, senderMessage.CommandParameters.Contract)
|
s.Require().Equal(contract, senderMessage.CommandParameters.Contract)
|
||||||
s.Require().Equal(CommandStateRequestAddressForTransactionAccepted, senderMessage.CommandParameters.CommandState)
|
s.Require().Equal(common.CommandStateRequestAddressForTransactionAccepted, senderMessage.CommandParameters.CommandState)
|
||||||
s.Require().Equal(initialCommandID, senderMessage.CommandParameters.ID)
|
s.Require().Equal(initialCommandID, senderMessage.CommandParameters.ID)
|
||||||
s.Require().Equal("some-address", senderMessage.CommandParameters.Address)
|
s.Require().Equal("some-address", senderMessage.CommandParameters.Address)
|
||||||
s.Require().Equal(receiverMessage.ID, senderMessage.Replace)
|
s.Require().Equal(receiverMessage.ID, senderMessage.Replace)
|
||||||
|
@ -1832,7 +1833,7 @@ func (s *MessengerSuite) TestAcceptRequestAddressForTransaction() {
|
||||||
s.Require().NotNil(receiverMessage.CommandParameters)
|
s.Require().NotNil(receiverMessage.CommandParameters)
|
||||||
s.Require().Equal(value, receiverMessage.CommandParameters.Value)
|
s.Require().Equal(value, receiverMessage.CommandParameters.Value)
|
||||||
s.Require().Equal(contract, receiverMessage.CommandParameters.Contract)
|
s.Require().Equal(contract, receiverMessage.CommandParameters.Contract)
|
||||||
s.Require().Equal(CommandStateRequestAddressForTransactionAccepted, receiverMessage.CommandParameters.CommandState)
|
s.Require().Equal(common.CommandStateRequestAddressForTransactionAccepted, receiverMessage.CommandParameters.CommandState)
|
||||||
s.Require().Equal(initialCommandID, receiverMessage.CommandParameters.ID)
|
s.Require().Equal(initialCommandID, receiverMessage.CommandParameters.ID)
|
||||||
s.Require().Equal("some-address", receiverMessage.CommandParameters.Address)
|
s.Require().Equal("some-address", receiverMessage.CommandParameters.Address)
|
||||||
s.Require().Equal(initialCommandID, receiverMessage.Replace)
|
s.Require().Equal(initialCommandID, receiverMessage.Replace)
|
||||||
|
@ -1868,7 +1869,7 @@ func (s *MessengerSuite) TestDeclineRequestTransaction() {
|
||||||
s.Require().Equal(contract, senderMessage.CommandParameters.Contract)
|
s.Require().Equal(contract, senderMessage.CommandParameters.Contract)
|
||||||
s.Require().Equal(receiverAddressString, senderMessage.CommandParameters.Address)
|
s.Require().Equal(receiverAddressString, senderMessage.CommandParameters.Address)
|
||||||
s.Require().Equal(initialCommandID, senderMessage.CommandParameters.ID)
|
s.Require().Equal(initialCommandID, senderMessage.CommandParameters.ID)
|
||||||
s.Require().Equal(CommandStateRequestTransaction, senderMessage.CommandParameters.CommandState)
|
s.Require().Equal(common.CommandStateRequestTransaction, senderMessage.CommandParameters.CommandState)
|
||||||
|
|
||||||
// Wait for the message to reach its destination
|
// Wait for the message to reach its destination
|
||||||
response, err = WaitOnMessengerResponse(
|
response, err = WaitOnMessengerResponse(
|
||||||
|
@ -1890,7 +1891,7 @@ func (s *MessengerSuite) TestDeclineRequestTransaction() {
|
||||||
s.Require().Equal(contract, receiverMessage.CommandParameters.Contract)
|
s.Require().Equal(contract, receiverMessage.CommandParameters.Contract)
|
||||||
s.Require().Equal(receiverAddressString, receiverMessage.CommandParameters.Address)
|
s.Require().Equal(receiverAddressString, receiverMessage.CommandParameters.Address)
|
||||||
s.Require().Equal(initialCommandID, receiverMessage.CommandParameters.ID)
|
s.Require().Equal(initialCommandID, receiverMessage.CommandParameters.ID)
|
||||||
s.Require().Equal(CommandStateRequestTransaction, receiverMessage.CommandParameters.CommandState)
|
s.Require().Equal(common.CommandStateRequestTransaction, receiverMessage.CommandParameters.CommandState)
|
||||||
|
|
||||||
response, err = theirMessenger.DeclineRequestTransaction(context.Background(), initialCommandID)
|
response, err = theirMessenger.DeclineRequestTransaction(context.Background(), initialCommandID)
|
||||||
s.Require().NoError(err)
|
s.Require().NoError(err)
|
||||||
|
@ -1904,7 +1905,7 @@ func (s *MessengerSuite) TestDeclineRequestTransaction() {
|
||||||
s.Require().Equal("Transaction request declined", senderMessage.Text)
|
s.Require().Equal("Transaction request declined", senderMessage.Text)
|
||||||
s.Require().Equal(initialCommandID, senderMessage.CommandParameters.ID)
|
s.Require().Equal(initialCommandID, senderMessage.CommandParameters.ID)
|
||||||
s.Require().Equal(receiverMessage.ID, senderMessage.Replace)
|
s.Require().Equal(receiverMessage.ID, senderMessage.Replace)
|
||||||
s.Require().Equal(CommandStateRequestTransactionDeclined, senderMessage.CommandParameters.CommandState)
|
s.Require().Equal(common.CommandStateRequestTransactionDeclined, senderMessage.CommandParameters.CommandState)
|
||||||
|
|
||||||
// Wait for the message to reach its destination
|
// Wait for the message to reach its destination
|
||||||
response, err = WaitOnMessengerResponse(
|
response, err = WaitOnMessengerResponse(
|
||||||
|
@ -1924,7 +1925,7 @@ func (s *MessengerSuite) TestDeclineRequestTransaction() {
|
||||||
s.Require().Equal("Transaction request declined", receiverMessage.Text)
|
s.Require().Equal("Transaction request declined", receiverMessage.Text)
|
||||||
s.Require().Equal(initialCommandID, receiverMessage.CommandParameters.ID)
|
s.Require().Equal(initialCommandID, receiverMessage.CommandParameters.ID)
|
||||||
s.Require().Equal(initialCommandID, receiverMessage.Replace)
|
s.Require().Equal(initialCommandID, receiverMessage.Replace)
|
||||||
s.Require().Equal(CommandStateRequestTransactionDeclined, receiverMessage.CommandParameters.CommandState)
|
s.Require().Equal(common.CommandStateRequestTransactionDeclined, receiverMessage.CommandParameters.CommandState)
|
||||||
s.Require().NoError(theirMessenger.Shutdown())
|
s.Require().NoError(theirMessenger.Shutdown())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1957,7 +1958,7 @@ func (s *MessengerSuite) TestRequestTransaction() {
|
||||||
s.Require().Equal(contract, senderMessage.CommandParameters.Contract)
|
s.Require().Equal(contract, senderMessage.CommandParameters.Contract)
|
||||||
s.Require().Equal(receiverAddressString, senderMessage.CommandParameters.Address)
|
s.Require().Equal(receiverAddressString, senderMessage.CommandParameters.Address)
|
||||||
s.Require().Equal(initialCommandID, senderMessage.CommandParameters.ID)
|
s.Require().Equal(initialCommandID, senderMessage.CommandParameters.ID)
|
||||||
s.Require().Equal(CommandStateRequestTransaction, senderMessage.CommandParameters.CommandState)
|
s.Require().Equal(common.CommandStateRequestTransaction, senderMessage.CommandParameters.CommandState)
|
||||||
|
|
||||||
// Wait for the message to reach its destination
|
// Wait for the message to reach its destination
|
||||||
response, err = WaitOnMessengerResponse(
|
response, err = WaitOnMessengerResponse(
|
||||||
|
@ -1979,7 +1980,7 @@ func (s *MessengerSuite) TestRequestTransaction() {
|
||||||
s.Require().Equal(contract, receiverMessage.CommandParameters.Contract)
|
s.Require().Equal(contract, receiverMessage.CommandParameters.Contract)
|
||||||
s.Require().Equal(receiverAddressString, receiverMessage.CommandParameters.Address)
|
s.Require().Equal(receiverAddressString, receiverMessage.CommandParameters.Address)
|
||||||
s.Require().Equal(initialCommandID, receiverMessage.CommandParameters.ID)
|
s.Require().Equal(initialCommandID, receiverMessage.CommandParameters.ID)
|
||||||
s.Require().Equal(CommandStateRequestTransaction, receiverMessage.CommandParameters.CommandState)
|
s.Require().Equal(common.CommandStateRequestTransaction, receiverMessage.CommandParameters.CommandState)
|
||||||
|
|
||||||
transactionHash := "0x412a851ac2ae51cad34a56c8a9cfee55d577ac5e1ac71cf488a2f2093a373799"
|
transactionHash := "0x412a851ac2ae51cad34a56c8a9cfee55d577ac5e1ac71cf488a2f2093a373799"
|
||||||
signature, err := buildSignature(theirMessenger.identity, &theirMessenger.identity.PublicKey, transactionHash)
|
signature, err := buildSignature(theirMessenger.identity, &theirMessenger.identity.PublicKey, transactionHash)
|
||||||
|
@ -2003,7 +2004,7 @@ func (s *MessengerSuite) TestRequestTransaction() {
|
||||||
s.Require().Equal(signature, senderMessage.CommandParameters.Signature)
|
s.Require().Equal(signature, senderMessage.CommandParameters.Signature)
|
||||||
s.Require().NotEmpty(senderMessage.ID)
|
s.Require().NotEmpty(senderMessage.ID)
|
||||||
s.Require().Equal(receiverMessage.ID, senderMessage.Replace)
|
s.Require().Equal(receiverMessage.ID, senderMessage.Replace)
|
||||||
s.Require().Equal(CommandStateTransactionSent, senderMessage.CommandParameters.CommandState)
|
s.Require().Equal(common.CommandStateTransactionSent, senderMessage.CommandParameters.CommandState)
|
||||||
|
|
||||||
var transactions []*TransactionToValidate
|
var transactions []*TransactionToValidate
|
||||||
// Wait for the message to reach its destination
|
// Wait for the message to reach its destination
|
||||||
|
@ -2068,7 +2069,7 @@ func (s *MessengerSuite) TestRequestTransaction() {
|
||||||
s.Require().Equal(receiverAddressString, receiverMessage.CommandParameters.Address)
|
s.Require().Equal(receiverAddressString, receiverMessage.CommandParameters.Address)
|
||||||
s.Require().Equal(initialCommandID, receiverMessage.CommandParameters.ID)
|
s.Require().Equal(initialCommandID, receiverMessage.CommandParameters.ID)
|
||||||
s.Require().Equal(signature, receiverMessage.CommandParameters.Signature)
|
s.Require().Equal(signature, receiverMessage.CommandParameters.Signature)
|
||||||
s.Require().Equal(CommandStateTransactionSent, receiverMessage.CommandParameters.CommandState)
|
s.Require().Equal(common.CommandStateTransactionSent, receiverMessage.CommandParameters.CommandState)
|
||||||
s.Require().Equal(senderMessage.ID, receiverMessage.ID)
|
s.Require().Equal(senderMessage.ID, receiverMessage.ID)
|
||||||
s.Require().Equal(senderMessage.Replace, senderMessage.Replace)
|
s.Require().Equal(senderMessage.Replace, senderMessage.Replace)
|
||||||
s.Require().NoError(theirMessenger.Shutdown())
|
s.Require().NoError(theirMessenger.Shutdown())
|
||||||
|
@ -2102,7 +2103,7 @@ func (m *mockSendMessagesRequest) SendMessagesRequest(peerID []byte, request typ
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *MessengerSuite) TestMessageJSON() {
|
func (s *MessengerSuite) TestMessageJSON() {
|
||||||
message := &Message{
|
message := &common.Message{
|
||||||
ID: "test-1",
|
ID: "test-1",
|
||||||
LocalChatID: "local-chat-id",
|
LocalChatID: "local-chat-id",
|
||||||
Alias: "alias",
|
Alias: "alias",
|
||||||
|
@ -2121,7 +2122,7 @@ func (s *MessengerSuite) TestMessageJSON() {
|
||||||
s.Require().NoError(err)
|
s.Require().NoError(err)
|
||||||
s.Require().Equal(expectedJSON, string(messageJSON))
|
s.Require().Equal(expectedJSON, string(messageJSON))
|
||||||
|
|
||||||
decodedMessage := &Message{}
|
decodedMessage := &common.Message{}
|
||||||
err = json.Unmarshal([]byte(expectedJSON), decodedMessage)
|
err = json.Unmarshal([]byte(expectedJSON), decodedMessage)
|
||||||
s.Require().NoError(err)
|
s.Require().NoError(err)
|
||||||
s.Require().Equal(message, decodedMessage)
|
s.Require().Equal(message, decodedMessage)
|
||||||
|
@ -2186,14 +2187,14 @@ func (s *MessageHandlerSuite) TestRun() {
|
||||||
Name string
|
Name string
|
||||||
Error bool
|
Error bool
|
||||||
Chat Chat // Chat to create
|
Chat Chat // Chat to create
|
||||||
Message Message
|
Message common.Message
|
||||||
SigPubKey *ecdsa.PublicKey
|
SigPubKey *ecdsa.PublicKey
|
||||||
ExpectedChatID string
|
ExpectedChatID string
|
||||||
}{
|
}{
|
||||||
{
|
{
|
||||||
Name: "Public chat",
|
Name: "Public chat",
|
||||||
Chat: CreatePublicChat("test-chat", &testTimeSource{}),
|
Chat: CreatePublicChat("test-chat", &testTimeSource{}),
|
||||||
Message: Message{
|
Message: common.Message{
|
||||||
ChatMessage: protobuf.ChatMessage{
|
ChatMessage: protobuf.ChatMessage{
|
||||||
ChatId: "test-chat",
|
ChatId: "test-chat",
|
||||||
MessageType: protobuf.MessageType_PUBLIC_GROUP,
|
MessageType: protobuf.MessageType_PUBLIC_GROUP,
|
||||||
|
@ -2205,7 +2206,7 @@ func (s *MessageHandlerSuite) TestRun() {
|
||||||
{
|
{
|
||||||
Name: "Private message from myself with existing chat",
|
Name: "Private message from myself with existing chat",
|
||||||
Chat: CreateOneToOneChat("test-private-chat", &key1.PublicKey, &testTimeSource{}),
|
Chat: CreateOneToOneChat("test-private-chat", &key1.PublicKey, &testTimeSource{}),
|
||||||
Message: Message{
|
Message: common.Message{
|
||||||
ChatMessage: protobuf.ChatMessage{
|
ChatMessage: protobuf.ChatMessage{
|
||||||
ChatId: "test-chat",
|
ChatId: "test-chat",
|
||||||
MessageType: protobuf.MessageType_ONE_TO_ONE,
|
MessageType: protobuf.MessageType_ONE_TO_ONE,
|
||||||
|
@ -2217,7 +2218,7 @@ func (s *MessageHandlerSuite) TestRun() {
|
||||||
{
|
{
|
||||||
Name: "Private message from other with existing chat",
|
Name: "Private message from other with existing chat",
|
||||||
Chat: CreateOneToOneChat("test-private-chat", &key2.PublicKey, &testTimeSource{}),
|
Chat: CreateOneToOneChat("test-private-chat", &key2.PublicKey, &testTimeSource{}),
|
||||||
Message: Message{
|
Message: common.Message{
|
||||||
ChatMessage: protobuf.ChatMessage{
|
ChatMessage: protobuf.ChatMessage{
|
||||||
ChatId: "test-chat",
|
ChatId: "test-chat",
|
||||||
MessageType: protobuf.MessageType_ONE_TO_ONE,
|
MessageType: protobuf.MessageType_ONE_TO_ONE,
|
||||||
|
@ -2229,7 +2230,7 @@ func (s *MessageHandlerSuite) TestRun() {
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
Name: "Private message from myself without chat",
|
Name: "Private message from myself without chat",
|
||||||
Message: Message{
|
Message: common.Message{
|
||||||
ChatMessage: protobuf.ChatMessage{
|
ChatMessage: protobuf.ChatMessage{
|
||||||
ChatId: "test-chat",
|
ChatId: "test-chat",
|
||||||
MessageType: protobuf.MessageType_ONE_TO_ONE,
|
MessageType: protobuf.MessageType_ONE_TO_ONE,
|
||||||
|
@ -2241,7 +2242,7 @@ func (s *MessageHandlerSuite) TestRun() {
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
Name: "Private message from other without chat",
|
Name: "Private message from other without chat",
|
||||||
Message: Message{
|
Message: common.Message{
|
||||||
ChatMessage: protobuf.ChatMessage{
|
ChatMessage: protobuf.ChatMessage{
|
||||||
ChatId: "test-chat",
|
ChatId: "test-chat",
|
||||||
MessageType: protobuf.MessageType_ONE_TO_ONE,
|
MessageType: protobuf.MessageType_ONE_TO_ONE,
|
||||||
|
@ -2258,7 +2259,7 @@ func (s *MessageHandlerSuite) TestRun() {
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
Name: "Private group message",
|
Name: "Private group message",
|
||||||
Message: Message{
|
Message: common.Message{
|
||||||
ChatMessage: protobuf.ChatMessage{
|
ChatMessage: protobuf.ChatMessage{
|
||||||
ChatId: "non-existing-chat",
|
ChatId: "non-existing-chat",
|
||||||
MessageType: protobuf.MessageType_PRIVATE_GROUP,
|
MessageType: protobuf.MessageType_PRIVATE_GROUP,
|
||||||
|
|
|
@ -22,6 +22,8 @@
|
||||||
// 1596805115_create_group_chat_invitations_table.up.sql (231B)
|
// 1596805115_create_group_chat_invitations_table.up.sql (231B)
|
||||||
// 1597322655_add_invitation_admin_chat_field.up.sql (54B)
|
// 1597322655_add_invitation_admin_chat_field.up.sql (54B)
|
||||||
// 1597757544_add_nickname.up.sql (52B)
|
// 1597757544_add_nickname.up.sql (52B)
|
||||||
|
// 1598955122_add_mentions.down.sql (0)
|
||||||
|
// 1598955122_add_mentions.up.sql (52B)
|
||||||
// 1599641390_add_emoji_reactions_index.down.sql (67B)
|
// 1599641390_add_emoji_reactions_index.down.sql (67B)
|
||||||
// 1599641390_add_emoji_reactions_index.up.sql (126B)
|
// 1599641390_add_emoji_reactions_index.up.sql (126B)
|
||||||
// doc.go (850B)
|
// doc.go (850B)
|
||||||
|
@ -533,6 +535,46 @@ func _1597757544_add_nicknameUpSql() (*asset, error) {
|
||||||
return a, nil
|
return a, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var __1598955122_add_mentionsDownSql = []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\x01\x00\x00\xff\xff\x00\x00\x00\x00\x00\x00\x00\x00")
|
||||||
|
|
||||||
|
func _1598955122_add_mentionsDownSqlBytes() ([]byte, error) {
|
||||||
|
return bindataRead(
|
||||||
|
__1598955122_add_mentionsDownSql,
|
||||||
|
"1598955122_add_mentions.down.sql",
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
func _1598955122_add_mentionsDownSql() (*asset, error) {
|
||||||
|
bytes, err := _1598955122_add_mentionsDownSqlBytes()
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
info := bindataFileInfo{name: "1598955122_add_mentions.down.sql", size: 0, mode: os.FileMode(0644), modTime: time.Unix(1599679300, 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}}
|
||||||
|
return a, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
var __1598955122_add_mentionsUpSql = []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\x72\xf4\x09\x71\x0d\x52\x08\x71\x74\xf2\x71\x55\x28\x2d\x4e\x2d\x8a\xcf\x4d\x2d\x2e\x4e\x4c\x4f\x2d\x56\x70\x74\x71\x51\x70\xf6\xf7\x09\xf5\xf5\x53\xc8\x4d\xcd\x2b\xc9\xcc\xcf\x2b\x56\x70\xf2\xf1\x77\xb2\xe6\x02\x04\x00\x00\xff\xff\xca\xf8\x74\x41\x34\x00\x00\x00")
|
||||||
|
|
||||||
|
func _1598955122_add_mentionsUpSqlBytes() ([]byte, error) {
|
||||||
|
return bindataRead(
|
||||||
|
__1598955122_add_mentionsUpSql,
|
||||||
|
"1598955122_add_mentions.up.sql",
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
func _1598955122_add_mentionsUpSql() (*asset, error) {
|
||||||
|
bytes, err := _1598955122_add_mentionsUpSqlBytes()
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
info := bindataFileInfo{name: "1598955122_add_mentions.up.sql", size: 52, mode: os.FileMode(0644), modTime: time.Unix(1599679300, 0)}
|
||||||
|
a := &asset{bytes: bytes, info: info, digest: [32]uint8{0x8d, 0x22, 0x17, 0x92, 0xd2, 0x11, 0x4e, 0x7, 0x93, 0x9a, 0x55, 0xfd, 0xb, 0x97, 0xc4, 0x63, 0x6a, 0x81, 0x97, 0xcd, 0xb2, 0xf8, 0x4b, 0x5f, 0x3c, 0xfa, 0x3a, 0x38, 0x53, 0x10, 0xed, 0x9d}}
|
||||||
|
return a, nil
|
||||||
|
}
|
||||||
|
|
||||||
var __1599641390_add_emoji_reactions_indexDownSql = []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\x72\x09\xf2\x0f\x50\xf0\xf4\x73\x71\x8d\x50\x48\xcd\xcd\xcf\xca\x8c\x2f\x4a\x4d\x4c\x2e\xc9\xcc\xcf\x2b\x8e\xcf\x4d\x2d\x2e\x4e\x4c\x4f\x8d\xcf\x4c\x89\xcf\xc9\x4f\x4e\xcc\x89\x4f\xce\x48\x2c\x01\xf1\x8a\x52\x4b\x8a\x12\x93\x4b\x52\x53\xe2\x33\x53\x2a\xac\xb9\x00\x01\x00\x00\xff\xff\xb2\x85\x84\xa0\x43\x00\x00\x00")
|
var __1599641390_add_emoji_reactions_indexDownSql = []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\x72\x09\xf2\x0f\x50\xf0\xf4\x73\x71\x8d\x50\x48\xcd\xcd\xcf\xca\x8c\x2f\x4a\x4d\x4c\x2e\xc9\xcc\xcf\x2b\x8e\xcf\x4d\x2d\x2e\x4e\x4c\x4f\x8d\xcf\x4c\x89\xcf\xc9\x4f\x4e\xcc\x89\x4f\xce\x48\x2c\x01\xf1\x8a\x52\x4b\x8a\x12\x93\x4b\x52\x53\xe2\x33\x53\x2a\xac\xb9\x00\x01\x00\x00\xff\xff\xb2\x85\x84\xa0\x43\x00\x00\x00")
|
||||||
|
|
||||||
func _1599641390_add_emoji_reactions_indexDownSqlBytes() ([]byte, error) {
|
func _1599641390_add_emoji_reactions_indexDownSqlBytes() ([]byte, error) {
|
||||||
|
@ -548,7 +590,7 @@ func _1599641390_add_emoji_reactions_indexDownSql() (*asset, error) {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
info := bindataFileInfo{name: "1599641390_add_emoji_reactions_index.down.sql", size: 67, mode: os.FileMode(0644), modTime: time.Unix(1599641440, 0)}
|
info := bindataFileInfo{name: "1599641390_add_emoji_reactions_index.down.sql", size: 67, mode: os.FileMode(0644), modTime: time.Unix(1599679300, 0)}
|
||||||
a := &asset{bytes: bytes, info: info, digest: [32]uint8{0x89, 0x39, 0x0, 0x51, 0x5b, 0x48, 0xc3, 0xf3, 0x6a, 0x96, 0xf1, 0xd2, 0xa6, 0x60, 0xa8, 0x68, 0x21, 0xb5, 0xa0, 0x11, 0x11, 0x99, 0xde, 0xad, 0xa6, 0xa7, 0x56, 0xc1, 0xb2, 0xa6, 0x63, 0xe4}}
|
a := &asset{bytes: bytes, info: info, digest: [32]uint8{0x89, 0x39, 0x0, 0x51, 0x5b, 0x48, 0xc3, 0xf3, 0x6a, 0x96, 0xf1, 0xd2, 0xa6, 0x60, 0xa8, 0x68, 0x21, 0xb5, 0xa0, 0x11, 0x11, 0x99, 0xde, 0xad, 0xa6, 0xa7, 0x56, 0xc1, 0xb2, 0xa6, 0x63, 0xe4}}
|
||||||
return a, nil
|
return a, nil
|
||||||
}
|
}
|
||||||
|
@ -568,7 +610,7 @@ func _1599641390_add_emoji_reactions_indexUpSql() (*asset, error) {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
info := bindataFileInfo{name: "1599641390_add_emoji_reactions_index.up.sql", size: 126, mode: os.FileMode(0644), modTime: time.Unix(1599641420, 0)}
|
info := bindataFileInfo{name: "1599641390_add_emoji_reactions_index.up.sql", size: 126, mode: os.FileMode(0644), modTime: time.Unix(1599679300, 0)}
|
||||||
a := &asset{bytes: bytes, info: info, digest: [32]uint8{0xf9, 0xd8, 0xdc, 0xa7, 0xb, 0x92, 0x7a, 0x61, 0x37, 0x24, 0x1c, 0x77, 0x5e, 0xe, 0x7e, 0xfc, 0x9f, 0x98, 0x7b, 0x65, 0xe7, 0xf9, 0x71, 0x57, 0x89, 0x2d, 0x90, 0x1b, 0xf6, 0x5e, 0x37, 0xe8}}
|
a := &asset{bytes: bytes, info: info, digest: [32]uint8{0xf9, 0xd8, 0xdc, 0xa7, 0xb, 0x92, 0x7a, 0x61, 0x37, 0x24, 0x1c, 0x77, 0x5e, 0xe, 0x7e, 0xfc, 0x9f, 0x98, 0x7b, 0x65, 0xe7, 0xf9, 0x71, 0x57, 0x89, 0x2d, 0x90, 0x1b, 0xf6, 0x5e, 0x37, 0xe8}}
|
||||||
return a, nil
|
return a, nil
|
||||||
}
|
}
|
||||||
|
@ -728,6 +770,10 @@ var _bindata = map[string]func() (*asset, error){
|
||||||
|
|
||||||
"1597757544_add_nickname.up.sql": _1597757544_add_nicknameUpSql,
|
"1597757544_add_nickname.up.sql": _1597757544_add_nicknameUpSql,
|
||||||
|
|
||||||
|
"1598955122_add_mentions.down.sql": _1598955122_add_mentionsDownSql,
|
||||||
|
|
||||||
|
"1598955122_add_mentions.up.sql": _1598955122_add_mentionsUpSql,
|
||||||
|
|
||||||
"1599641390_add_emoji_reactions_index.down.sql": _1599641390_add_emoji_reactions_indexDownSql,
|
"1599641390_add_emoji_reactions_index.down.sql": _1599641390_add_emoji_reactions_indexDownSql,
|
||||||
|
|
||||||
"1599641390_add_emoji_reactions_index.up.sql": _1599641390_add_emoji_reactions_indexUpSql,
|
"1599641390_add_emoji_reactions_index.up.sql": _1599641390_add_emoji_reactions_indexUpSql,
|
||||||
|
@ -798,6 +844,8 @@ var _bintree = &bintree{nil, map[string]*bintree{
|
||||||
"1596805115_create_group_chat_invitations_table.up.sql": &bintree{_1596805115_create_group_chat_invitations_tableUpSql, map[string]*bintree{}},
|
"1596805115_create_group_chat_invitations_table.up.sql": &bintree{_1596805115_create_group_chat_invitations_tableUpSql, map[string]*bintree{}},
|
||||||
"1597322655_add_invitation_admin_chat_field.up.sql": &bintree{_1597322655_add_invitation_admin_chat_fieldUpSql, map[string]*bintree{}},
|
"1597322655_add_invitation_admin_chat_field.up.sql": &bintree{_1597322655_add_invitation_admin_chat_fieldUpSql, map[string]*bintree{}},
|
||||||
"1597757544_add_nickname.up.sql": &bintree{_1597757544_add_nicknameUpSql, map[string]*bintree{}},
|
"1597757544_add_nickname.up.sql": &bintree{_1597757544_add_nicknameUpSql, map[string]*bintree{}},
|
||||||
|
"1598955122_add_mentions.down.sql": &bintree{_1598955122_add_mentionsDownSql, map[string]*bintree{}},
|
||||||
|
"1598955122_add_mentions.up.sql": &bintree{_1598955122_add_mentionsUpSql, map[string]*bintree{}},
|
||||||
"1599641390_add_emoji_reactions_index.down.sql": &bintree{_1599641390_add_emoji_reactions_indexDownSql, map[string]*bintree{}},
|
"1599641390_add_emoji_reactions_index.down.sql": &bintree{_1599641390_add_emoji_reactions_indexDownSql, map[string]*bintree{}},
|
||||||
"1599641390_add_emoji_reactions_index.up.sql": &bintree{_1599641390_add_emoji_reactions_indexUpSql, map[string]*bintree{}},
|
"1599641390_add_emoji_reactions_index.up.sql": &bintree{_1599641390_add_emoji_reactions_indexUpSql, map[string]*bintree{}},
|
||||||
"doc.go": &bintree{docGo, map[string]*bintree{}},
|
"doc.go": &bintree{docGo, map[string]*bintree{}},
|
||||||
|
|
|
@ -0,0 +1 @@
|
||||||
|
ALTER TABLE user_messages ADD COLUMN mentions BLOB;
|
|
@ -266,7 +266,7 @@ func (db sqlitePersistence) chats(tx *sql.Tx) (chats []*Chat, err error) {
|
||||||
|
|
||||||
// Restore last message
|
// Restore last message
|
||||||
if lastMessageBytes != nil {
|
if lastMessageBytes != nil {
|
||||||
message := &Message{}
|
message := &common.Message{}
|
||||||
if err = json.Unmarshal(lastMessageBytes, message); err != nil {
|
if err = json.Unmarshal(lastMessageBytes, message); err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
@ -346,7 +346,7 @@ func (db sqlitePersistence) Chat(chatID string) (*Chat, error) {
|
||||||
|
|
||||||
// Restore last message
|
// Restore last message
|
||||||
if lastMessageBytes != nil {
|
if lastMessageBytes != nil {
|
||||||
message := &Message{}
|
message := &common.Message{}
|
||||||
if err = json.Unmarshal(lastMessageBytes, message); err != nil {
|
if err = json.Unmarshal(lastMessageBytes, message); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
|
@ -11,6 +11,9 @@ import (
|
||||||
|
|
||||||
"github.com/stretchr/testify/require"
|
"github.com/stretchr/testify/require"
|
||||||
|
|
||||||
|
"github.com/status-im/status-go/eth-node/crypto"
|
||||||
|
"github.com/status-im/status-go/eth-node/types"
|
||||||
|
"github.com/status-im/status-go/protocol/common"
|
||||||
"github.com/status-im/status-go/protocol/protobuf"
|
"github.com/status-im/status-go/protocol/protobuf"
|
||||||
"github.com/status-im/status-go/protocol/sqlite"
|
"github.com/status-im/status-go/protocol/sqlite"
|
||||||
)
|
)
|
||||||
|
@ -101,9 +104,9 @@ func TestMessageByChatID(t *testing.T) {
|
||||||
count := 1000
|
count := 1000
|
||||||
pageSize := 50
|
pageSize := 50
|
||||||
|
|
||||||
var messages []*Message
|
var messages []*common.Message
|
||||||
for i := 0; i < count; i++ {
|
for i := 0; i < count; i++ {
|
||||||
messages = append(messages, &Message{
|
messages = append(messages, &common.Message{
|
||||||
ID: strconv.Itoa(i),
|
ID: strconv.Itoa(i),
|
||||||
LocalChatID: chatID,
|
LocalChatID: chatID,
|
||||||
ChatMessage: protobuf.ChatMessage{
|
ChatMessage: protobuf.ChatMessage{
|
||||||
|
@ -114,7 +117,7 @@ func TestMessageByChatID(t *testing.T) {
|
||||||
|
|
||||||
// Add some other chats.
|
// Add some other chats.
|
||||||
if count%5 == 0 {
|
if count%5 == 0 {
|
||||||
messages = append(messages, &Message{
|
messages = append(messages, &common.Message{
|
||||||
ID: strconv.Itoa(count + i),
|
ID: strconv.Itoa(count + i),
|
||||||
LocalChatID: "other-chat",
|
LocalChatID: "other-chat",
|
||||||
ChatMessage: protobuf.ChatMessage{
|
ChatMessage: protobuf.ChatMessage{
|
||||||
|
@ -130,7 +133,7 @@ func TestMessageByChatID(t *testing.T) {
|
||||||
outOfOrderCount := pageSize + 1
|
outOfOrderCount := pageSize + 1
|
||||||
allCount := count + outOfOrderCount
|
allCount := count + outOfOrderCount
|
||||||
for i := 0; i < pageSize+1; i++ {
|
for i := 0; i < pageSize+1; i++ {
|
||||||
messages = append(messages, &Message{
|
messages = append(messages, &common.Message{
|
||||||
ID: strconv.Itoa(count*2 + i),
|
ID: strconv.Itoa(count*2 + i),
|
||||||
LocalChatID: chatID,
|
LocalChatID: chatID,
|
||||||
ChatMessage: protobuf.ChatMessage{
|
ChatMessage: protobuf.ChatMessage{
|
||||||
|
@ -145,13 +148,13 @@ func TestMessageByChatID(t *testing.T) {
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
result []*Message
|
result []*common.Message
|
||||||
cursor string
|
cursor string
|
||||||
iter int
|
iter int
|
||||||
)
|
)
|
||||||
for {
|
for {
|
||||||
var (
|
var (
|
||||||
items []*Message
|
items []*common.Message
|
||||||
err error
|
err error
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -181,7 +184,7 @@ func TestMessageReplies(t *testing.T) {
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
p := sqlitePersistence{db: db}
|
p := sqlitePersistence{db: db}
|
||||||
chatID := testPublicChatID
|
chatID := testPublicChatID
|
||||||
message1 := &Message{
|
message1 := &common.Message{
|
||||||
ID: "id-1",
|
ID: "id-1",
|
||||||
LocalChatID: chatID,
|
LocalChatID: chatID,
|
||||||
ChatMessage: protobuf.ChatMessage{
|
ChatMessage: protobuf.ChatMessage{
|
||||||
|
@ -190,7 +193,7 @@ func TestMessageReplies(t *testing.T) {
|
||||||
},
|
},
|
||||||
From: "1",
|
From: "1",
|
||||||
}
|
}
|
||||||
message2 := &Message{
|
message2 := &common.Message{
|
||||||
ID: "id-2",
|
ID: "id-2",
|
||||||
LocalChatID: chatID,
|
LocalChatID: chatID,
|
||||||
ChatMessage: protobuf.ChatMessage{
|
ChatMessage: protobuf.ChatMessage{
|
||||||
|
@ -202,7 +205,7 @@ func TestMessageReplies(t *testing.T) {
|
||||||
From: "2",
|
From: "2",
|
||||||
}
|
}
|
||||||
|
|
||||||
message3 := &Message{
|
message3 := &common.Message{
|
||||||
ID: "id-3",
|
ID: "id-3",
|
||||||
LocalChatID: chatID,
|
LocalChatID: chatID,
|
||||||
ChatMessage: protobuf.ChatMessage{
|
ChatMessage: protobuf.ChatMessage{
|
||||||
|
@ -213,7 +216,7 @@ func TestMessageReplies(t *testing.T) {
|
||||||
From: "3",
|
From: "3",
|
||||||
}
|
}
|
||||||
|
|
||||||
messages := []*Message{message1, message2, message3}
|
messages := []*common.Message{message1, message2, message3}
|
||||||
|
|
||||||
err = p.SaveMessages(messages)
|
err = p.SaveMessages(messages)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
@ -225,7 +228,7 @@ func TestMessageReplies(t *testing.T) {
|
||||||
require.Nil(t, retrievedMessages[0].QuotedMessage)
|
require.Nil(t, retrievedMessages[0].QuotedMessage)
|
||||||
|
|
||||||
require.Equal(t, "id-1", retrievedMessages[1].ResponseTo)
|
require.Equal(t, "id-1", retrievedMessages[1].ResponseTo)
|
||||||
require.Equal(t, &QuotedMessage{From: "1", Text: "content-1"}, retrievedMessages[1].QuotedMessage)
|
require.Equal(t, &common.QuotedMessage{From: "1", Text: "content-1"}, retrievedMessages[1].QuotedMessage)
|
||||||
|
|
||||||
require.Equal(t, "", retrievedMessages[2].ResponseTo)
|
require.Equal(t, "", retrievedMessages[2].ResponseTo)
|
||||||
require.Nil(t, retrievedMessages[2].QuotedMessage)
|
require.Nil(t, retrievedMessages[2].QuotedMessage)
|
||||||
|
@ -240,10 +243,10 @@ func TestMessageByChatIDWithTheSameClocks(t *testing.T) {
|
||||||
count := len(clockValues)
|
count := len(clockValues)
|
||||||
pageSize := 2
|
pageSize := 2
|
||||||
|
|
||||||
var messages []*Message
|
var messages []*common.Message
|
||||||
|
|
||||||
for i, clock := range clockValues {
|
for i, clock := range clockValues {
|
||||||
messages = append(messages, &Message{
|
messages = append(messages, &common.Message{
|
||||||
ID: strconv.Itoa(i),
|
ID: strconv.Itoa(i),
|
||||||
LocalChatID: chatID,
|
LocalChatID: chatID,
|
||||||
ChatMessage: protobuf.ChatMessage{
|
ChatMessage: protobuf.ChatMessage{
|
||||||
|
@ -257,13 +260,13 @@ func TestMessageByChatIDWithTheSameClocks(t *testing.T) {
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
result []*Message
|
result []*common.Message
|
||||||
cursor string
|
cursor string
|
||||||
iter int
|
iter int
|
||||||
)
|
)
|
||||||
for {
|
for {
|
||||||
var (
|
var (
|
||||||
items []*Message
|
items []*common.Message
|
||||||
err error
|
err error
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -322,14 +325,14 @@ func TestDeleteMessagesByChatID(t *testing.T) {
|
||||||
err = insertMinimalMessage(p, "2")
|
err = insertMinimalMessage(p, "2")
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
m, _, err := p.MessageByChatID("chat-id", "", 10)
|
m, _, err := p.MessageByChatID(testPublicChatID, "", 10)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
require.Equal(t, 2, len(m))
|
require.Equal(t, 2, len(m))
|
||||||
|
|
||||||
err = p.DeleteMessagesByChatID("chat-id")
|
err = p.DeleteMessagesByChatID(testPublicChatID)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
m, _, err = p.MessageByChatID("chat-id", "", 10)
|
m, _, err = p.MessageByChatID(testPublicChatID, "", 10)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
require.Equal(t, 0, len(m))
|
require.Equal(t, 0, len(m))
|
||||||
|
|
||||||
|
@ -388,7 +391,7 @@ func TestPersistenceEmojiReactions(t *testing.T) {
|
||||||
from2 := "from-2"
|
from2 := "from-2"
|
||||||
from3 := "from-3"
|
from3 := "from-3"
|
||||||
|
|
||||||
chatID := "chat-id"
|
chatID := testPublicChatID
|
||||||
|
|
||||||
err = insertMinimalMessage(p, id1)
|
err = insertMinimalMessage(p, id1)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
@ -485,9 +488,9 @@ func openTestDB() (*sql.DB, error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func insertMinimalMessage(p sqlitePersistence, id string) error {
|
func insertMinimalMessage(p sqlitePersistence, id string) error {
|
||||||
return p.SaveMessages([]*Message{{
|
return p.SaveMessages([]*common.Message{{
|
||||||
ID: id,
|
ID: id,
|
||||||
LocalChatID: "chat-id",
|
LocalChatID: testPublicChatID,
|
||||||
ChatMessage: protobuf.ChatMessage{Text: "some-text"},
|
ChatMessage: protobuf.ChatMessage{Text: "some-text"},
|
||||||
From: "me",
|
From: "me",
|
||||||
}})
|
}})
|
||||||
|
@ -510,7 +513,7 @@ func TestMessagesAudioDurationMsNull(t *testing.T) {
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
require.Len(t, m, 1)
|
require.Len(t, m, 1)
|
||||||
|
|
||||||
m, _, err = p.MessageByChatID("chat-id", "", 10)
|
m, _, err = p.MessageByChatID(testPublicChatID, "", 10)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
require.Len(t, m, 1)
|
require.Len(t, m, 1)
|
||||||
}
|
}
|
||||||
|
@ -521,7 +524,7 @@ func TestSaveChat(t *testing.T) {
|
||||||
p := sqlitePersistence{db: db}
|
p := sqlitePersistence{db: db}
|
||||||
|
|
||||||
chat := CreatePublicChat("test-chat", &testTimeSource{})
|
chat := CreatePublicChat("test-chat", &testTimeSource{})
|
||||||
chat.LastMessage = &Message{}
|
chat.LastMessage = &common.Message{}
|
||||||
err = p.SaveChat(chat)
|
err = p.SaveChat(chat)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
@ -529,3 +532,33 @@ func TestSaveChat(t *testing.T) {
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
require.Equal(t, &chat, retrievedChat)
|
require.Equal(t, &chat, retrievedChat)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestSaveMentions(t *testing.T) {
|
||||||
|
chatID := testPublicChatID
|
||||||
|
db, err := openTestDB()
|
||||||
|
require.NoError(t, err)
|
||||||
|
p := sqlitePersistence{db: db}
|
||||||
|
|
||||||
|
key, err := crypto.GenerateKey()
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
pkString := types.EncodeHex(crypto.FromECDSAPub(&key.PublicKey))
|
||||||
|
|
||||||
|
message := common.Message{
|
||||||
|
ID: "1",
|
||||||
|
LocalChatID: chatID,
|
||||||
|
ChatMessage: protobuf.ChatMessage{Text: "some-text"},
|
||||||
|
From: "me",
|
||||||
|
Mentions: []string{pkString},
|
||||||
|
}
|
||||||
|
|
||||||
|
err = p.SaveMessages([]*common.Message{&message})
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
retrievedMessages, _, err := p.MessageByChatID(chatID, "", 10)
|
||||||
|
require.NoError(t, err)
|
||||||
|
require.Len(t, retrievedMessages, 1)
|
||||||
|
require.Len(t, retrievedMessages[0].Mentions, 1)
|
||||||
|
require.Equal(t, retrievedMessages[0].Mentions, message.Mentions)
|
||||||
|
|
||||||
|
}
|
||||||
|
|
|
@ -174,9 +174,7 @@ func init() {
|
||||||
proto.RegisterType((*ApplicationMetadataMessage)(nil), "protobuf.ApplicationMetadataMessage")
|
proto.RegisterType((*ApplicationMetadataMessage)(nil), "protobuf.ApplicationMetadataMessage")
|
||||||
}
|
}
|
||||||
|
|
||||||
func init() {
|
func init() { proto.RegisterFile("application_metadata_message.proto", fileDescriptor_ad09a6406fcf24c7) }
|
||||||
proto.RegisterFile("application_metadata_message.proto", fileDescriptor_ad09a6406fcf24c7)
|
|
||||||
}
|
|
||||||
|
|
||||||
var fileDescriptor_ad09a6406fcf24c7 = []byte{
|
var fileDescriptor_ad09a6406fcf24c7 = []byte{
|
||||||
// 493 bytes of a gzipped FileDescriptorProto
|
// 493 bytes of a gzipped FileDescriptorProto
|
||||||
|
|
|
@ -123,9 +123,7 @@ func init() {
|
||||||
proto.RegisterType((*GroupChatInvitation)(nil), "protobuf.GroupChatInvitation")
|
proto.RegisterType((*GroupChatInvitation)(nil), "protobuf.GroupChatInvitation")
|
||||||
}
|
}
|
||||||
|
|
||||||
func init() {
|
func init() { proto.RegisterFile("group_chat_invitation.proto", fileDescriptor_a6a73333de6a8ebe) }
|
||||||
proto.RegisterFile("group_chat_invitation.proto", fileDescriptor_a6a73333de6a8ebe)
|
|
||||||
}
|
|
||||||
|
|
||||||
var fileDescriptor_a6a73333de6a8ebe = []byte{
|
var fileDescriptor_a6a73333de6a8ebe = []byte{
|
||||||
// 234 bytes of a gzipped FileDescriptorProto
|
// 234 bytes of a gzipped FileDescriptorProto
|
||||||
|
|
|
@ -335,9 +335,7 @@ func init() {
|
||||||
proto.RegisterType((*SyncInstallation)(nil), "protobuf.SyncInstallation")
|
proto.RegisterType((*SyncInstallation)(nil), "protobuf.SyncInstallation")
|
||||||
}
|
}
|
||||||
|
|
||||||
func init() {
|
func init() { proto.RegisterFile("pairing.proto", fileDescriptor_d61ab7221f0b5518) }
|
||||||
proto.RegisterFile("pairing.proto", fileDescriptor_d61ab7221f0b5518)
|
|
||||||
}
|
|
||||||
|
|
||||||
var fileDescriptor_d61ab7221f0b5518 = []byte{
|
var fileDescriptor_d61ab7221f0b5518 = []byte{
|
||||||
// 397 bytes of a gzipped FileDescriptorProto
|
// 397 bytes of a gzipped FileDescriptorProto
|
||||||
|
|
|
@ -142,21 +142,23 @@ func (PushNotificationReport_ErrorType) EnumDescriptor() ([]byte, []int) {
|
||||||
}
|
}
|
||||||
|
|
||||||
type PushNotificationRegistration struct {
|
type PushNotificationRegistration struct {
|
||||||
TokenType PushNotificationRegistration_TokenType `protobuf:"varint,1,opt,name=token_type,json=tokenType,proto3,enum=protobuf.PushNotificationRegistration_TokenType" json:"token_type,omitempty"`
|
TokenType PushNotificationRegistration_TokenType `protobuf:"varint,1,opt,name=token_type,json=tokenType,proto3,enum=protobuf.PushNotificationRegistration_TokenType" json:"token_type,omitempty"`
|
||||||
DeviceToken string `protobuf:"bytes,2,opt,name=device_token,json=deviceToken,proto3" json:"device_token,omitempty"`
|
DeviceToken string `protobuf:"bytes,2,opt,name=device_token,json=deviceToken,proto3" json:"device_token,omitempty"`
|
||||||
InstallationId string `protobuf:"bytes,3,opt,name=installation_id,json=installationId,proto3" json:"installation_id,omitempty"`
|
InstallationId string `protobuf:"bytes,3,opt,name=installation_id,json=installationId,proto3" json:"installation_id,omitempty"`
|
||||||
AccessToken string `protobuf:"bytes,4,opt,name=access_token,json=accessToken,proto3" json:"access_token,omitempty"`
|
AccessToken string `protobuf:"bytes,4,opt,name=access_token,json=accessToken,proto3" json:"access_token,omitempty"`
|
||||||
Enabled bool `protobuf:"varint,5,opt,name=enabled,proto3" json:"enabled,omitempty"`
|
Enabled bool `protobuf:"varint,5,opt,name=enabled,proto3" json:"enabled,omitempty"`
|
||||||
Version uint64 `protobuf:"varint,6,opt,name=version,proto3" json:"version,omitempty"`
|
Version uint64 `protobuf:"varint,6,opt,name=version,proto3" json:"version,omitempty"`
|
||||||
AllowedKeyList [][]byte `protobuf:"bytes,7,rep,name=allowed_key_list,json=allowedKeyList,proto3" json:"allowed_key_list,omitempty"`
|
AllowedKeyList [][]byte `protobuf:"bytes,7,rep,name=allowed_key_list,json=allowedKeyList,proto3" json:"allowed_key_list,omitempty"`
|
||||||
BlockedChatList [][]byte `protobuf:"bytes,8,rep,name=blocked_chat_list,json=blockedChatList,proto3" json:"blocked_chat_list,omitempty"`
|
BlockedChatList [][]byte `protobuf:"bytes,8,rep,name=blocked_chat_list,json=blockedChatList,proto3" json:"blocked_chat_list,omitempty"`
|
||||||
Unregister bool `protobuf:"varint,9,opt,name=unregister,proto3" json:"unregister,omitempty"`
|
Unregister bool `protobuf:"varint,9,opt,name=unregister,proto3" json:"unregister,omitempty"`
|
||||||
Grant []byte `protobuf:"bytes,10,opt,name=grant,proto3" json:"grant,omitempty"`
|
Grant []byte `protobuf:"bytes,10,opt,name=grant,proto3" json:"grant,omitempty"`
|
||||||
AllowFromContactsOnly bool `protobuf:"varint,11,opt,name=allow_from_contacts_only,json=allowFromContactsOnly,proto3" json:"allow_from_contacts_only,omitempty"`
|
AllowFromContactsOnly bool `protobuf:"varint,11,opt,name=allow_from_contacts_only,json=allowFromContactsOnly,proto3" json:"allow_from_contacts_only,omitempty"`
|
||||||
ApnTopic string `protobuf:"bytes,12,opt,name=apn_topic,json=apnTopic,proto3" json:"apn_topic,omitempty"`
|
ApnTopic string `protobuf:"bytes,12,opt,name=apn_topic,json=apnTopic,proto3" json:"apn_topic,omitempty"`
|
||||||
XXX_NoUnkeyedLiteral struct{} `json:"-"`
|
BlockMentions bool `protobuf:"varint,13,opt,name=block_mentions,json=blockMentions,proto3" json:"block_mentions,omitempty"`
|
||||||
XXX_unrecognized []byte `json:"-"`
|
AllowedMentionsChatList [][]byte `protobuf:"bytes,14,rep,name=allowed_mentions_chat_list,json=allowedMentionsChatList,proto3" json:"allowed_mentions_chat_list,omitempty"`
|
||||||
XXX_sizecache int32 `json:"-"`
|
XXX_NoUnkeyedLiteral struct{} `json:"-"`
|
||||||
|
XXX_unrecognized []byte `json:"-"`
|
||||||
|
XXX_sizecache int32 `json:"-"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *PushNotificationRegistration) Reset() { *m = PushNotificationRegistration{} }
|
func (m *PushNotificationRegistration) Reset() { *m = PushNotificationRegistration{} }
|
||||||
|
@ -268,6 +270,20 @@ func (m *PushNotificationRegistration) GetApnTopic() string {
|
||||||
return ""
|
return ""
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (m *PushNotificationRegistration) GetBlockMentions() bool {
|
||||||
|
if m != nil {
|
||||||
|
return m.BlockMentions
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *PushNotificationRegistration) GetAllowedMentionsChatList() [][]byte {
|
||||||
|
if m != nil {
|
||||||
|
return m.AllowedMentionsChatList
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
type PushNotificationRegistrationResponse struct {
|
type PushNotificationRegistrationResponse struct {
|
||||||
Success bool `protobuf:"varint,1,opt,name=success,proto3" json:"success,omitempty"`
|
Success bool `protobuf:"varint,1,opt,name=success,proto3" json:"success,omitempty"`
|
||||||
Error PushNotificationRegistrationResponse_ErrorType `protobuf:"varint,2,opt,name=error,proto3,enum=protobuf.PushNotificationRegistrationResponse_ErrorType" json:"error,omitempty"`
|
Error PushNotificationRegistrationResponse_ErrorType `protobuf:"varint,2,opt,name=error,proto3,enum=protobuf.PushNotificationRegistrationResponse_ErrorType" json:"error,omitempty"`
|
||||||
|
@ -550,6 +566,7 @@ type PushNotification struct {
|
||||||
InstallationId string `protobuf:"bytes,4,opt,name=installation_id,json=installationId,proto3" json:"installation_id,omitempty"`
|
InstallationId string `protobuf:"bytes,4,opt,name=installation_id,json=installationId,proto3" json:"installation_id,omitempty"`
|
||||||
Message []byte `protobuf:"bytes,5,opt,name=message,proto3" json:"message,omitempty"`
|
Message []byte `protobuf:"bytes,5,opt,name=message,proto3" json:"message,omitempty"`
|
||||||
Type PushNotification_PushNotificationType `protobuf:"varint,6,opt,name=type,proto3,enum=protobuf.PushNotification_PushNotificationType" json:"type,omitempty"`
|
Type PushNotification_PushNotificationType `protobuf:"varint,6,opt,name=type,proto3,enum=protobuf.PushNotification_PushNotificationType" json:"type,omitempty"`
|
||||||
|
Author []byte `protobuf:"bytes,7,opt,name=author,proto3" json:"author,omitempty"`
|
||||||
XXX_NoUnkeyedLiteral struct{} `json:"-"`
|
XXX_NoUnkeyedLiteral struct{} `json:"-"`
|
||||||
XXX_unrecognized []byte `json:"-"`
|
XXX_unrecognized []byte `json:"-"`
|
||||||
XXX_sizecache int32 `json:"-"`
|
XXX_sizecache int32 `json:"-"`
|
||||||
|
@ -622,6 +639,13 @@ func (m *PushNotification) GetType() PushNotification_PushNotificationType {
|
||||||
return PushNotification_UNKNOWN_PUSH_NOTIFICATION_TYPE
|
return PushNotification_UNKNOWN_PUSH_NOTIFICATION_TYPE
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (m *PushNotification) GetAuthor() []byte {
|
||||||
|
if m != nil {
|
||||||
|
return m.Author
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
type PushNotificationRequest struct {
|
type PushNotificationRequest struct {
|
||||||
Requests []*PushNotification `protobuf:"bytes,1,rep,name=requests,proto3" json:"requests,omitempty"`
|
Requests []*PushNotification `protobuf:"bytes,1,rep,name=requests,proto3" json:"requests,omitempty"`
|
||||||
MessageId []byte `protobuf:"bytes,2,opt,name=message_id,json=messageId,proto3" json:"message_id,omitempty"`
|
MessageId []byte `protobuf:"bytes,2,opt,name=message_id,json=messageId,proto3" json:"message_id,omitempty"`
|
||||||
|
@ -799,65 +823,68 @@ func init() {
|
||||||
func init() { proto.RegisterFile("push_notifications.proto", fileDescriptor_200acd86044eaa5d) }
|
func init() { proto.RegisterFile("push_notifications.proto", fileDescriptor_200acd86044eaa5d) }
|
||||||
|
|
||||||
var fileDescriptor_200acd86044eaa5d = []byte{
|
var fileDescriptor_200acd86044eaa5d = []byte{
|
||||||
// 952 bytes of a gzipped FileDescriptorProto
|
// 1002 bytes of a gzipped FileDescriptorProto
|
||||||
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xac, 0x55, 0x51, 0x6f, 0xe3, 0x44,
|
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xac, 0x55, 0xdd, 0x6e, 0xe3, 0x44,
|
||||||
0x10, 0xc6, 0x4e, 0xda, 0x24, 0x93, 0x90, 0xba, 0xab, 0xb6, 0x67, 0x0e, 0x7a, 0x04, 0x83, 0x44,
|
0x14, 0xc6, 0x4e, 0xda, 0x24, 0x27, 0x69, 0x9a, 0x8e, 0xfa, 0x63, 0x0a, 0x5d, 0x82, 0x01, 0x11,
|
||||||
0xd4, 0x87, 0x80, 0x8a, 0xc4, 0x9d, 0x78, 0x22, 0xa4, 0x4e, 0xcf, 0x6a, 0x63, 0x87, 0x8d, 0xcb,
|
0xf5, 0xa2, 0xa0, 0x22, 0xb1, 0x2b, 0xb8, 0x21, 0xa4, 0x6e, 0xd7, 0x6a, 0x63, 0x87, 0x89, 0xcb,
|
||||||
0xe9, 0x24, 0x24, 0xcb, 0xb1, 0x37, 0xad, 0x55, 0xd7, 0x6b, 0xbc, 0x9b, 0xa2, 0xbc, 0xf1, 0x03,
|
0x6a, 0x25, 0xa4, 0x91, 0x9b, 0x4c, 0x5b, 0xab, 0xae, 0xc7, 0x78, 0xc6, 0x45, 0xb9, 0xe3, 0x01,
|
||||||
0x78, 0xe1, 0x95, 0x9f, 0xc1, 0x33, 0xff, 0x80, 0x3f, 0x85, 0xbc, 0xb6, 0xd3, 0xb4, 0x71, 0xd3,
|
0xb8, 0xe1, 0x96, 0x2b, 0x9e, 0x81, 0x57, 0xe2, 0x45, 0x90, 0xc7, 0x76, 0xd6, 0x6d, 0xdc, 0xb4,
|
||||||
0x22, 0xf1, 0x94, 0xcc, 0x37, 0x3b, 0x33, 0xbb, 0xf3, 0xcd, 0x37, 0x06, 0x35, 0x9e, 0xb3, 0x2b,
|
0x48, 0x7b, 0x95, 0x9c, 0x6f, 0xce, 0x39, 0x33, 0xe7, 0xe7, 0xfb, 0x0c, 0x5a, 0x18, 0xf3, 0x6b,
|
||||||
0x27, 0xa2, 0x3c, 0x98, 0x05, 0x9e, 0xcb, 0x03, 0x1a, 0xb1, 0x5e, 0x9c, 0x50, 0x4e, 0x51, 0x5d,
|
0x12, 0x30, 0xe1, 0x5d, 0x7a, 0x13, 0x57, 0x78, 0x2c, 0xe0, 0x07, 0x61, 0xc4, 0x04, 0x43, 0x75,
|
||||||
0xfc, 0x4c, 0xe7, 0x33, 0xed, 0xef, 0x2a, 0x7c, 0x32, 0x9e, 0xb3, 0x2b, 0x73, 0xe5, 0x14, 0x26,
|
0xf9, 0x73, 0x11, 0x5f, 0xea, 0x7f, 0xaf, 0xc0, 0xc7, 0xa3, 0x98, 0x5f, 0x5b, 0x05, 0x2f, 0x4c,
|
||||||
0x97, 0x01, 0xe3, 0x89, 0xf8, 0x8f, 0x2c, 0x00, 0x4e, 0xaf, 0x49, 0xe4, 0xf0, 0x45, 0x4c, 0x54,
|
0xaf, 0x3c, 0x2e, 0x22, 0xf9, 0x1f, 0xd9, 0x00, 0x82, 0xdd, 0xd0, 0x80, 0x88, 0x59, 0x48, 0x35,
|
||||||
0xa9, 0x23, 0x75, 0xdb, 0xc7, 0x5f, 0xf7, 0x8a, 0xf8, 0xde, 0xa6, 0xd8, 0x9e, 0x9d, 0x06, 0xda,
|
0xa5, 0xab, 0xf4, 0xda, 0x87, 0x5f, 0x1f, 0xe4, 0xf1, 0x07, 0xcb, 0x62, 0x0f, 0x9c, 0x24, 0xd0,
|
||||||
0x8b, 0x98, 0xe0, 0x06, 0x2f, 0xfe, 0xa2, 0xcf, 0xa0, 0xe5, 0x93, 0xdb, 0xc0, 0x23, 0x8e, 0xc0,
|
0x99, 0x85, 0x14, 0x37, 0x44, 0xfe, 0x17, 0x7d, 0x0a, 0xad, 0x29, 0xbd, 0xf3, 0x26, 0x94, 0x48,
|
||||||
0x54, 0xb9, 0x23, 0x75, 0x1b, 0xb8, 0x99, 0x61, 0x22, 0x02, 0x7d, 0x09, 0x3b, 0x41, 0xc4, 0xb8,
|
0x4c, 0x53, 0xbb, 0x4a, 0xaf, 0x81, 0x9b, 0x29, 0x26, 0x23, 0xd0, 0x97, 0xb0, 0xee, 0x05, 0x5c,
|
||||||
0x1b, 0x86, 0x22, 0x8f, 0x13, 0xf8, 0x6a, 0x45, 0x9c, 0x6a, 0xaf, 0xc2, 0x86, 0x9f, 0xe6, 0x72,
|
0xb8, 0xbe, 0x2f, 0xf3, 0x10, 0x6f, 0xaa, 0x55, 0xa4, 0x57, 0xbb, 0x08, 0x9b, 0xd3, 0x24, 0x97,
|
||||||
0x3d, 0x8f, 0x30, 0x96, 0xe7, 0xaa, 0x66, 0xb9, 0x32, 0x2c, 0xcb, 0xa5, 0x42, 0x8d, 0x44, 0xee,
|
0x3b, 0x99, 0x50, 0xce, 0xb3, 0x5c, 0xd5, 0x34, 0x57, 0x8a, 0xa5, 0xb9, 0x34, 0xa8, 0xd1, 0xc0,
|
||||||
0x34, 0x24, 0xbe, 0xba, 0xd5, 0x91, 0xba, 0x75, 0x5c, 0x98, 0xa9, 0xe7, 0x96, 0x24, 0x2c, 0xa0,
|
0xbd, 0xf0, 0xe9, 0x54, 0x5b, 0xe9, 0x2a, 0xbd, 0x3a, 0xce, 0xcd, 0xe4, 0xe4, 0x8e, 0x46, 0xdc,
|
||||||
0x91, 0xba, 0xdd, 0x91, 0xba, 0x55, 0x5c, 0x98, 0xa8, 0x0b, 0x8a, 0x1b, 0x86, 0xf4, 0x57, 0xe2,
|
0x63, 0x81, 0xb6, 0xda, 0x55, 0x7a, 0x55, 0x9c, 0x9b, 0xa8, 0x07, 0x1d, 0xd7, 0xf7, 0xd9, 0x6f,
|
||||||
0x3b, 0xd7, 0x64, 0xe1, 0x84, 0x01, 0xe3, 0x6a, 0xad, 0x53, 0xe9, 0xb6, 0x70, 0x3b, 0xc7, 0xcf,
|
0x74, 0x4a, 0x6e, 0xe8, 0x8c, 0xf8, 0x1e, 0x17, 0x5a, 0xad, 0x5b, 0xe9, 0xb5, 0x70, 0x3b, 0xc3,
|
||||||
0xc8, 0xe2, 0x3c, 0x60, 0x1c, 0x1d, 0xc1, 0xee, 0x34, 0xa4, 0xde, 0x35, 0xf1, 0x1d, 0xef, 0xca,
|
0x4f, 0xe9, 0xec, 0xcc, 0xe3, 0x02, 0xed, 0xc3, 0xc6, 0x85, 0xcf, 0x26, 0x37, 0x74, 0x4a, 0x26,
|
||||||
0xe5, 0xd9, 0xd1, 0xba, 0x38, 0xba, 0x93, 0x3b, 0x06, 0x57, 0x2e, 0x17, 0x67, 0x5f, 0x01, 0xcc,
|
0xd7, 0xae, 0x48, 0x5d, 0xeb, 0xd2, 0x75, 0x3d, 0x3b, 0x18, 0x5c, 0xbb, 0x42, 0xfa, 0xbe, 0x00,
|
||||||
0xa3, 0x44, 0xf4, 0x87, 0x24, 0x6a, 0x43, 0x5c, 0x66, 0x05, 0x41, 0x7b, 0xb0, 0x75, 0x99, 0xb8,
|
0x88, 0x83, 0x48, 0xf6, 0x87, 0x46, 0x5a, 0x43, 0x3e, 0xa6, 0x80, 0xa0, 0x4d, 0x58, 0xb9, 0x8a,
|
||||||
0x11, 0x57, 0xa1, 0x23, 0x75, 0x5b, 0x38, 0x33, 0xd0, 0x6b, 0x50, 0x45, 0x4d, 0x67, 0x96, 0xd0,
|
0xdc, 0x40, 0x68, 0xd0, 0x55, 0x7a, 0x2d, 0x9c, 0x1a, 0xe8, 0x25, 0x68, 0xf2, 0x4e, 0x72, 0x19,
|
||||||
0x1b, 0xc7, 0xa3, 0x11, 0x77, 0x3d, 0xce, 0x1c, 0x1a, 0x85, 0x0b, 0xb5, 0x29, 0x72, 0xec, 0x0b,
|
0xb1, 0x5b, 0x32, 0x61, 0x81, 0x70, 0x27, 0x82, 0x13, 0x16, 0xf8, 0x33, 0xad, 0x29, 0x73, 0x6c,
|
||||||
0xff, 0x30, 0xa1, 0x37, 0x83, 0xdc, 0x6b, 0x45, 0xe1, 0x02, 0x7d, 0x0c, 0x0d, 0x37, 0x8e, 0x1c,
|
0xc9, 0xf3, 0xe3, 0x88, 0xdd, 0x0e, 0xb2, 0x53, 0x3b, 0xf0, 0x67, 0xe8, 0x23, 0x68, 0xb8, 0x61,
|
||||||
0x4e, 0xe3, 0xc0, 0x53, 0x5b, 0xa2, 0x31, 0x75, 0x37, 0x8e, 0xec, 0xd4, 0xd6, 0x86, 0xd0, 0x58,
|
0x40, 0x04, 0x0b, 0xbd, 0x89, 0xd6, 0x92, 0x8d, 0xa9, 0xbb, 0x61, 0xe0, 0x24, 0x36, 0xfa, 0x02,
|
||||||
0x92, 0x83, 0x0e, 0x00, 0x5d, 0x98, 0x67, 0xa6, 0xf5, 0xce, 0x74, 0x6c, 0xeb, 0x4c, 0x37, 0x1d,
|
0xda, 0xf2, 0x79, 0xe4, 0x96, 0x06, 0x72, 0x31, 0xb4, 0x35, 0x99, 0x6b, 0x4d, 0xa2, 0xc3, 0x0c,
|
||||||
0xfb, 0xfd, 0x58, 0x57, 0x3e, 0x40, 0x1f, 0x42, 0xa3, 0x3f, 0xce, 0x31, 0x45, 0x42, 0x08, 0xda,
|
0x44, 0xdf, 0xc3, 0x6e, 0xde, 0x88, 0xdc, 0xb1, 0x50, 0x67, 0x5b, 0xd6, 0xb9, 0x93, 0x79, 0xe4,
|
||||||
0x43, 0x03, 0xeb, 0x3f, 0xf4, 0x27, 0x7a, 0x8e, 0xc9, 0xda, 0x5f, 0x32, 0x7c, 0xb1, 0x69, 0x04,
|
0x41, 0x79, 0xbd, 0xfa, 0x31, 0x34, 0xe6, 0x0b, 0x80, 0xb6, 0x01, 0x9d, 0x5b, 0xa7, 0x96, 0xfd,
|
||||||
0x30, 0x61, 0x31, 0x8d, 0x18, 0x49, 0x9b, 0xcd, 0xe6, 0x82, 0x16, 0x31, 0x43, 0x75, 0x5c, 0x98,
|
0xc6, 0x22, 0x8e, 0x7d, 0x6a, 0x58, 0xc4, 0x79, 0x3b, 0x32, 0x3a, 0x1f, 0xa0, 0x35, 0x68, 0xf4,
|
||||||
0xc8, 0x84, 0x2d, 0x92, 0x24, 0x34, 0x11, 0x83, 0xd0, 0x3e, 0x7e, 0xf3, 0xbc, 0xd9, 0x2a, 0x12,
|
0x47, 0x19, 0xd6, 0x51, 0x10, 0x82, 0xf6, 0xb1, 0x89, 0x8d, 0x1f, 0xfb, 0x63, 0x23, 0xc3, 0x54,
|
||||||
0xf7, 0xf4, 0x34, 0x56, 0xcc, 0x58, 0x96, 0x06, 0x1d, 0x02, 0x24, 0xe4, 0x97, 0x39, 0x61, 0xbc,
|
0xfd, 0x1f, 0x15, 0x3e, 0x5f, 0xb6, 0x66, 0x98, 0xf2, 0x90, 0x05, 0x9c, 0x26, 0x03, 0xe5, 0xb1,
|
||||||
0x98, 0x9b, 0x16, 0x6e, 0xe4, 0x88, 0xe1, 0x6b, 0xbf, 0x49, 0xd0, 0x58, 0xc6, 0xac, 0x3e, 0x5d,
|
0x1c, 0xbd, 0xdc, 0xd3, 0x3a, 0xce, 0x4d, 0x64, 0xc1, 0x0a, 0x8d, 0x22, 0x16, 0xc9, 0x65, 0x6b,
|
||||||
0xc7, 0xd8, 0xc2, 0xc5, 0xd3, 0xf7, 0x61, 0x77, 0xd4, 0x3f, 0x1f, 0x5a, 0x78, 0xa4, 0x9f, 0x38,
|
0x1f, 0xbe, 0x7a, 0xde, 0xfe, 0xe6, 0x89, 0x0f, 0x8c, 0x24, 0x56, 0xee, 0x71, 0x9a, 0x06, 0xed,
|
||||||
0x23, 0x7d, 0x32, 0xe9, 0x9f, 0xea, 0x8a, 0x84, 0xf6, 0x40, 0xf9, 0x49, 0xc7, 0x13, 0xc3, 0x32,
|
0x01, 0x44, 0xf4, 0xd7, 0x98, 0x72, 0x91, 0xef, 0x66, 0x0b, 0x37, 0x32, 0xc4, 0x9c, 0xea, 0xbf,
|
||||||
0x9d, 0x91, 0x31, 0x19, 0xf5, 0xed, 0xc1, 0x5b, 0x45, 0x46, 0x2f, 0xe1, 0xe0, 0xc2, 0x9c, 0x5c,
|
0x2b, 0xd0, 0x98, 0xc7, 0x14, 0x4b, 0x37, 0x30, 0xb6, 0x71, 0x5e, 0xfa, 0x16, 0x6c, 0x0c, 0xfb,
|
||||||
0x8c, 0xc7, 0x16, 0xb6, 0xf5, 0x93, 0xd5, 0x1e, 0x56, 0xd2, 0xa6, 0x19, 0xa6, 0xad, 0x63, 0xb3,
|
0x67, 0xc7, 0x36, 0x1e, 0x1a, 0x47, 0x64, 0x68, 0x8c, 0xc7, 0xfd, 0x13, 0xa3, 0xa3, 0xa0, 0x4d,
|
||||||
0x7f, 0x9e, 0x55, 0x50, 0xaa, 0xda, 0x1c, 0xd4, 0x9c, 0xa9, 0x01, 0xf5, 0x49, 0xdf, 0xbf, 0x25,
|
0xe8, 0xfc, 0x6c, 0xe0, 0xb1, 0x69, 0x5b, 0x64, 0x68, 0x8e, 0x87, 0x7d, 0x67, 0xf0, 0xba, 0xa3,
|
||||||
0x09, 0x0f, 0x18, 0xb9, 0x21, 0x11, 0x47, 0xef, 0xe1, 0x60, 0x4d, 0xb5, 0x4e, 0x10, 0xcd, 0xa8,
|
0xa2, 0x5d, 0xd8, 0x3e, 0xb7, 0xc6, 0xe7, 0xa3, 0x91, 0x8d, 0x1d, 0xe3, 0xa8, 0xd8, 0xc3, 0x4a,
|
||||||
0x2a, 0x75, 0x2a, 0xdd, 0xe6, 0xf1, 0xe7, 0x8f, 0xb7, 0xe7, 0xc7, 0x39, 0x49, 0x16, 0x46, 0x34,
|
0xd2, 0x34, 0xd3, 0x72, 0x0c, 0x6c, 0xf5, 0xcf, 0xd2, 0x1b, 0x3a, 0x55, 0x3d, 0x06, 0x2d, 0xdb,
|
||||||
0xa3, 0x78, 0x2f, 0x7e, 0xe0, 0x4a, 0x51, 0xed, 0x0d, 0xec, 0x97, 0x86, 0xa0, 0x4f, 0xa1, 0x19,
|
0x86, 0x01, 0x9b, 0xd2, 0xfe, 0xf4, 0x8e, 0x46, 0xc2, 0xe3, 0x34, 0x99, 0x22, 0x7a, 0x0b, 0xdb,
|
||||||
0xcf, 0xa7, 0x61, 0xe0, 0xa5, 0xd3, 0xce, 0x44, 0xa1, 0x16, 0x86, 0x0c, 0x3a, 0x23, 0x0b, 0xa6,
|
0x0b, 0xca, 0x40, 0xbc, 0xe0, 0x92, 0x69, 0x4a, 0xb7, 0xd2, 0x6b, 0x1e, 0x7e, 0xf6, 0x78, 0x7b,
|
||||||
0xfd, 0x2e, 0xc3, 0x47, 0x8f, 0x56, 0x5b, 0x13, 0xa1, 0xb4, 0x2e, 0xc2, 0x12, 0x41, 0xcb, 0xa5,
|
0x7e, 0x8a, 0x69, 0x34, 0x33, 0x83, 0x4b, 0x86, 0x37, 0xc3, 0x07, 0x47, 0x09, 0xaa, 0xbf, 0x82,
|
||||||
0x82, 0x3e, 0x04, 0xb8, 0xbb, 0x4a, 0x41, 0xde, 0xf2, 0x26, 0xa5, 0xc2, 0xac, 0x96, 0x0a, 0x73,
|
0xad, 0xd2, 0x10, 0xf4, 0x09, 0x34, 0xc3, 0xf8, 0xc2, 0xf7, 0x26, 0x09, 0xa3, 0xb8, 0xbc, 0xa8,
|
||||||
0x29, 0xa6, 0xad, 0x55, 0x31, 0x3d, 0x2e, 0xf9, 0x23, 0xd8, 0x65, 0x24, 0xb9, 0x25, 0x89, 0xb3,
|
0x85, 0x21, 0x85, 0x4e, 0xe9, 0x8c, 0xeb, 0x7f, 0xa8, 0xf0, 0xe1, 0xa3, 0xb7, 0x2d, 0x10, 0x5d,
|
||||||
0x52, 0xbf, 0x26, 0x62, 0x77, 0x32, 0xc7, 0xb8, 0xb8, 0x85, 0xf6, 0x87, 0x04, 0x87, 0xa5, 0xed,
|
0x59, 0x24, 0x7a, 0x89, 0x68, 0xa8, 0xa5, 0xa2, 0xb1, 0x07, 0xf0, 0xee, 0x29, 0xf9, 0xf0, 0xe6,
|
||||||
0x58, 0x4e, 0xfb, 0x6b, 0xa8, 0xfe, 0x57, 0xce, 0x44, 0x40, 0xfa, 0xfe, 0x1b, 0xc2, 0x98, 0x7b,
|
0x2f, 0x29, 0x25, 0x7f, 0xb5, 0x94, 0xfc, 0x73, 0xc2, 0xae, 0x14, 0x09, 0xfb, 0xb8, 0xac, 0xec,
|
||||||
0x49, 0x8a, 0x1e, 0xb5, 0x70, 0x23, 0x47, 0x0c, 0x7f, 0x55, 0x45, 0x95, 0x7b, 0x2a, 0xd2, 0xfe,
|
0xc3, 0x06, 0xa7, 0xd1, 0x1d, 0x8d, 0x48, 0xe1, 0xfe, 0x9a, 0x8c, 0x5d, 0x4f, 0x0f, 0x46, 0xf9,
|
||||||
0x91, 0x41, 0x79, 0x98, 0xfc, 0x39, 0xcc, 0xbc, 0x80, 0x9a, 0x58, 0x5c, 0xcb, 0x6a, 0xdb, 0xa9,
|
0x2b, 0xf4, 0x3f, 0x15, 0xd8, 0x2b, 0x6d, 0xc7, 0x7c, 0xdb, 0x5f, 0x42, 0xf5, 0xff, 0xce, 0x4c,
|
||||||
0xf9, 0x34, 0x13, 0x25, 0x8c, 0x56, 0x4b, 0x19, 0x55, 0xa1, 0x96, 0xdf, 0x3f, 0xa7, 0xa2, 0x30,
|
0x06, 0x24, 0xf5, 0xdf, 0x52, 0xce, 0xdd, 0x2b, 0x9a, 0xf7, 0xa8, 0x85, 0x1b, 0x19, 0x62, 0x4e,
|
||||||
0xd1, 0x00, 0xaa, 0xe2, 0x9b, 0xb2, 0x2d, 0x74, 0xff, 0xd5, 0xe3, 0x4d, 0x5a, 0x03, 0x84, 0xdc,
|
0x8b, 0x2c, 0xaa, 0xdc, 0x63, 0x91, 0xfe, 0xaf, 0x0a, 0x9d, 0x87, 0xc9, 0x9f, 0x33, 0x99, 0x1d,
|
||||||
0x45, 0xb0, 0x66, 0xc3, 0x5e, 0x99, 0x17, 0x69, 0xf0, 0xaa, 0x10, 0xf6, 0xf8, 0x62, 0xf2, 0xd6,
|
0xa8, 0x49, 0xd1, 0x98, 0xdf, 0xb6, 0x9a, 0x98, 0x4f, 0x4f, 0xa2, 0x64, 0xa2, 0xd5, 0xd2, 0x89,
|
||||||
0x31, 0x2d, 0xdb, 0x18, 0x1a, 0x83, 0xbe, 0x9d, 0x6a, 0x37, 0x17, 0x79, 0x13, 0x6a, 0x77, 0xd2,
|
0x6a, 0x50, 0xcb, 0xde, 0x9f, 0x8d, 0x22, 0x37, 0xd1, 0x00, 0xaa, 0xf2, 0xbb, 0xb5, 0x2a, 0x79,
|
||||||
0x16, 0x86, 0x99, 0xba, 0x15, 0x59, 0x8b, 0xe1, 0xc5, 0xfa, 0xf2, 0x11, 0x1b, 0x04, 0x7d, 0x0b,
|
0xff, 0xd5, 0xe3, 0x4d, 0x5a, 0x00, 0x24, 0xdd, 0x65, 0x30, 0xda, 0x86, 0x55, 0x37, 0x16, 0xd7,
|
||||||
0xf5, 0x7c, 0x99, 0xb0, 0x9c, 0xde, 0x97, 0x1b, 0x36, 0xd6, 0xf2, 0xec, 0x13, 0xcc, 0x6a, 0x7f,
|
0x2c, 0xca, 0x86, 0x95, 0x59, 0xba, 0x03, 0x9b, 0x65, 0x51, 0x48, 0x87, 0x17, 0x39, 0xe1, 0x47,
|
||||||
0xca, 0x70, 0xb0, 0x5e, 0x32, 0xa6, 0x09, 0xdf, 0xb0, 0x3a, 0xbf, 0xbf, 0xbf, 0x3a, 0x8f, 0x36,
|
0xe7, 0xe3, 0xd7, 0xc4, 0xb2, 0x1d, 0xf3, 0xd8, 0x1c, 0xf4, 0x9d, 0x84, 0xd3, 0x19, 0xf9, 0x9b,
|
||||||
0xad, 0xce, 0x34, 0x55, 0xe9, 0xb2, 0xfc, 0x3f, 0x58, 0xd6, 0x7e, 0x7e, 0xce, 0x52, 0xdd, 0x81,
|
0x50, 0x7b, 0x47, 0x79, 0x69, 0x58, 0xc9, 0x71, 0x47, 0xd5, 0x43, 0xd8, 0x59, 0x14, 0x25, 0xa9,
|
||||||
0xe6, 0x3b, 0x6c, 0x99, 0xa7, 0xab, 0x5f, 0x94, 0x07, 0xcb, 0x51, 0x4e, 0x31, 0xd3, 0xb2, 0x1d,
|
0x2c, 0xe8, 0x5b, 0xa8, 0x67, 0x22, 0xc3, 0xb3, 0xb1, 0xef, 0x2e, 0x51, 0xb2, 0xb9, 0xef, 0x13,
|
||||||
0xac, 0x9f, 0x1a, 0x13, 0x5b, 0xc7, 0xfa, 0x89, 0x52, 0x49, 0x17, 0xe6, 0xfa, 0x83, 0x72, 0xa9,
|
0x13, 0xd7, 0xff, 0x52, 0x61, 0x7b, 0xf1, 0xca, 0x90, 0x45, 0x62, 0x89, 0xa4, 0xfe, 0x70, 0x5f,
|
||||||
0xdd, 0xef, 0xab, 0xf4, 0x50, 0x31, 0xdf, 0x41, 0x2d, 0x11, 0x6f, 0x67, 0xaa, 0x2c, 0xd8, 0xea,
|
0x52, 0xf7, 0x97, 0x49, 0x6a, 0x92, 0xaa, 0x54, 0x44, 0xdf, 0xc7, 0xf4, 0xf5, 0x5f, 0x9e, 0x23,
|
||||||
0x3c, 0xd5, 0x24, 0x5c, 0x04, 0x4c, 0xb7, 0xc5, 0xc9, 0x6f, 0xfe, 0x0d, 0x00, 0x00, 0xff, 0xff,
|
0xb6, 0xeb, 0xd0, 0x7c, 0x83, 0x6d, 0xeb, 0xa4, 0xf8, 0xa5, 0x79, 0x20, 0x9a, 0x6a, 0x82, 0x59,
|
||||||
0xff, 0x42, 0x7f, 0xee, 0x48, 0x09, 0x00, 0x00,
|
0xb6, 0x43, 0xb0, 0x71, 0x62, 0x8e, 0x1d, 0x03, 0x1b, 0x47, 0x9d, 0x4a, 0x22, 0xa4, 0x8b, 0x05,
|
||||||
|
0x65, 0x14, 0xbc, 0xdf, 0x57, 0xe5, 0x21, 0x93, 0xbe, 0x83, 0x5a, 0x24, 0x6b, 0xe7, 0x9a, 0x2a,
|
||||||
|
0xa7, 0xd5, 0x7d, 0xaa, 0x49, 0x38, 0x0f, 0xb8, 0x58, 0x95, 0x9e, 0xdf, 0xfc, 0x17, 0x00, 0x00,
|
||||||
|
0xff, 0xff, 0xd4, 0x90, 0x1f, 0x72, 0xc4, 0x09, 0x00, 0x00,
|
||||||
}
|
}
|
||||||
|
|
|
@ -20,6 +20,8 @@ message PushNotificationRegistration {
|
||||||
bytes grant = 10;
|
bytes grant = 10;
|
||||||
bool allow_from_contacts_only = 11;
|
bool allow_from_contacts_only = 11;
|
||||||
string apn_topic = 12;
|
string apn_topic = 12;
|
||||||
|
bool block_mentions = 13;
|
||||||
|
repeated bytes allowed_mentions_chat_list = 14;
|
||||||
}
|
}
|
||||||
|
|
||||||
message PushNotificationRegistrationResponse {
|
message PushNotificationRegistrationResponse {
|
||||||
|
@ -72,6 +74,7 @@ message PushNotification {
|
||||||
MESSAGE = 1;
|
MESSAGE = 1;
|
||||||
MENTION = 2;
|
MENTION = 2;
|
||||||
}
|
}
|
||||||
|
bytes author = 7;
|
||||||
}
|
}
|
||||||
|
|
||||||
message PushNotificationRequest {
|
message PushNotificationRequest {
|
||||||
|
|
|
@ -641,168 +641,6 @@ func (s *MessengerPushNotificationSuite) TestReceivePushNotificationRetries() {
|
||||||
s.Require().NoError(server.Shutdown())
|
s.Require().NoError(server.Shutdown())
|
||||||
}
|
}
|
||||||
|
|
||||||
// Here bob acts as his own server
|
|
||||||
func (s *MessengerPushNotificationSuite) TestActAsYourOwnPushNotificationServer() {
|
|
||||||
bob1 := s.m
|
|
||||||
server := s.newPushNotificationServer(s.shh, s.m.identity)
|
|
||||||
bob2 := server
|
|
||||||
alice := s.newMessenger(s.shh)
|
|
||||||
// start alice and enable sending push notifications
|
|
||||||
s.Require().NoError(alice.Start())
|
|
||||||
s.Require().NoError(alice.EnableSendingPushNotifications())
|
|
||||||
bobInstallationIDs := []string{bob1.installationID, bob2.installationID}
|
|
||||||
|
|
||||||
// Register bob1
|
|
||||||
err := bob1.AddPushNotificationsServer(context.Background(), &server.identity.PublicKey, pushnotificationclient.ServerTypeCustom)
|
|
||||||
s.Require().NoError(err)
|
|
||||||
|
|
||||||
err = bob1.RegisterForPushNotifications(context.Background(), bob1DeviceToken, testAPNTopic, protobuf.PushNotificationRegistration_APN_TOKEN)
|
|
||||||
|
|
||||||
// Pull servers and check we registered
|
|
||||||
err = tt.RetryWithBackOff(func() error {
|
|
||||||
_, err = server.RetrieveAll()
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
_, err = bob1.RetrieveAll()
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
registered, err := bob1.RegisteredForPushNotifications()
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
if !registered {
|
|
||||||
return errors.New("not registered")
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
})
|
|
||||||
// Make sure we receive it
|
|
||||||
s.Require().NoError(err)
|
|
||||||
bob1Servers, err := bob1.GetPushNotificationsServers()
|
|
||||||
s.Require().NoError(err)
|
|
||||||
|
|
||||||
// Register bob2
|
|
||||||
err = bob2.AddPushNotificationsServer(context.Background(), &server.identity.PublicKey, pushnotificationclient.ServerTypeCustom)
|
|
||||||
s.Require().NoError(err)
|
|
||||||
|
|
||||||
err = bob2.RegisterForPushNotifications(context.Background(), bob2DeviceToken, testAPNTopic, protobuf.PushNotificationRegistration_APN_TOKEN)
|
|
||||||
s.Require().NoError(err)
|
|
||||||
|
|
||||||
err = tt.RetryWithBackOff(func() error {
|
|
||||||
_, err = server.RetrieveAll()
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
_, err = bob2.RetrieveAll()
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
registered, err := bob2.RegisteredForPushNotifications()
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
if !registered {
|
|
||||||
return errors.New("not registered")
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
})
|
|
||||||
// Make sure we receive it
|
|
||||||
s.Require().NoError(err)
|
|
||||||
bob2Servers, err := bob2.GetPushNotificationsServers()
|
|
||||||
s.Require().NoError(err)
|
|
||||||
|
|
||||||
// Create one to one chat & send message
|
|
||||||
pkString := hex.EncodeToString(crypto.FromECDSAPub(&s.m.identity.PublicKey))
|
|
||||||
chat := CreateOneToOneChat(pkString, &s.m.identity.PublicKey, alice.transport)
|
|
||||||
s.Require().NoError(alice.SaveChat(&chat))
|
|
||||||
inputMessage := buildTestMessage(chat)
|
|
||||||
response, err := alice.SendChatMessage(context.Background(), inputMessage)
|
|
||||||
s.Require().NoError(err)
|
|
||||||
messageIDString := response.Messages[0].ID
|
|
||||||
messageID, err := hex.DecodeString(messageIDString[2:])
|
|
||||||
s.Require().NoError(err)
|
|
||||||
|
|
||||||
var info []*pushnotificationclient.PushNotificationInfo
|
|
||||||
err = tt.RetryWithBackOff(func() error {
|
|
||||||
_, err = server.RetrieveAll()
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
_, err = alice.RetrieveAll()
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
info, err = alice.pushNotificationClient.GetPushNotificationInfo(&bob1.identity.PublicKey, bobInstallationIDs)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
// Check we have replies for both bob1 and bob2
|
|
||||||
if len(info) != 2 {
|
|
||||||
return errors.New("info not fetched")
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
|
|
||||||
})
|
|
||||||
|
|
||||||
s.Require().NoError(err)
|
|
||||||
|
|
||||||
// Check we have replies for both bob1 and bob2
|
|
||||||
var bob1Info, bob2Info *pushnotificationclient.PushNotificationInfo
|
|
||||||
|
|
||||||
if info[0].AccessToken == bob1Servers[0].AccessToken {
|
|
||||||
bob1Info = info[0]
|
|
||||||
bob2Info = info[1]
|
|
||||||
} else {
|
|
||||||
bob2Info = info[0]
|
|
||||||
bob1Info = info[1]
|
|
||||||
}
|
|
||||||
|
|
||||||
s.Require().NotNil(bob1Info)
|
|
||||||
s.Require().Equal(bob1.installationID, bob1Info.InstallationID)
|
|
||||||
s.Require().Equal(bob1Servers[0].AccessToken, bob1Info.AccessToken)
|
|
||||||
s.Require().Equal(&bob1.identity.PublicKey, bob1Info.PublicKey)
|
|
||||||
|
|
||||||
s.Require().NotNil(bob2Info)
|
|
||||||
s.Require().Equal(bob2.installationID, bob2Info.InstallationID)
|
|
||||||
s.Require().Equal(bob2Servers[0].AccessToken, bob2Info.AccessToken)
|
|
||||||
s.Require().Equal(&bob2.identity.PublicKey, bob2Info.PublicKey)
|
|
||||||
|
|
||||||
retrievedNotificationInfo, err := alice.pushNotificationClient.GetPushNotificationInfo(&bob1.identity.PublicKey, bobInstallationIDs)
|
|
||||||
|
|
||||||
s.Require().NoError(err)
|
|
||||||
s.Require().NotNil(retrievedNotificationInfo)
|
|
||||||
s.Require().Len(retrievedNotificationInfo, 2)
|
|
||||||
|
|
||||||
var sentNotification *pushnotificationclient.SentNotification
|
|
||||||
err = tt.RetryWithBackOff(func() error {
|
|
||||||
_, err = server.RetrieveAll()
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
_, err = alice.RetrieveAll()
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
sentNotification, err = alice.pushNotificationClient.GetSentNotification(common.HashPublicKey(&bob1.identity.PublicKey), bob1.installationID, messageID)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
if sentNotification == nil {
|
|
||||||
return errors.New("sent notification not found")
|
|
||||||
}
|
|
||||||
if !sentNotification.Success {
|
|
||||||
return errors.New("sent notification not successul")
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
})
|
|
||||||
s.Require().NoError(err)
|
|
||||||
s.Require().NoError(bob2.Shutdown())
|
|
||||||
s.Require().NoError(alice.Shutdown())
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *MessengerPushNotificationSuite) TestContactCode() {
|
func (s *MessengerPushNotificationSuite) TestContactCode() {
|
||||||
|
|
||||||
bob1 := s.m
|
bob1 := s.m
|
||||||
|
@ -853,3 +691,133 @@ func (s *MessengerPushNotificationSuite) TestContactCode() {
|
||||||
s.Require().NoError(alice.Shutdown())
|
s.Require().NoError(alice.Shutdown())
|
||||||
s.Require().NoError(server.Shutdown())
|
s.Require().NoError(server.Shutdown())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (s *MessengerPushNotificationSuite) TestReceivePushNotificationMention() {
|
||||||
|
|
||||||
|
bob := s.m
|
||||||
|
|
||||||
|
serverKey, err := crypto.GenerateKey()
|
||||||
|
s.Require().NoError(err)
|
||||||
|
server := s.newPushNotificationServer(s.shh, serverKey)
|
||||||
|
|
||||||
|
alice := s.newMessenger(s.shh)
|
||||||
|
// start alice and enable sending push notifications
|
||||||
|
s.Require().NoError(alice.Start())
|
||||||
|
s.Require().NoError(alice.EnableSendingPushNotifications())
|
||||||
|
bobInstallationIDs := []string{bob.installationID}
|
||||||
|
|
||||||
|
// Create public chat and join for both alice and bob
|
||||||
|
chat := CreatePublicChat("status", s.m.transport)
|
||||||
|
err = bob.SaveChat(&chat)
|
||||||
|
s.Require().NoError(err)
|
||||||
|
|
||||||
|
err = bob.Join(chat)
|
||||||
|
s.Require().NoError(err)
|
||||||
|
|
||||||
|
err = alice.SaveChat(&chat)
|
||||||
|
s.Require().NoError(err)
|
||||||
|
|
||||||
|
err = alice.Join(chat)
|
||||||
|
s.Require().NoError(err)
|
||||||
|
|
||||||
|
// Register bob
|
||||||
|
err = bob.AddPushNotificationsServer(context.Background(), &server.identity.PublicKey, pushnotificationclient.ServerTypeCustom)
|
||||||
|
s.Require().NoError(err)
|
||||||
|
|
||||||
|
err = bob.RegisterForPushNotifications(context.Background(), bob1DeviceToken, testAPNTopic, protobuf.PushNotificationRegistration_APN_TOKEN)
|
||||||
|
|
||||||
|
// Pull servers and check we registered
|
||||||
|
err = tt.RetryWithBackOff(func() error {
|
||||||
|
_, err = server.RetrieveAll()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
_, err = bob.RetrieveAll()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
registered, err := bob.RegisteredForPushNotifications()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if !registered {
|
||||||
|
return errors.New("not registered")
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
})
|
||||||
|
// Make sure we receive it
|
||||||
|
s.Require().NoError(err)
|
||||||
|
bobServers, err := bob.GetPushNotificationsServers()
|
||||||
|
s.Require().NoError(err)
|
||||||
|
|
||||||
|
inputMessage := buildTestMessage(chat)
|
||||||
|
// message contains a mention
|
||||||
|
inputMessage.Text = "Hey @" + types.EncodeHex(crypto.FromECDSAPub(&bob.identity.PublicKey))
|
||||||
|
response, err := alice.SendChatMessage(context.Background(), inputMessage)
|
||||||
|
s.Require().NoError(err)
|
||||||
|
messageIDString := response.Messages[0].ID
|
||||||
|
messageID, err := hex.DecodeString(messageIDString[2:])
|
||||||
|
s.Require().NoError(err)
|
||||||
|
|
||||||
|
var bobInfo []*pushnotificationclient.PushNotificationInfo
|
||||||
|
err = tt.RetryWithBackOff(func() error {
|
||||||
|
_, err = server.RetrieveAll()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
_, err = alice.RetrieveAll()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
bobInfo, err = alice.pushNotificationClient.GetPushNotificationInfo(&bob.identity.PublicKey, bobInstallationIDs)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
// Check we have replies for bob
|
||||||
|
if len(bobInfo) != 1 {
|
||||||
|
return errors.New("info not fetched")
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
|
||||||
|
})
|
||||||
|
|
||||||
|
s.Require().NoError(err)
|
||||||
|
|
||||||
|
s.Require().NotEmpty(bobInfo)
|
||||||
|
s.Require().Equal(bob.installationID, bobInfo[0].InstallationID)
|
||||||
|
s.Require().Equal(bobServers[0].AccessToken, bobInfo[0].AccessToken)
|
||||||
|
s.Require().Equal(&bob.identity.PublicKey, bobInfo[0].PublicKey)
|
||||||
|
|
||||||
|
retrievedNotificationInfo, err := alice.pushNotificationClient.GetPushNotificationInfo(&bob.identity.PublicKey, bobInstallationIDs)
|
||||||
|
|
||||||
|
s.Require().NoError(err)
|
||||||
|
s.Require().NotNil(retrievedNotificationInfo)
|
||||||
|
s.Require().Len(retrievedNotificationInfo, 1)
|
||||||
|
|
||||||
|
var sentNotification *pushnotificationclient.SentNotification
|
||||||
|
err = tt.RetryWithBackOff(func() error {
|
||||||
|
_, err = server.RetrieveAll()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
_, err = alice.RetrieveAll()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
sentNotification, err = alice.pushNotificationClient.GetSentNotification(common.HashPublicKey(&bob.identity.PublicKey), bob.installationID, messageID)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if sentNotification == nil {
|
||||||
|
return errors.New("sent notification not found")
|
||||||
|
}
|
||||||
|
if !sentNotification.Success {
|
||||||
|
return errors.New("sent notification not successul")
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
})
|
||||||
|
s.Require().NoError(err)
|
||||||
|
s.Require().NoError(alice.Shutdown())
|
||||||
|
s.Require().NoError(server.Shutdown())
|
||||||
|
}
|
||||||
|
|
|
@ -7,6 +7,7 @@ import (
|
||||||
"crypto/cipher"
|
"crypto/cipher"
|
||||||
"crypto/ecdsa"
|
"crypto/ecdsa"
|
||||||
"crypto/rand"
|
"crypto/rand"
|
||||||
|
"database/sql"
|
||||||
"encoding/hex"
|
"encoding/hex"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"errors"
|
"errors"
|
||||||
|
@ -47,6 +48,8 @@ import (
|
||||||
const encryptedPayloadKeyLength = 16
|
const encryptedPayloadKeyLength = 16
|
||||||
const accessTokenKeyLength = 16
|
const accessTokenKeyLength = 16
|
||||||
const staleQueryTimeInSeconds = 86400
|
const staleQueryTimeInSeconds = 86400
|
||||||
|
const mentionInstallationID = "mention"
|
||||||
|
const oneToOneChatIDLength = 132
|
||||||
|
|
||||||
// maxRegistrationRetries is the maximum number of attempts we do before giving up registering with a server
|
// maxRegistrationRetries is the maximum number of attempts we do before giving up registering with a server
|
||||||
const maxRegistrationRetries int64 = 12
|
const maxRegistrationRetries int64 = 12
|
||||||
|
@ -103,13 +106,21 @@ type PushNotificationInfo struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
type SentNotification struct {
|
type SentNotification struct {
|
||||||
PublicKey *ecdsa.PublicKey
|
PublicKey *ecdsa.PublicKey
|
||||||
InstallationID string
|
InstallationID string
|
||||||
LastTriedAt int64
|
LastTriedAt int64
|
||||||
RetryCount int64
|
RetryCount int64
|
||||||
MessageID []byte
|
MessageID []byte
|
||||||
Success bool
|
ChatID string
|
||||||
Error protobuf.PushNotificationReport_ErrorType
|
NotificationType protobuf.PushNotification_PushNotificationType
|
||||||
|
Success bool
|
||||||
|
Error protobuf.PushNotificationReport_ErrorType
|
||||||
|
}
|
||||||
|
|
||||||
|
type RegistrationOptions struct {
|
||||||
|
PublicChatIDs []string
|
||||||
|
MutedChatIDs []string
|
||||||
|
ContactIDs []*ecdsa.PublicKey
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *SentNotification) HashedPublicKey() []byte {
|
func (s *SentNotification) HashedPublicKey() []byte {
|
||||||
|
@ -128,6 +139,9 @@ type Config struct {
|
||||||
// only from contacts
|
// only from contacts
|
||||||
AllowFromContactsOnly bool
|
AllowFromContactsOnly bool
|
||||||
|
|
||||||
|
// BlockMentions indicates whether we should not receive notification for mentions
|
||||||
|
BlockMentions bool
|
||||||
|
|
||||||
// InstallationID is the installation-id for this device
|
// InstallationID is the installation-id for this device
|
||||||
InstallationID string
|
InstallationID string
|
||||||
|
|
||||||
|
@ -138,8 +152,13 @@ type Config struct {
|
||||||
DefaultServers []*ecdsa.PublicKey
|
DefaultServers []*ecdsa.PublicKey
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type MessagePersistence interface {
|
||||||
|
MessageByID(string) (*common.Message, error)
|
||||||
|
}
|
||||||
|
|
||||||
type Client struct {
|
type Client struct {
|
||||||
persistence *Persistence
|
persistence *Persistence
|
||||||
|
messagePersistence MessagePersistence
|
||||||
|
|
||||||
config *Config
|
config *Config
|
||||||
|
|
||||||
|
@ -176,13 +195,14 @@ type Client struct {
|
||||||
registrationSubscriptions []chan struct{}
|
registrationSubscriptions []chan struct{}
|
||||||
}
|
}
|
||||||
|
|
||||||
func New(persistence *Persistence, config *Config, processor *common.MessageProcessor) *Client {
|
func New(persistence *Persistence, config *Config, processor *common.MessageProcessor, messagePersistence MessagePersistence) *Client {
|
||||||
return &Client{
|
return &Client{
|
||||||
quit: make(chan struct{}),
|
quit: make(chan struct{}),
|
||||||
config: config,
|
config: config,
|
||||||
messageProcessor: processor,
|
messageProcessor: processor,
|
||||||
persistence: persistence,
|
messagePersistence: messagePersistence,
|
||||||
reader: rand.Reader,
|
persistence: persistence,
|
||||||
|
reader: rand.Reader,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -191,15 +211,12 @@ func (c *Client) Start() error {
|
||||||
return errors.New("can't start, missing message processor")
|
return errors.New("can't start, missing message processor")
|
||||||
}
|
}
|
||||||
|
|
||||||
c.config.Logger.Debug("starting push notification client", zap.Any("config", c.config))
|
|
||||||
|
|
||||||
err := c.loadLastPushNotificationRegistration()
|
err := c.loadLastPushNotificationRegistration()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
c.subscribeForSentMessages()
|
c.subscribeForMessageEvents()
|
||||||
c.subscribeForScheduledMessages()
|
|
||||||
|
|
||||||
// We start even if push notifications are disabled, as we might
|
// We start even if push notifications are disabled, as we might
|
||||||
// actually be sending an unregister message
|
// actually be sending an unregister message
|
||||||
|
@ -299,7 +316,7 @@ func (c *Client) GetServers() ([]*PushNotificationServer, error) {
|
||||||
return c.persistence.GetServers()
|
return c.persistence.GetServers()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Client) Reregister(contactIDs []*ecdsa.PublicKey, mutedChatIDs []string) error {
|
func (c *Client) Reregister(options *RegistrationOptions) error {
|
||||||
c.config.Logger.Debug("re-registering")
|
c.config.Logger.Debug("re-registering")
|
||||||
if len(c.deviceToken) == 0 {
|
if len(c.deviceToken) == 0 {
|
||||||
c.config.Logger.Info("no device token, not registering")
|
c.config.Logger.Info("no device token, not registering")
|
||||||
|
@ -311,7 +328,7 @@ func (c *Client) Reregister(contactIDs []*ecdsa.PublicKey, mutedChatIDs []string
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
return c.Register(c.deviceToken, c.apnTopic, c.tokenType, contactIDs, mutedChatIDs)
|
return c.Register(c.deviceToken, c.apnTopic, c.tokenType, options)
|
||||||
}
|
}
|
||||||
|
|
||||||
// pickDefaultServesr picks n servers at random
|
// pickDefaultServesr picks n servers at random
|
||||||
|
@ -333,7 +350,7 @@ func (c *Client) pickDefaultServers(servers []*ecdsa.PublicKey) []*ecdsa.PublicK
|
||||||
}
|
}
|
||||||
|
|
||||||
// Register registers with all the servers
|
// Register registers with all the servers
|
||||||
func (c *Client) Register(deviceToken, apnTopic string, tokenType protobuf.PushNotificationRegistration_TokenType, contactIDs []*ecdsa.PublicKey, mutedChatIDs []string) error {
|
func (c *Client) Register(deviceToken, apnTopic string, tokenType protobuf.PushNotificationRegistration_TokenType, options *RegistrationOptions) error {
|
||||||
// stop registration loop
|
// stop registration loop
|
||||||
c.stopRegistrationLoop()
|
c.stopRegistrationLoop()
|
||||||
|
|
||||||
|
@ -364,12 +381,12 @@ func (c *Client) Register(deviceToken, apnTopic string, tokenType protobuf.PushN
|
||||||
c.apnTopic = apnTopic
|
c.apnTopic = apnTopic
|
||||||
c.tokenType = tokenType
|
c.tokenType = tokenType
|
||||||
|
|
||||||
registration, err := c.buildPushNotificationRegistrationMessage(contactIDs, mutedChatIDs)
|
registration, err := c.buildPushNotificationRegistrationMessage(options)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
err = c.saveLastPushNotificationRegistration(registration, contactIDs)
|
err = c.saveLastPushNotificationRegistration(registration, options.ContactIDs)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -588,22 +605,42 @@ func (c *Client) DisableSending() {
|
||||||
c.config.SendEnabled = false
|
c.config.SendEnabled = false
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Client) EnablePushNotificationsFromContactsOnly(contactIDs []*ecdsa.PublicKey, mutedChatIDs []string) error {
|
func (c *Client) EnablePushNotificationsFromContactsOnly(options *RegistrationOptions) error {
|
||||||
c.config.Logger.Debug("enabling push notification from contacts only")
|
c.config.Logger.Debug("enabling push notification from contacts only")
|
||||||
c.config.AllowFromContactsOnly = true
|
c.config.AllowFromContactsOnly = true
|
||||||
if c.lastPushNotificationRegistration != nil && c.config.RemoteNotificationsEnabled {
|
if c.lastPushNotificationRegistration != nil && c.config.RemoteNotificationsEnabled {
|
||||||
c.config.Logger.Debug("re-registering after enabling push notifications from contacts only")
|
c.config.Logger.Debug("re-registering after enabling push notifications from contacts only")
|
||||||
return c.Register(c.deviceToken, c.apnTopic, c.tokenType, contactIDs, mutedChatIDs)
|
return c.Register(c.deviceToken, c.apnTopic, c.tokenType, options)
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Client) DisablePushNotificationsFromContactsOnly(contactIDs []*ecdsa.PublicKey, mutedChatIDs []string) error {
|
func (c *Client) DisablePushNotificationsFromContactsOnly(options *RegistrationOptions) error {
|
||||||
c.config.Logger.Debug("disabling push notification from contacts only")
|
c.config.Logger.Debug("disabling push notification from contacts only")
|
||||||
c.config.AllowFromContactsOnly = false
|
c.config.AllowFromContactsOnly = false
|
||||||
if c.lastPushNotificationRegistration != nil && c.config.RemoteNotificationsEnabled {
|
if c.lastPushNotificationRegistration != nil && c.config.RemoteNotificationsEnabled {
|
||||||
c.config.Logger.Debug("re-registering after disabling push notifications from contacts only")
|
c.config.Logger.Debug("re-registering after disabling push notifications from contacts only")
|
||||||
return c.Register(c.deviceToken, c.apnTopic, c.tokenType, contactIDs, mutedChatIDs)
|
return c.Register(c.deviceToken, c.apnTopic, c.tokenType, options)
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *Client) EnablePushNotificationsBlockMentions(options *RegistrationOptions) error {
|
||||||
|
c.config.Logger.Debug("disabling push notifications for mentions")
|
||||||
|
c.config.BlockMentions = true
|
||||||
|
if c.lastPushNotificationRegistration != nil && c.config.RemoteNotificationsEnabled {
|
||||||
|
c.config.Logger.Debug("re-registering after disabling push notifications for mentions")
|
||||||
|
return c.Register(c.deviceToken, c.apnTopic, c.tokenType, options)
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *Client) DisablePushNotificationsBlockMentions(options *RegistrationOptions) error {
|
||||||
|
c.config.Logger.Debug("enabling push notifications for mentions")
|
||||||
|
c.config.BlockMentions = false
|
||||||
|
if c.lastPushNotificationRegistration != nil && c.config.RemoteNotificationsEnabled {
|
||||||
|
c.config.Logger.Debug("re-registering after enabling push notifications for mentions")
|
||||||
|
return c.Register(c.deviceToken, c.apnTopic, c.tokenType, options)
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
@ -644,37 +681,21 @@ func (c *Client) generateSharedKey(publicKey *ecdsa.PublicKey) ([]byte, error) {
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
// subscribeForSentMessages subscribes for newly sent messages so we can check if we need to send a push notification
|
// subscribeForMessageEvents subscribes for newly sent/scheduled messages so we can check if we need to send a push notification
|
||||||
func (c *Client) subscribeForSentMessages() {
|
func (c *Client) subscribeForMessageEvents() {
|
||||||
go func() {
|
go func() {
|
||||||
c.config.Logger.Debug("subscribing for sent messages")
|
c.config.Logger.Debug("subscribing for message events")
|
||||||
subscription := c.messageProcessor.SubscribeToSentMessages()
|
sentMessagesSubscription := c.messageProcessor.SubscribeToSentMessages()
|
||||||
|
scheduledMessagesSubscription := c.messageProcessor.SubscribeToScheduledMessages()
|
||||||
for {
|
for {
|
||||||
select {
|
select {
|
||||||
case m, more := <-subscription:
|
// order is important, since both are asynchronous, we want to process
|
||||||
if !more {
|
// first scheduled messages, and after sent messages, otherwise we might
|
||||||
c.config.Logger.Debug("no more sent messages, quitting")
|
// have some race conditions.
|
||||||
return
|
// This does not completely rules them out, but reduced the window
|
||||||
}
|
// where it might happen, a single channel should be used
|
||||||
c.config.Logger.Debug("handling message sent")
|
// if this actually happens.
|
||||||
if err := c.handleMessageSent(m); err != nil {
|
case m, more := <-scheduledMessagesSubscription:
|
||||||
c.config.Logger.Error("failed to handle message", zap.Error(err))
|
|
||||||
}
|
|
||||||
case <-c.quit:
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}()
|
|
||||||
}
|
|
||||||
|
|
||||||
// subscribeForScheduledMessages subscribes for messages scheduler for dispatch
|
|
||||||
func (c *Client) subscribeForScheduledMessages() {
|
|
||||||
go func() {
|
|
||||||
c.config.Logger.Debug("subscribing for scheduled messages")
|
|
||||||
subscription := c.messageProcessor.SubscribeToScheduledMessages()
|
|
||||||
for {
|
|
||||||
select {
|
|
||||||
case m, more := <-subscription:
|
|
||||||
if !more {
|
if !more {
|
||||||
c.config.Logger.Debug("no more scheduled messages, quitting")
|
c.config.Logger.Debug("no more scheduled messages, quitting")
|
||||||
return
|
return
|
||||||
|
@ -683,6 +704,16 @@ func (c *Client) subscribeForScheduledMessages() {
|
||||||
if err := c.handleMessageScheduled(m); err != nil {
|
if err := c.handleMessageScheduled(m); err != nil {
|
||||||
c.config.Logger.Error("failed to handle message", zap.Error(err))
|
c.config.Logger.Error("failed to handle message", zap.Error(err))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
case m, more := <-sentMessagesSubscription:
|
||||||
|
if !more {
|
||||||
|
c.config.Logger.Debug("no more sent messages, quitting")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
c.config.Logger.Debug("handling message sent")
|
||||||
|
if err := c.handleMessageSent(m); err != nil {
|
||||||
|
c.config.Logger.Error("failed to handle message", zap.Error(err))
|
||||||
|
}
|
||||||
case <-c.quit:
|
case <-c.quit:
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
@ -785,10 +816,9 @@ func (c *Client) queryNotificationInfo(publicKey *ecdsa.PublicKey, force bool) e
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// handleMessageSent is called every time a message is sent. It will check if
|
// handleMessageSent is called every time a message is sent
|
||||||
// we need to notify on the message, and if so it will try to dispatch a push notification
|
|
||||||
// messages might be batched, if coming from datasync for example.
|
|
||||||
func (c *Client) handleMessageSent(sentMessage *common.SentMessage) error {
|
func (c *Client) handleMessageSent(sentMessage *common.SentMessage) error {
|
||||||
|
|
||||||
c.config.Logger.Debug("sent messages", zap.Any("messageIDs", sentMessage.MessageIDs))
|
c.config.Logger.Debug("sent messages", zap.Any("messageIDs", sentMessage.MessageIDs))
|
||||||
|
|
||||||
// Ignore if we are not sending notifications
|
// Ignore if we are not sending notifications
|
||||||
|
@ -797,6 +827,109 @@ func (c *Client) handleMessageSent(sentMessage *common.SentMessage) error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if sentMessage.PublicKey == nil {
|
||||||
|
return c.handlePublicMessageSent(sentMessage)
|
||||||
|
}
|
||||||
|
return c.handleDirectMessageSent(sentMessage)
|
||||||
|
}
|
||||||
|
|
||||||
|
// saving to the database might happen after we fetch the message, so we retry
|
||||||
|
// for a reasonable amount of time before giving up
|
||||||
|
func (c *Client) getMessage(messageID string) (*common.Message, error) {
|
||||||
|
retries := 0
|
||||||
|
for retries < 10 {
|
||||||
|
message, err := c.messagePersistence.MessageByID(messageID)
|
||||||
|
if err == sql.ErrNoRows {
|
||||||
|
retries++
|
||||||
|
time.Sleep(300 * time.Millisecond)
|
||||||
|
continue
|
||||||
|
} else if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return message, nil
|
||||||
|
}
|
||||||
|
return nil, sql.ErrNoRows
|
||||||
|
}
|
||||||
|
|
||||||
|
// handlePublicMessageSent handles public messages, we notify only on mentions
|
||||||
|
func (c *Client) handlePublicMessageSent(sentMessage *common.SentMessage) error {
|
||||||
|
// We always expect a single message, as we never batch them
|
||||||
|
if len(sentMessage.MessageIDs) != 1 {
|
||||||
|
return errors.New("batched public messages not handled")
|
||||||
|
}
|
||||||
|
|
||||||
|
messageID := sentMessage.MessageIDs[0]
|
||||||
|
c.config.Logger.Debug("handling public messages", zap.Binary("messageID", messageID))
|
||||||
|
tracked, err := c.persistence.TrackedMessage(messageID)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
if !tracked {
|
||||||
|
c.config.Logger.Debug("messageID not tracked, nothing to do", zap.Binary("messageID", messageID))
|
||||||
|
}
|
||||||
|
|
||||||
|
c.config.Logger.Debug("messageID tracked", zap.Binary("messageID", messageID))
|
||||||
|
|
||||||
|
message, err := c.getMessage(types.EncodeHex(messageID))
|
||||||
|
if err != nil {
|
||||||
|
c.config.Logger.Error("could not retrieve message", zap.Error(err))
|
||||||
|
}
|
||||||
|
|
||||||
|
// This might happen if the user deleted their messages for example
|
||||||
|
if message == nil {
|
||||||
|
c.config.Logger.Warn("message not retrieved")
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
c.config.Logger.Debug("message found", zap.Binary("messageID", messageID))
|
||||||
|
for _, pkString := range message.Mentions {
|
||||||
|
c.config.Logger.Debug("handling mention", zap.String("publickey", pkString))
|
||||||
|
pubkeyBytes, err := types.DecodeHex(pkString)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
publicKey, err := crypto.UnmarshalPubkey(pubkeyBytes)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// we use a synthetic installationID for mentions, as all devices need to be notified
|
||||||
|
shouldNotify, err := c.shouldNotifyOn(publicKey, mentionInstallationID, messageID)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
c.config.Logger.Debug("should no mention", zap.Any("publickey", shouldNotify))
|
||||||
|
// we send the notifications and return the info of the devices notified
|
||||||
|
infos, err := c.sendNotification(publicKey, nil, messageID, message.LocalChatID, protobuf.PushNotification_MENTION)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// mark message as sent so we don't notify again
|
||||||
|
for _, i := range infos {
|
||||||
|
c.config.Logger.Debug("marking as sent ", zap.Binary("mid", messageID), zap.String("id", i.InstallationID))
|
||||||
|
if err := c.notifiedOn(publicKey, i.InstallationID, messageID, message.LocalChatID, protobuf.PushNotification_MESSAGE); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// handleDirectMessageSent handles one to ones and private group chat messages
|
||||||
|
// It will check if we need to notify on the message, and if so it will try to
|
||||||
|
// dispatch a push notification messages might be batched, if coming
|
||||||
|
// from datasync for example.
|
||||||
|
func (c *Client) handleDirectMessageSent(sentMessage *common.SentMessage) error {
|
||||||
|
c.config.Logger.Debug("handling direct messages", zap.Any("messageIDs", sentMessage.MessageIDs))
|
||||||
|
|
||||||
publicKey := sentMessage.PublicKey
|
publicKey := sentMessage.PublicKey
|
||||||
|
|
||||||
// Collect the messageIDs we want to notify on
|
// Collect the messageIDs we want to notify on
|
||||||
|
@ -849,8 +982,27 @@ func (c *Client) handleMessageSent(sentMessage *common.SentMessage) error {
|
||||||
|
|
||||||
c.config.Logger.Debug("actionable messages", zap.Any("message-ids", trackedMessageIDs), zap.Any("installation-ids", installationIDs))
|
c.config.Logger.Debug("actionable messages", zap.Any("message-ids", trackedMessageIDs), zap.Any("installation-ids", installationIDs))
|
||||||
|
|
||||||
|
// Get message to check chatID. Again we use the first message for simplicity, but we should send one for each chatID. Messages though are very rarely batched.
|
||||||
|
message, err := c.getMessage(types.EncodeHex(trackedMessageIDs[0]))
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// This is not the prettiest.
|
||||||
|
// because chatIDs are asymettric, we need to check if it's a one-to-one message or a group chat message.
|
||||||
|
// to do that we fingerprint the chatID.
|
||||||
|
// If it's a public key, we use our own public key as chatID, which correspond to the chatID used by the other peer
|
||||||
|
// otherwise we use the group chat ID
|
||||||
|
var chatID string
|
||||||
|
if len(message.ChatId) == oneToOneChatIDLength {
|
||||||
|
chatID = types.EncodeHex(crypto.FromECDSAPub(&c.config.Identity.PublicKey))
|
||||||
|
} else {
|
||||||
|
// this is a group chat
|
||||||
|
chatID = message.ChatId
|
||||||
|
}
|
||||||
|
|
||||||
// we send the notifications and return the info of the devices notified
|
// we send the notifications and return the info of the devices notified
|
||||||
infos, err := c.sendNotification(publicKey, installationIDs, trackedMessageIDs[0])
|
infos, err := c.sendNotification(publicKey, installationIDs, trackedMessageIDs[0], chatID, protobuf.PushNotification_MESSAGE)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -860,7 +1012,7 @@ func (c *Client) handleMessageSent(sentMessage *common.SentMessage) error {
|
||||||
for _, messageID := range trackedMessageIDs {
|
for _, messageID := range trackedMessageIDs {
|
||||||
|
|
||||||
c.config.Logger.Debug("marking as sent ", zap.Binary("mid", messageID), zap.String("id", i.InstallationID))
|
c.config.Logger.Debug("marking as sent ", zap.Binary("mid", messageID), zap.String("id", i.InstallationID))
|
||||||
if err := c.notifiedOn(publicKey, i.InstallationID, messageID); err != nil {
|
if err := c.notifiedOn(publicKey, i.InstallationID, messageID, chatID, protobuf.PushNotification_MESSAGE); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -890,17 +1042,19 @@ func (c *Client) shouldNotifyOn(publicKey *ecdsa.PublicKey, installationID strin
|
||||||
return c.persistence.ShouldSendNotificationFor(publicKey, installationID, messageID)
|
return c.persistence.ShouldSendNotificationFor(publicKey, installationID, messageID)
|
||||||
}
|
}
|
||||||
|
|
||||||
// notifiedOn marks a combination of publickey/installationid/messageID as notified
|
// notifiedOn marks a combination of publickey/installationid/messageID/chatID/type as notified
|
||||||
func (c *Client) notifiedOn(publicKey *ecdsa.PublicKey, installationID string, messageID []byte) error {
|
func (c *Client) notifiedOn(publicKey *ecdsa.PublicKey, installationID string, messageID []byte, chatID string, notificationType protobuf.PushNotification_PushNotificationType) error {
|
||||||
return c.persistence.UpsertSentNotification(&SentNotification{
|
return c.persistence.UpsertSentNotification(&SentNotification{
|
||||||
PublicKey: publicKey,
|
PublicKey: publicKey,
|
||||||
LastTriedAt: time.Now().Unix(),
|
LastTriedAt: time.Now().Unix(),
|
||||||
InstallationID: installationID,
|
InstallationID: installationID,
|
||||||
MessageID: messageID,
|
MessageID: messageID,
|
||||||
|
ChatID: chatID,
|
||||||
|
NotificationType: notificationType,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Client) mutedChatIDsHashes(chatIDs []string) [][]byte {
|
func (c *Client) chatIDsHashes(chatIDs []string) [][]byte {
|
||||||
var mutedChatListHashes [][]byte
|
var mutedChatListHashes [][]byte
|
||||||
|
|
||||||
for _, chatID := range chatIDs {
|
for _, chatID := range chatIDs {
|
||||||
|
@ -979,26 +1133,27 @@ func (c *Client) getVersion() uint64 {
|
||||||
return c.lastPushNotificationRegistration.Version + 1
|
return c.lastPushNotificationRegistration.Version + 1
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Client) buildPushNotificationRegistrationMessage(contactIDs []*ecdsa.PublicKey, mutedChatIDs []string) (*protobuf.PushNotificationRegistration, error) {
|
func (c *Client) buildPushNotificationRegistrationMessage(options *RegistrationOptions) (*protobuf.PushNotificationRegistration, error) {
|
||||||
token := c.getToken(contactIDs)
|
token := c.getToken(options.ContactIDs)
|
||||||
allowedKeyList, err := c.allowedKeyList([]byte(token), contactIDs)
|
allowedKeyList, err := c.allowedKeyList([]byte(token), options.ContactIDs)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
options := &protobuf.PushNotificationRegistration{
|
return &protobuf.PushNotificationRegistration{
|
||||||
AccessToken: token,
|
AccessToken: token,
|
||||||
TokenType: c.tokenType,
|
TokenType: c.tokenType,
|
||||||
ApnTopic: c.apnTopic,
|
ApnTopic: c.apnTopic,
|
||||||
Version: c.getVersion(),
|
Version: c.getVersion(),
|
||||||
InstallationId: c.config.InstallationID,
|
InstallationId: c.config.InstallationID,
|
||||||
DeviceToken: c.deviceToken,
|
DeviceToken: c.deviceToken,
|
||||||
AllowFromContactsOnly: c.config.AllowFromContactsOnly,
|
AllowFromContactsOnly: c.config.AllowFromContactsOnly,
|
||||||
Enabled: c.config.RemoteNotificationsEnabled,
|
Enabled: c.config.RemoteNotificationsEnabled,
|
||||||
BlockedChatList: c.mutedChatIDsHashes(mutedChatIDs),
|
BlockedChatList: c.chatIDsHashes(options.MutedChatIDs),
|
||||||
AllowedKeyList: allowedKeyList,
|
BlockMentions: c.config.BlockMentions,
|
||||||
}
|
AllowedMentionsChatList: c.chatIDsHashes(options.PublicChatIDs),
|
||||||
return options, nil
|
AllowedKeyList: allowedKeyList,
|
||||||
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Client) buildPushNotificationUnregisterMessage() *protobuf.PushNotificationRegistration {
|
func (c *Client) buildPushNotificationUnregisterMessage() *protobuf.PushNotificationRegistration {
|
||||||
|
@ -1128,7 +1283,8 @@ func (c *Client) registerWithServer(registration *protobuf.PushNotificationRegis
|
||||||
|
|
||||||
// sendNotification sends an actual notification to the push notification server.
|
// sendNotification sends an actual notification to the push notification server.
|
||||||
// the notification is sent using an ephemeral key to shield the real identity of the sender
|
// the notification is sent using an ephemeral key to shield the real identity of the sender
|
||||||
func (c *Client) sendNotification(publicKey *ecdsa.PublicKey, installationIDs []string, messageID []byte) ([]*PushNotificationInfo, error) {
|
func (c *Client) sendNotification(publicKey *ecdsa.PublicKey, installationIDs []string, messageID []byte, chatID string, notificationType protobuf.PushNotification_PushNotificationType) ([]*PushNotificationInfo, error) {
|
||||||
|
|
||||||
// get latest push notification infos
|
// get latest push notification infos
|
||||||
err := c.queryNotificationInfo(publicKey, false)
|
err := c.queryNotificationInfo(publicKey, false)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -1187,12 +1343,12 @@ func (c *Client) sendNotification(publicKey *ecdsa.PublicKey, installationIDs []
|
||||||
for _, infos := range actionableInfos {
|
for _, infos := range actionableInfos {
|
||||||
var pushNotifications []*protobuf.PushNotification
|
var pushNotifications []*protobuf.PushNotification
|
||||||
for _, i := range infos {
|
for _, i := range infos {
|
||||||
// TODO: Add group chat ChatID
|
|
||||||
pushNotifications = append(pushNotifications, &protobuf.PushNotification{
|
pushNotifications = append(pushNotifications, &protobuf.PushNotification{
|
||||||
Type: protobuf.PushNotification_MESSAGE,
|
Type: notificationType,
|
||||||
// For now we set the ChatID to our own identity key, this will work fine for blocked users
|
// For now we set the ChatID to our own identity key, this will work fine for blocked users
|
||||||
// and muted 1-to-1 chats, but not for group chats.
|
// and muted 1-to-1 chats, but not for group chats.
|
||||||
ChatId: common.Shake256([]byte(types.EncodeHex(crypto.FromECDSAPub(&c.config.Identity.PublicKey)))),
|
ChatId: common.Shake256([]byte(chatID)),
|
||||||
|
Author: common.Shake256([]byte(types.EncodeHex(crypto.FromECDSAPub(&c.config.Identity.PublicKey)))),
|
||||||
AccessToken: i.AccessToken,
|
AccessToken: i.AccessToken,
|
||||||
PublicKey: common.HashPublicKey(publicKey),
|
PublicKey: common.HashPublicKey(publicKey),
|
||||||
InstallationId: i.InstallationID,
|
InstallationId: i.InstallationID,
|
||||||
|
@ -1251,7 +1407,7 @@ func (c *Client) resendNotification(pn *SentNotification) error {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
_, err = c.sendNotification(pn.PublicKey, []string{pn.InstallationID}, pn.MessageID)
|
_, err = c.sendNotification(pn.PublicKey, []string{pn.InstallationID}, pn.MessageID, pn.ChatID, pn.NotificationType)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1304,6 +1460,9 @@ func (c *Client) resendingLoop() error {
|
||||||
|
|
||||||
// registrationLoop is a loop that is running when we need to register with a push notification server, it only runs when needed, it will quit if no work is necessary.
|
// registrationLoop is a loop that is running when we need to register with a push notification server, it only runs when needed, it will quit if no work is necessary.
|
||||||
func (c *Client) registrationLoop() error {
|
func (c *Client) registrationLoop() error {
|
||||||
|
if c.lastPushNotificationRegistration == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
for {
|
for {
|
||||||
c.config.Logger.Debug("running registration loop")
|
c.config.Logger.Debug("running registration loop")
|
||||||
servers, err := c.persistence.GetServers()
|
servers, err := c.persistence.GetServers()
|
||||||
|
|
|
@ -58,7 +58,7 @@ func (s *ClientSuite) SetupTest() {
|
||||||
InstallationID: s.installationID,
|
InstallationID: s.installationID,
|
||||||
}
|
}
|
||||||
|
|
||||||
s.client = New(s.persistence, config, nil)
|
s.client = New(s.persistence, config, nil, nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *ClientSuite) TestBuildPushNotificationRegisterMessage() {
|
func (s *ClientSuite) TestBuildPushNotificationRegisterMessage() {
|
||||||
|
@ -74,6 +74,11 @@ func (s *ClientSuite) TestBuildPushNotificationRegisterMessage() {
|
||||||
s.Require().NoError(err)
|
s.Require().NoError(err)
|
||||||
contactIDs := []*ecdsa.PublicKey{&contactKey.PublicKey}
|
contactIDs := []*ecdsa.PublicKey{&contactKey.PublicKey}
|
||||||
|
|
||||||
|
options := &RegistrationOptions{
|
||||||
|
ContactIDs: contactIDs,
|
||||||
|
MutedChatIDs: mutedChatList,
|
||||||
|
}
|
||||||
|
|
||||||
// Set random generator for uuid
|
// Set random generator for uuid
|
||||||
var seed int64 = 1
|
var seed int64 = 1
|
||||||
uuid.SetRand(rand.New(rand.NewSource(seed)))
|
uuid.SetRand(rand.New(rand.NewSource(seed)))
|
||||||
|
@ -88,7 +93,7 @@ func (s *ClientSuite) TestBuildPushNotificationRegisterMessage() {
|
||||||
// Set reader
|
// Set reader
|
||||||
s.client.reader = bytes.NewReader([]byte(expectedUUID))
|
s.client.reader = bytes.NewReader([]byte(expectedUUID))
|
||||||
|
|
||||||
options := &protobuf.PushNotificationRegistration{
|
registration := &protobuf.PushNotificationRegistration{
|
||||||
Version: 1,
|
Version: 1,
|
||||||
AccessToken: expectedUUID,
|
AccessToken: expectedUUID,
|
||||||
DeviceToken: testDeviceToken,
|
DeviceToken: testDeviceToken,
|
||||||
|
@ -97,24 +102,36 @@ func (s *ClientSuite) TestBuildPushNotificationRegisterMessage() {
|
||||||
BlockedChatList: mutedChatListHashes,
|
BlockedChatList: mutedChatListHashes,
|
||||||
}
|
}
|
||||||
|
|
||||||
actualMessage, err := s.client.buildPushNotificationRegistrationMessage(contactIDs, mutedChatList)
|
actualMessage, err := s.client.buildPushNotificationRegistrationMessage(options)
|
||||||
s.Require().NoError(err)
|
s.Require().NoError(err)
|
||||||
|
|
||||||
s.Require().Equal(options, actualMessage)
|
s.Require().Equal(registration, actualMessage)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *ClientSuite) TestBuildPushNotificationRegisterMessageAllowFromContactsOnly() {
|
func (s *ClientSuite) TestBuildPushNotificationRegisterMessageAllowFromContactsOnly() {
|
||||||
mutedChatList := []string{"a", "b"}
|
mutedChatList := []string{"a", "b"}
|
||||||
|
publicChatList := []string{"c", "d"}
|
||||||
|
|
||||||
// build chat lish hashes
|
// build muted chat lish hashes
|
||||||
var mutedChatListHashes [][]byte
|
var mutedChatListHashes [][]byte
|
||||||
for _, chatID := range mutedChatList {
|
for _, chatID := range mutedChatList {
|
||||||
mutedChatListHashes = append(mutedChatListHashes, common.Shake256([]byte(chatID)))
|
mutedChatListHashes = append(mutedChatListHashes, common.Shake256([]byte(chatID)))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// build public chat lish hashes
|
||||||
|
var publicChatListHashes [][]byte
|
||||||
|
for _, chatID := range publicChatList {
|
||||||
|
publicChatListHashes = append(publicChatListHashes, common.Shake256([]byte(chatID)))
|
||||||
|
}
|
||||||
|
|
||||||
contactKey, err := crypto.GenerateKey()
|
contactKey, err := crypto.GenerateKey()
|
||||||
s.Require().NoError(err)
|
s.Require().NoError(err)
|
||||||
contactIDs := []*ecdsa.PublicKey{&contactKey.PublicKey}
|
contactIDs := []*ecdsa.PublicKey{&contactKey.PublicKey}
|
||||||
|
options := &RegistrationOptions{
|
||||||
|
ContactIDs: contactIDs,
|
||||||
|
MutedChatIDs: mutedChatList,
|
||||||
|
PublicChatIDs: publicChatList,
|
||||||
|
}
|
||||||
|
|
||||||
// Set random generator for uuid
|
// Set random generator for uuid
|
||||||
var seed int64 = 1
|
var seed int64 = 1
|
||||||
|
@ -144,21 +161,22 @@ func (s *ClientSuite) TestBuildPushNotificationRegisterMessageAllowFromContactsO
|
||||||
// Set reader
|
// Set reader
|
||||||
s.client.reader = bytes.NewReader([]byte(expectedUUID))
|
s.client.reader = bytes.NewReader([]byte(expectedUUID))
|
||||||
|
|
||||||
options := &protobuf.PushNotificationRegistration{
|
registration := &protobuf.PushNotificationRegistration{
|
||||||
Version: 1,
|
Version: 1,
|
||||||
AccessToken: expectedUUID,
|
AccessToken: expectedUUID,
|
||||||
DeviceToken: testDeviceToken,
|
DeviceToken: testDeviceToken,
|
||||||
InstallationId: s.installationID,
|
InstallationId: s.installationID,
|
||||||
AllowFromContactsOnly: true,
|
AllowFromContactsOnly: true,
|
||||||
Enabled: true,
|
Enabled: true,
|
||||||
BlockedChatList: mutedChatListHashes,
|
BlockedChatList: mutedChatListHashes,
|
||||||
AllowedKeyList: [][]byte{encryptedToken},
|
AllowedKeyList: [][]byte{encryptedToken},
|
||||||
|
AllowedMentionsChatList: publicChatListHashes,
|
||||||
}
|
}
|
||||||
|
|
||||||
actualMessage, err := s.client.buildPushNotificationRegistrationMessage(contactIDs, mutedChatList)
|
actualMessage, err := s.client.buildPushNotificationRegistrationMessage(options)
|
||||||
s.Require().NoError(err)
|
s.Require().NoError(err)
|
||||||
|
|
||||||
s.Require().Equal(options, actualMessage)
|
s.Require().Equal(registration, actualMessage)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *ClientSuite) TestHandleMessageScheduled() {
|
func (s *ClientSuite) TestHandleMessageScheduled() {
|
||||||
|
@ -183,7 +201,7 @@ func (s *ClientSuite) TestHandleMessageScheduled() {
|
||||||
s.Require().True(response)
|
s.Require().True(response)
|
||||||
|
|
||||||
// Save notification
|
// Save notification
|
||||||
s.Require().NoError(s.client.notifiedOn(&key1.PublicKey, installationID1, messageID))
|
s.Require().NoError(s.client.notifiedOn(&key1.PublicKey, installationID1, messageID, chatID, protobuf.PushNotification_MESSAGE))
|
||||||
|
|
||||||
// Second time, should not notify
|
// Second time, should not notify
|
||||||
response, err = s.client.shouldNotifyOn(&key1.PublicKey, installationID1, messageID)
|
response, err = s.client.shouldNotifyOn(&key1.PublicKey, installationID1, messageID)
|
||||||
|
|
|
@ -4,6 +4,8 @@
|
||||||
// 1593601729_initial_schema.up.sql (1.773kB)
|
// 1593601729_initial_schema.up.sql (1.773kB)
|
||||||
// 1597909626_add_server_type.down.sql (0)
|
// 1597909626_add_server_type.down.sql (0)
|
||||||
// 1597909626_add_server_type.up.sql (145B)
|
// 1597909626_add_server_type.up.sql (145B)
|
||||||
|
// 1599053776_add_chat_id_and_type.down.sql (0)
|
||||||
|
// 1599053776_add_chat_id_and_type.up.sql (264B)
|
||||||
// doc.go (382B)
|
// doc.go (382B)
|
||||||
|
|
||||||
package migrations
|
package migrations
|
||||||
|
@ -128,7 +130,7 @@ func _1597909626_add_server_typeDownSql() (*asset, error) {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
info := bindataFileInfo{name: "1597909626_add_server_type.down.sql", size: 0, mode: os.FileMode(0644), modTime: time.Unix(1597909727, 0)}
|
info := bindataFileInfo{name: "1597909626_add_server_type.down.sql", size: 0, mode: os.FileMode(0644), modTime: time.Unix(1598949727, 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}}
|
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}}
|
||||||
return a, nil
|
return a, nil
|
||||||
}
|
}
|
||||||
|
@ -148,11 +150,51 @@ func _1597909626_add_server_typeUpSql() (*asset, error) {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
info := bindataFileInfo{name: "1597909626_add_server_type.up.sql", size: 145, mode: os.FileMode(0644), modTime: time.Unix(1597909704, 0)}
|
info := bindataFileInfo{name: "1597909626_add_server_type.up.sql", size: 145, mode: os.FileMode(0644), modTime: time.Unix(1598949727, 0)}
|
||||||
a := &asset{bytes: bytes, info: info, digest: [32]uint8{0xc8, 0x3f, 0xe0, 0xe7, 0x57, 0x0, 0x5d, 0x60, 0xf3, 0x55, 0x64, 0x71, 0x80, 0x3c, 0xca, 0x8, 0x61, 0xb5, 0x3c, 0xe, 0xa1, 0xe4, 0x61, 0xd1, 0x4e, 0xd8, 0xb2, 0x55, 0xdd, 0x87, 0x62, 0x9b}}
|
a := &asset{bytes: bytes, info: info, digest: [32]uint8{0xc8, 0x3f, 0xe0, 0xe7, 0x57, 0x0, 0x5d, 0x60, 0xf3, 0x55, 0x64, 0x71, 0x80, 0x3c, 0xca, 0x8, 0x61, 0xb5, 0x3c, 0xe, 0xa1, 0xe4, 0x61, 0xd1, 0x4e, 0xd8, 0xb2, 0x55, 0xdd, 0x87, 0x62, 0x9b}}
|
||||||
return a, nil
|
return a, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var __1599053776_add_chat_id_and_typeDownSql = []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\x01\x00\x00\xff\xff\x00\x00\x00\x00\x00\x00\x00\x00")
|
||||||
|
|
||||||
|
func _1599053776_add_chat_id_and_typeDownSqlBytes() ([]byte, error) {
|
||||||
|
return bindataRead(
|
||||||
|
__1599053776_add_chat_id_and_typeDownSql,
|
||||||
|
"1599053776_add_chat_id_and_type.down.sql",
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
func _1599053776_add_chat_id_and_typeDownSql() (*asset, error) {
|
||||||
|
bytes, err := _1599053776_add_chat_id_and_typeDownSqlBytes()
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
info := bindataFileInfo{name: "1599053776_add_chat_id_and_type.down.sql", size: 0, mode: os.FileMode(0644), modTime: time.Unix(1599053859, 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}}
|
||||||
|
return a, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
var __1599053776_add_chat_id_and_typeUpSql = []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\x72\xf4\x09\x71\x0d\x52\x08\x71\x74\xf2\x71\x55\x28\x28\x2d\xce\x88\xcf\xcb\x2f\xc9\x4c\xcb\x4c\x4e\x2c\xc9\xcc\xcf\x8b\x4f\xce\xc9\x4c\xcd\x2b\x89\x2f\x06\x11\xc8\x12\xc5\x0a\x8e\x2e\x2e\x0a\xce\xfe\x3e\xa1\xbe\x7e\x0a\xc9\x19\x89\x25\xf1\x99\x29\x0a\x21\xae\x11\x21\xd6\x5c\x54\x30\x10\x45\x47\x49\x65\x41\xaa\x82\xa7\x5f\x88\x35\x17\x57\x68\x80\x8b\x63\x08\x69\xa6\x06\xbb\x86\xc0\xdd\x67\xab\xa0\xa4\xa4\x83\xc5\x70\x5b\x05\x43\x6b\x2e\x40\x00\x00\x00\xff\xff\x22\xaf\x2b\x87\x08\x01\x00\x00")
|
||||||
|
|
||||||
|
func _1599053776_add_chat_id_and_typeUpSqlBytes() ([]byte, error) {
|
||||||
|
return bindataRead(
|
||||||
|
__1599053776_add_chat_id_and_typeUpSql,
|
||||||
|
"1599053776_add_chat_id_and_type.up.sql",
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
func _1599053776_add_chat_id_and_typeUpSql() (*asset, error) {
|
||||||
|
bytes, err := _1599053776_add_chat_id_and_typeUpSqlBytes()
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
info := bindataFileInfo{name: "1599053776_add_chat_id_and_type.up.sql", size: 264, mode: os.FileMode(0644), modTime: time.Unix(1599053853, 0)}
|
||||||
|
a := &asset{bytes: bytes, info: info, digest: [32]uint8{0xea, 0x7a, 0xf9, 0xc4, 0xa2, 0x96, 0x2e, 0xf9, 0x8f, 0x7, 0xf1, 0x1e, 0x73, 0x8a, 0xa6, 0x3a, 0x13, 0x4, 0x73, 0x82, 0x83, 0xb, 0xe3, 0xb5, 0x3b, 0x7e, 0xd, 0x23, 0xce, 0x98, 0xd4, 0xdc}}
|
||||||
|
return a, nil
|
||||||
|
}
|
||||||
|
|
||||||
var _docGo = []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\x84\x8f\x3d\x6e\xec\x30\x0c\x84\x7b\x9d\x62\xb0\xcd\x36\xcf\x52\xf3\xaa\x74\x29\xd3\xe7\x02\x5c\x89\x96\x88\xb5\x24\x43\xa4\xf7\xe7\xf6\x81\x37\x01\xe2\x2e\xed\x87\xf9\x86\xc3\x10\xf0\x59\x44\x31\xcb\xc2\x10\x45\xe3\xc8\xaa\x34\x9e\xb8\x70\xa4\x4d\x19\xa7\x2c\x56\xb6\x8b\x8f\xbd\x06\x35\xb2\x4d\x27\xa9\xa1\x4a\x1e\x64\x1c\x6e\xff\x4f\x2e\x04\x44\x6a\x67\x43\xa1\x96\x16\x7e\x75\x29\xd4\x68\x98\xb4\x8c\xbb\x58\x01\x61\x1d\x3c\xcb\xc3\xe3\xdd\xb0\x30\xa9\xc1\x0a\xd9\x59\x61\x85\x11\x49\x79\xaf\x99\xfb\x40\xee\xd3\x45\x5a\x22\x23\xbf\xa3\x8f\xf9\x40\xf6\x85\x91\x96\x85\x13\xe6\xd1\xeb\xcb\x55\xaa\x8c\x24\x83\xa3\xf5\xf1\xfc\x07\x52\x65\x43\xa3\xca\xba\xfb\x85\x6e\x8c\xd6\x7f\xce\x83\x5a\xfa\xfb\x23\xdc\xfb\xb8\x2a\x48\xc1\x8f\x95\xa3\x71\xf2\xce\xad\x14\xaf\x94\x19\xdf\x39\xe9\x4d\x9d\x0b\x21\xf7\xb7\xcc\x8d\x77\xf3\xb8\x73\x5a\xaf\xf9\x90\xc4\xd4\xe1\x7d\xf8\x05\x3e\x77\xf8\xe0\xbe\x02\x00\x00\xff\xff\x4d\x1d\x5d\x50\x7e\x01\x00\x00")
|
var _docGo = []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\x84\x8f\x3d\x6e\xec\x30\x0c\x84\x7b\x9d\x62\xb0\xcd\x36\xcf\x52\xf3\xaa\x74\x29\xd3\xe7\x02\x5c\x89\x96\x88\xb5\x24\x43\xa4\xf7\xe7\xf6\x81\x37\x01\xe2\x2e\xed\x87\xf9\x86\xc3\x10\xf0\x59\x44\x31\xcb\xc2\x10\x45\xe3\xc8\xaa\x34\x9e\xb8\x70\xa4\x4d\x19\xa7\x2c\x56\xb6\x8b\x8f\xbd\x06\x35\xb2\x4d\x27\xa9\xa1\x4a\x1e\x64\x1c\x6e\xff\x4f\x2e\x04\x44\x6a\x67\x43\xa1\x96\x16\x7e\x75\x29\xd4\x68\x98\xb4\x8c\xbb\x58\x01\x61\x1d\x3c\xcb\xc3\xe3\xdd\xb0\x30\xa9\xc1\x0a\xd9\x59\x61\x85\x11\x49\x79\xaf\x99\xfb\x40\xee\xd3\x45\x5a\x22\x23\xbf\xa3\x8f\xf9\x40\xf6\x85\x91\x96\x85\x13\xe6\xd1\xeb\xcb\x55\xaa\x8c\x24\x83\xa3\xf5\xf1\xfc\x07\x52\x65\x43\xa3\xca\xba\xfb\x85\x6e\x8c\xd6\x7f\xce\x83\x5a\xfa\xfb\x23\xdc\xfb\xb8\x2a\x48\xc1\x8f\x95\xa3\x71\xf2\xce\xad\x14\xaf\x94\x19\xdf\x39\xe9\x4d\x9d\x0b\x21\xf7\xb7\xcc\x8d\x77\xf3\xb8\x73\x5a\xaf\xf9\x90\xc4\xd4\xe1\x7d\xf8\x05\x3e\x77\xf8\xe0\xbe\x02\x00\x00\xff\xff\x4d\x1d\x5d\x50\x7e\x01\x00\x00")
|
||||||
|
|
||||||
func docGoBytes() ([]byte, error) {
|
func docGoBytes() ([]byte, error) {
|
||||||
|
@ -272,6 +314,10 @@ var _bindata = map[string]func() (*asset, error){
|
||||||
|
|
||||||
"1597909626_add_server_type.up.sql": _1597909626_add_server_typeUpSql,
|
"1597909626_add_server_type.up.sql": _1597909626_add_server_typeUpSql,
|
||||||
|
|
||||||
|
"1599053776_add_chat_id_and_type.down.sql": _1599053776_add_chat_id_and_typeDownSql,
|
||||||
|
|
||||||
|
"1599053776_add_chat_id_and_type.up.sql": _1599053776_add_chat_id_and_typeUpSql,
|
||||||
|
|
||||||
"doc.go": docGo,
|
"doc.go": docGo,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -316,11 +362,13 @@ type bintree struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
var _bintree = &bintree{nil, map[string]*bintree{
|
var _bintree = &bintree{nil, map[string]*bintree{
|
||||||
"1593601729_initial_schema.down.sql": &bintree{_1593601729_initial_schemaDownSql, map[string]*bintree{}},
|
"1593601729_initial_schema.down.sql": &bintree{_1593601729_initial_schemaDownSql, map[string]*bintree{}},
|
||||||
"1593601729_initial_schema.up.sql": &bintree{_1593601729_initial_schemaUpSql, map[string]*bintree{}},
|
"1593601729_initial_schema.up.sql": &bintree{_1593601729_initial_schemaUpSql, map[string]*bintree{}},
|
||||||
"1597909626_add_server_type.down.sql": &bintree{_1597909626_add_server_typeDownSql, map[string]*bintree{}},
|
"1597909626_add_server_type.down.sql": &bintree{_1597909626_add_server_typeDownSql, map[string]*bintree{}},
|
||||||
"1597909626_add_server_type.up.sql": &bintree{_1597909626_add_server_typeUpSql, map[string]*bintree{}},
|
"1597909626_add_server_type.up.sql": &bintree{_1597909626_add_server_typeUpSql, map[string]*bintree{}},
|
||||||
"doc.go": &bintree{docGo, map[string]*bintree{}},
|
"1599053776_add_chat_id_and_type.down.sql": &bintree{_1599053776_add_chat_id_and_typeDownSql, map[string]*bintree{}},
|
||||||
|
"1599053776_add_chat_id_and_type.up.sql": &bintree{_1599053776_add_chat_id_and_typeUpSql, 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.
|
||||||
|
|
|
@ -0,0 +1,4 @@
|
||||||
|
ALTER TABLE push_notification_client_sent_notifications ADD COLUMN chat_id TEXT;
|
||||||
|
ALTER TABLE push_notification_client_sent_notifications ADD COLUMN notification_type INT;
|
||||||
|
|
||||||
|
UPDATE push_notification_client_sent_notifications SET chat_id = "", notification_type = 1;
|
|
@ -277,7 +277,7 @@ func (p *Persistence) ShouldSendNotificationToAllInstallationIDs(publicKey *ecds
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *Persistence) UpsertSentNotification(n *SentNotification) error {
|
func (p *Persistence) UpsertSentNotification(n *SentNotification) error {
|
||||||
_, err := p.db.Exec(`INSERT INTO push_notification_client_sent_notifications (public_key, installation_id, message_id, last_tried_at, retry_count, success, error, hashed_public_key) VALUES (?, ?, ?, ?, ?, ?, ?, ?)`, crypto.CompressPubkey(n.PublicKey), n.InstallationID, n.MessageID, n.LastTriedAt, n.RetryCount, n.Success, n.Error, n.HashedPublicKey())
|
_, err := p.db.Exec(`INSERT INTO push_notification_client_sent_notifications (public_key, installation_id, message_id, last_tried_at, retry_count, success, error, hashed_public_key,chat_id, notification_type) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`, crypto.CompressPubkey(n.PublicKey), n.InstallationID, n.MessageID, n.LastTriedAt, n.RetryCount, n.Success, n.Error, n.HashedPublicKey(), n.ChatID, n.NotificationType)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -287,7 +287,7 @@ func (p *Persistence) GetSentNotification(hashedPublicKey []byte, installationID
|
||||||
InstallationID: installationID,
|
InstallationID: installationID,
|
||||||
MessageID: messageID,
|
MessageID: messageID,
|
||||||
}
|
}
|
||||||
err := p.db.QueryRow(`SELECT retry_count, last_tried_at, error, success, public_key FROM push_notification_client_sent_notifications WHERE hashed_public_key = ?`, hashedPublicKey).Scan(&sentNotification.RetryCount, &sentNotification.LastTriedAt, &sentNotification.Error, &sentNotification.Success, &publicKeyBytes)
|
err := p.db.QueryRow(`SELECT retry_count, last_tried_at, error, success, public_key,chat_id,notification_type FROM push_notification_client_sent_notifications WHERE hashed_public_key = ?`, hashedPublicKey).Scan(&sentNotification.RetryCount, &sentNotification.LastTriedAt, &sentNotification.Error, &sentNotification.Success, &publicKeyBytes, &sentNotification.ChatID, &sentNotification.NotificationType)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
@ -309,7 +309,7 @@ func (p *Persistence) UpdateNotificationResponse(messageID []byte, response *pro
|
||||||
|
|
||||||
func (p *Persistence) GetRetriablePushNotifications() ([]*SentNotification, error) {
|
func (p *Persistence) GetRetriablePushNotifications() ([]*SentNotification, error) {
|
||||||
var notifications []*SentNotification
|
var notifications []*SentNotification
|
||||||
rows, err := p.db.Query(`SELECT retry_count, last_tried_at, error, success, public_key, installation_id, message_id FROM push_notification_client_sent_notifications WHERE NOT success AND error = ?`, protobuf.PushNotificationReport_WRONG_TOKEN)
|
rows, err := p.db.Query(`SELECT retry_count, last_tried_at, error, success, public_key, installation_id, message_id,chat_id, notification_type FROM push_notification_client_sent_notifications WHERE NOT success AND error = ?`, protobuf.PushNotificationReport_WRONG_TOKEN)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
@ -318,7 +318,7 @@ func (p *Persistence) GetRetriablePushNotifications() ([]*SentNotification, erro
|
||||||
for rows.Next() {
|
for rows.Next() {
|
||||||
var publicKeyBytes []byte
|
var publicKeyBytes []byte
|
||||||
notification := &SentNotification{}
|
notification := &SentNotification{}
|
||||||
err = rows.Scan(¬ification.RetryCount, ¬ification.LastTriedAt, ¬ification.Error, ¬ification.Success, &publicKeyBytes, ¬ification.InstallationID, ¬ification.MessageID)
|
err = rows.Scan(¬ification.RetryCount, ¬ification.LastTriedAt, ¬ification.Error, ¬ification.Success, &publicKeyBytes, ¬ification.InstallationID, ¬ification.MessageID, ¬ification.ChatID, ¬ification.NotificationType)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
|
@ -12,7 +12,8 @@ import (
|
||||||
"github.com/status-im/status-go/protocol/protobuf"
|
"github.com/status-im/status-go/protocol/protobuf"
|
||||||
)
|
)
|
||||||
|
|
||||||
const defaultNotificationMessage = "You have a new message"
|
const defaultNewMessageNotificationText = "You have a new message"
|
||||||
|
const defaultMentionNotificationText = "Someone mentioned you"
|
||||||
|
|
||||||
type GoRushRequestData struct {
|
type GoRushRequestData struct {
|
||||||
EncryptedMessage string `json:"encryptedMessage"`
|
EncryptedMessage string `json:"encryptedMessage"`
|
||||||
|
@ -52,11 +53,17 @@ func PushNotificationRegistrationToGoRushRequest(requestAndRegistrations []*Requ
|
||||||
for _, requestAndRegistration := range requestAndRegistrations {
|
for _, requestAndRegistration := range requestAndRegistrations {
|
||||||
request := requestAndRegistration.Request
|
request := requestAndRegistration.Request
|
||||||
registration := requestAndRegistration.Registration
|
registration := requestAndRegistration.Registration
|
||||||
|
var text string
|
||||||
|
if request.Type == protobuf.PushNotification_MESSAGE {
|
||||||
|
text = defaultNewMessageNotificationText
|
||||||
|
} else {
|
||||||
|
text = defaultMentionNotificationText
|
||||||
|
}
|
||||||
goRushRequests.Notifications = append(goRushRequests.Notifications,
|
goRushRequests.Notifications = append(goRushRequests.Notifications,
|
||||||
&GoRushRequestNotification{
|
&GoRushRequestNotification{
|
||||||
Tokens: []string{registration.DeviceToken},
|
Tokens: []string{registration.DeviceToken},
|
||||||
Platform: tokenTypeToGoRushPlatform(registration.TokenType),
|
Platform: tokenTypeToGoRushPlatform(registration.TokenType),
|
||||||
Message: defaultNotificationMessage,
|
Message: text,
|
||||||
Topic: registration.ApnTopic,
|
Topic: registration.ApnTopic,
|
||||||
Data: &GoRushRequestData{
|
Data: &GoRushRequestData{
|
||||||
EncryptedMessage: types.EncodeHex(request.Message),
|
EncryptedMessage: types.EncodeHex(request.Message),
|
||||||
|
|
|
@ -33,6 +33,7 @@ func TestPushNotificationRegistrationToGoRushRequest(t *testing.T) {
|
||||||
{
|
{
|
||||||
Request: &protobuf.PushNotification{
|
Request: &protobuf.PushNotification{
|
||||||
ChatId: chatID,
|
ChatId: chatID,
|
||||||
|
Type: protobuf.PushNotification_MESSAGE,
|
||||||
PublicKey: publicKey1,
|
PublicKey: publicKey1,
|
||||||
InstallationId: installationID1,
|
InstallationId: installationID1,
|
||||||
Message: message1,
|
Message: message1,
|
||||||
|
@ -45,6 +46,7 @@ func TestPushNotificationRegistrationToGoRushRequest(t *testing.T) {
|
||||||
{
|
{
|
||||||
Request: &protobuf.PushNotification{
|
Request: &protobuf.PushNotification{
|
||||||
ChatId: chatID,
|
ChatId: chatID,
|
||||||
|
Type: protobuf.PushNotification_MESSAGE,
|
||||||
PublicKey: publicKey1,
|
PublicKey: publicKey1,
|
||||||
InstallationId: installationID2,
|
InstallationId: installationID2,
|
||||||
Message: message2,
|
Message: message2,
|
||||||
|
@ -57,6 +59,7 @@ func TestPushNotificationRegistrationToGoRushRequest(t *testing.T) {
|
||||||
{
|
{
|
||||||
Request: &protobuf.PushNotification{
|
Request: &protobuf.PushNotification{
|
||||||
ChatId: chatID,
|
ChatId: chatID,
|
||||||
|
Type: protobuf.PushNotification_MENTION,
|
||||||
PublicKey: publicKey2,
|
PublicKey: publicKey2,
|
||||||
InstallationId: installationID3,
|
InstallationId: installationID3,
|
||||||
Message: message3,
|
Message: message3,
|
||||||
|
@ -73,7 +76,7 @@ func TestPushNotificationRegistrationToGoRushRequest(t *testing.T) {
|
||||||
{
|
{
|
||||||
Tokens: []string{token1},
|
Tokens: []string{token1},
|
||||||
Platform: platform1,
|
Platform: platform1,
|
||||||
Message: defaultNotificationMessage,
|
Message: defaultNewMessageNotificationText,
|
||||||
Data: &GoRushRequestData{
|
Data: &GoRushRequestData{
|
||||||
EncryptedMessage: hexMessage1,
|
EncryptedMessage: hexMessage1,
|
||||||
ChatID: types.EncodeHex(chatID),
|
ChatID: types.EncodeHex(chatID),
|
||||||
|
@ -83,7 +86,7 @@ func TestPushNotificationRegistrationToGoRushRequest(t *testing.T) {
|
||||||
{
|
{
|
||||||
Tokens: []string{token2},
|
Tokens: []string{token2},
|
||||||
Platform: platform2,
|
Platform: platform2,
|
||||||
Message: defaultNotificationMessage,
|
Message: defaultNewMessageNotificationText,
|
||||||
Data: &GoRushRequestData{
|
Data: &GoRushRequestData{
|
||||||
EncryptedMessage: hexMessage2,
|
EncryptedMessage: hexMessage2,
|
||||||
ChatID: types.EncodeHex(chatID),
|
ChatID: types.EncodeHex(chatID),
|
||||||
|
@ -93,7 +96,7 @@ func TestPushNotificationRegistrationToGoRushRequest(t *testing.T) {
|
||||||
{
|
{
|
||||||
Tokens: []string{token3},
|
Tokens: []string{token3},
|
||||||
Platform: platform3,
|
Platform: platform3,
|
||||||
Message: defaultNotificationMessage,
|
Message: defaultMentionNotificationText,
|
||||||
Data: &GoRushRequestData{
|
Data: &GoRushRequestData{
|
||||||
EncryptedMessage: hexMessage3,
|
EncryptedMessage: hexMessage3,
|
||||||
ChatID: types.EncodeHex(chatID),
|
ChatID: types.EncodeHex(chatID),
|
||||||
|
|
|
@ -21,6 +21,8 @@ import (
|
||||||
const encryptedPayloadKeyLength = 16
|
const encryptedPayloadKeyLength = 16
|
||||||
const defaultGorushURL = "https://gorush.status.im"
|
const defaultGorushURL = "https://gorush.status.im"
|
||||||
|
|
||||||
|
var errUnhandledPushNotificationType = errors.New("unhandled push notification type")
|
||||||
|
|
||||||
type Config struct {
|
type Config struct {
|
||||||
Enabled bool
|
Enabled bool
|
||||||
// Identity is our identity key
|
// Identity is our identity key
|
||||||
|
@ -56,7 +58,7 @@ func (s *Server) Start() error {
|
||||||
|
|
||||||
s.config.Logger.Info("starting push notification server")
|
s.config.Logger.Info("starting push notification server")
|
||||||
if s.config.Identity == nil {
|
if s.config.Identity == nil {
|
||||||
s.config.Logger.Info("Identity nil")
|
s.config.Logger.Debug("Identity nil")
|
||||||
// Pull identity from database
|
// Pull identity from database
|
||||||
identity, err := s.persistence.GetIdentity()
|
identity, err := s.persistence.GetIdentity()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -139,7 +141,7 @@ func (s *Server) HandlePushNotificationQuery(publicKey *ecdsa.PublicKey, message
|
||||||
func (s *Server) HandlePushNotificationRequest(publicKey *ecdsa.PublicKey,
|
func (s *Server) HandlePushNotificationRequest(publicKey *ecdsa.PublicKey,
|
||||||
messageID []byte,
|
messageID []byte,
|
||||||
request protobuf.PushNotificationRequest) error {
|
request protobuf.PushNotificationRequest) error {
|
||||||
s.config.Logger.Info("handling pn request", zap.Binary("message-id", messageID))
|
s.config.Logger.Debug("handling pn request", zap.Binary("message-id", messageID))
|
||||||
|
|
||||||
// This is at-most-once semantic for now
|
// This is at-most-once semantic for now
|
||||||
exists, err := s.persistence.PushNotificationExists(messageID)
|
exists, err := s.persistence.PushNotificationExists(messageID)
|
||||||
|
@ -148,14 +150,20 @@ func (s *Server) HandlePushNotificationRequest(publicKey *ecdsa.PublicKey,
|
||||||
}
|
}
|
||||||
|
|
||||||
if exists {
|
if exists {
|
||||||
s.config.Logger.Info("already handled")
|
s.config.Logger.Debug("already handled")
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
response := s.buildPushNotificationRequestResponseAndSendNotification(&request)
|
response, requestsAndRegistrations := s.buildPushNotificationRequestResponse(&request)
|
||||||
|
//AndSendNotification(&request)
|
||||||
if response == nil {
|
if response == nil {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
err = s.sendPushNotification(requestsAndRegistrations)
|
||||||
|
if err != nil {
|
||||||
|
s.config.Logger.Error("failed to send go rush notification", zap.Error(err))
|
||||||
|
return err
|
||||||
|
}
|
||||||
encodedMessage, err := proto.Marshal(response)
|
encodedMessage, err := proto.Marshal(response)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
|
@ -298,7 +306,7 @@ func (s *Server) validateRegistration(publicKey *ecdsa.PublicKey, payload []byte
|
||||||
// buildPushNotificationQueryResponse check if we have the client information and send them back
|
// buildPushNotificationQueryResponse check if we have the client information and send them back
|
||||||
func (s *Server) buildPushNotificationQueryResponse(query *protobuf.PushNotificationQuery) *protobuf.PushNotificationQueryResponse {
|
func (s *Server) buildPushNotificationQueryResponse(query *protobuf.PushNotificationQuery) *protobuf.PushNotificationQueryResponse {
|
||||||
|
|
||||||
s.config.Logger.Info("handling push notification query")
|
s.config.Logger.Debug("handling push notification query")
|
||||||
response := &protobuf.PushNotificationQueryResponse{}
|
response := &protobuf.PushNotificationQueryResponse{}
|
||||||
if query == nil || len(query.PublicKeys) == 0 {
|
if query == nil || len(query.PublicKeys) == 0 {
|
||||||
return response
|
return response
|
||||||
|
@ -334,23 +342,65 @@ func (s *Server) buildPushNotificationQueryResponse(query *protobuf.PushNotifica
|
||||||
return response
|
return response
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Server) blockedChatID(blockedChatIDs [][]byte, chatID []byte) bool {
|
func (s *Server) contains(list [][]byte, chatID []byte) bool {
|
||||||
for _, blockedChatID := range blockedChatIDs {
|
for _, list := range list {
|
||||||
if bytes.Equal(blockedChatID, chatID) {
|
if bytes.Equal(list, chatID) {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
// buildPushNotificationRequestResponseAndSendNotification will build a response
|
type reportResult struct {
|
||||||
// and fire-and-forget send a query to the gorush instance
|
sendNotification bool
|
||||||
func (s *Server) buildPushNotificationRequestResponseAndSendNotification(request *protobuf.PushNotificationRequest) *protobuf.PushNotificationResponse {
|
report *protobuf.PushNotificationReport
|
||||||
|
}
|
||||||
|
|
||||||
|
// buildPushNotificationReport checks the request against the registration and
|
||||||
|
// returns whether we should send the notification and what the response should be
|
||||||
|
func (s *Server) buildPushNotificationReport(pn *protobuf.PushNotification, registration *protobuf.PushNotificationRegistration) (*reportResult, error) {
|
||||||
|
response := &reportResult{}
|
||||||
|
report := &protobuf.PushNotificationReport{
|
||||||
|
PublicKey: pn.PublicKey,
|
||||||
|
InstallationId: pn.InstallationId,
|
||||||
|
}
|
||||||
|
|
||||||
|
if pn.Type == protobuf.PushNotification_UNKNOWN_PUSH_NOTIFICATION_TYPE {
|
||||||
|
s.config.Logger.Warn("unhandled type")
|
||||||
|
return nil, errUnhandledPushNotificationType
|
||||||
|
}
|
||||||
|
|
||||||
|
if registration == nil {
|
||||||
|
s.config.Logger.Warn("empty registration")
|
||||||
|
report.Error = protobuf.PushNotificationReport_NOT_REGISTERED
|
||||||
|
} else if registration.AccessToken != pn.AccessToken {
|
||||||
|
s.config.Logger.Debug("invalid token")
|
||||||
|
report.Error = protobuf.PushNotificationReport_WRONG_TOKEN
|
||||||
|
} else if (s.isMessageNotification(pn) && !s.isValidMessageNotification(pn, registration)) || (s.isMentionNotification(pn) && !s.isValidMentionNotification(pn, registration)) {
|
||||||
|
s.config.Logger.Debug("filtered notification")
|
||||||
|
// We report as successful but don't send the notification
|
||||||
|
// for privacy reasons, as otherwise we would disclose that
|
||||||
|
// the sending client has been blocked or that the registering
|
||||||
|
// client has not joined a given public chat
|
||||||
|
report.Success = true
|
||||||
|
} else {
|
||||||
|
response.sendNotification = true
|
||||||
|
s.config.Logger.Debug("sending push notification")
|
||||||
|
report.Success = true
|
||||||
|
}
|
||||||
|
|
||||||
|
response.report = report
|
||||||
|
|
||||||
|
return response, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// buildPushNotificationRequestResponse will build a response
|
||||||
|
func (s *Server) buildPushNotificationRequestResponse(request *protobuf.PushNotificationRequest) (*protobuf.PushNotificationResponse, []*RequestAndRegistration) {
|
||||||
response := &protobuf.PushNotificationResponse{}
|
response := &protobuf.PushNotificationResponse{}
|
||||||
// We don't even send a response in this case
|
// We don't even send a response in this case
|
||||||
if request == nil || len(request.MessageId) == 0 {
|
if request == nil || len(request.MessageId) == 0 {
|
||||||
s.config.Logger.Warn("empty message id")
|
s.config.Logger.Warn("empty message id")
|
||||||
return nil
|
return nil, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
response.MessageId = request.MessageId
|
response.MessageId = request.MessageId
|
||||||
|
@ -360,56 +410,48 @@ func (s *Server) buildPushNotificationRequestResponseAndSendNotification(request
|
||||||
|
|
||||||
for _, pn := range request.Requests {
|
for _, pn := range request.Requests {
|
||||||
registration, err := s.persistence.GetPushNotificationRegistrationByPublicKeyAndInstallationID(pn.PublicKey, pn.InstallationId)
|
registration, err := s.persistence.GetPushNotificationRegistrationByPublicKeyAndInstallationID(pn.PublicKey, pn.InstallationId)
|
||||||
report := &protobuf.PushNotificationReport{
|
var report *protobuf.PushNotificationReport
|
||||||
PublicKey: pn.PublicKey,
|
|
||||||
InstallationId: pn.InstallationId,
|
|
||||||
}
|
|
||||||
|
|
||||||
if pn.Type != protobuf.PushNotification_MESSAGE {
|
|
||||||
s.config.Logger.Warn("unhandled type")
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
s.config.Logger.Error("failed to retrieve registration", zap.Error(err))
|
report = &protobuf.PushNotificationReport{
|
||||||
report.Error = protobuf.PushNotificationReport_UNKNOWN_ERROR_TYPE
|
PublicKey: pn.PublicKey,
|
||||||
} else if registration == nil {
|
Error: protobuf.PushNotificationReport_UNKNOWN_ERROR_TYPE,
|
||||||
s.config.Logger.Warn("empty registration")
|
InstallationId: pn.InstallationId,
|
||||||
report.Error = protobuf.PushNotificationReport_NOT_REGISTERED
|
}
|
||||||
} else if registration.AccessToken != pn.AccessToken {
|
|
||||||
report.Error = protobuf.PushNotificationReport_WRONG_TOKEN
|
|
||||||
} else if s.blockedChatID(registration.BlockedChatList, pn.ChatId) {
|
|
||||||
// We report as successful but don't send the notification
|
|
||||||
report.Success = true
|
|
||||||
} else {
|
} else {
|
||||||
// For now we just assume that the notification will be successful
|
response, err := s.buildPushNotificationReport(pn, registration)
|
||||||
requestAndRegistrations = append(requestAndRegistrations, &RequestAndRegistration{
|
if err != nil {
|
||||||
Request: pn,
|
s.config.Logger.Warn("unhandled type")
|
||||||
Registration: registration,
|
continue
|
||||||
})
|
}
|
||||||
report.Success = true
|
|
||||||
|
if response.sendNotification {
|
||||||
|
requestAndRegistrations = append(requestAndRegistrations, &RequestAndRegistration{
|
||||||
|
Request: pn,
|
||||||
|
Registration: registration,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
report = response.report
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
response.Reports = append(response.Reports, report)
|
response.Reports = append(response.Reports, report)
|
||||||
}
|
}
|
||||||
|
|
||||||
s.config.Logger.Info("built pn request")
|
s.config.Logger.Debug("built pn request")
|
||||||
if len(requestAndRegistrations) == 0 {
|
if len(requestAndRegistrations) == 0 {
|
||||||
s.config.Logger.Warn("no request and registration")
|
s.config.Logger.Warn("no request and registration")
|
||||||
return response
|
return response, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// This can be done asynchronously
|
return response, requestAndRegistrations
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *Server) sendPushNotification(requestAndRegistrations []*RequestAndRegistration) error {
|
||||||
|
if len(requestAndRegistrations) == 0 {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
goRushRequest := PushNotificationRegistrationToGoRushRequest(requestAndRegistrations)
|
goRushRequest := PushNotificationRegistrationToGoRushRequest(requestAndRegistrations)
|
||||||
err := sendGoRushNotification(goRushRequest, s.config.GorushURL, s.config.Logger)
|
return sendGoRushNotification(goRushRequest, s.config.GorushURL, s.config.Logger)
|
||||||
if err != nil {
|
|
||||||
s.config.Logger.Error("failed to send go rush notification", zap.Error(err))
|
|
||||||
// TODO: handle this error?
|
|
||||||
// GoRush will not let us know that the sending of the push notification has failed,
|
|
||||||
// so this likely mean that the actual HTTP request has failed, or there was some unexpected error
|
|
||||||
}
|
|
||||||
|
|
||||||
return response
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// listenToPublicKeyQueryTopic listen to a topic derived from the hashed public key
|
// listenToPublicKeyQueryTopic listen to a topic derived from the hashed public key
|
||||||
|
@ -424,7 +466,7 @@ func (s *Server) listenToPublicKeyQueryTopic(hashedPublicKey []byte) error {
|
||||||
// buildPushNotificationRegistrationResponse will check the registration is valid, save it, and listen to the topic for the queries
|
// buildPushNotificationRegistrationResponse will check the registration is valid, save it, and listen to the topic for the queries
|
||||||
func (s *Server) buildPushNotificationRegistrationResponse(publicKey *ecdsa.PublicKey, payload []byte) *protobuf.PushNotificationRegistrationResponse {
|
func (s *Server) buildPushNotificationRegistrationResponse(publicKey *ecdsa.PublicKey, payload []byte) *protobuf.PushNotificationRegistrationResponse {
|
||||||
|
|
||||||
s.config.Logger.Info("handling push notification registration")
|
s.config.Logger.Debug("handling push notification registration")
|
||||||
response := &protobuf.PushNotificationRegistrationResponse{
|
response := &protobuf.PushNotificationRegistrationResponse{
|
||||||
RequestId: common.Shake256(payload),
|
RequestId: common.Shake256(payload),
|
||||||
}
|
}
|
||||||
|
@ -442,7 +484,7 @@ func (s *Server) buildPushNotificationRegistrationResponse(publicKey *ecdsa.Publ
|
||||||
}
|
}
|
||||||
|
|
||||||
if registration.Unregister {
|
if registration.Unregister {
|
||||||
s.config.Logger.Info("unregistering client")
|
s.config.Logger.Debug("unregistering client")
|
||||||
// We save an empty registration, only keeping version and installation-id
|
// We save an empty registration, only keeping version and installation-id
|
||||||
if err := s.persistence.UnregisterPushNotificationRegistration(common.HashPublicKey(publicKey), registration.InstallationId, registration.Version); err != nil {
|
if err := s.persistence.UnregisterPushNotificationRegistration(common.HashPublicKey(publicKey), registration.InstallationId, registration.Version); err != nil {
|
||||||
response.Error = protobuf.PushNotificationRegistrationResponse_INTERNAL_ERROR
|
response.Error = protobuf.PushNotificationRegistrationResponse_INTERNAL_ERROR
|
||||||
|
@ -464,7 +506,32 @@ func (s *Server) buildPushNotificationRegistrationResponse(publicKey *ecdsa.Publ
|
||||||
}
|
}
|
||||||
response.Success = true
|
response.Success = true
|
||||||
|
|
||||||
s.config.Logger.Info("handled push notification registration successfully")
|
s.config.Logger.Debug("handled push notification registration successfully")
|
||||||
|
|
||||||
return response
|
return response
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (s *Server) isMentionNotification(pn *protobuf.PushNotification) bool {
|
||||||
|
return pn.Type == protobuf.PushNotification_MENTION
|
||||||
|
}
|
||||||
|
|
||||||
|
// isValidMentionNotification checks:
|
||||||
|
// this is a mention
|
||||||
|
// mentions are enabled
|
||||||
|
// the user joined the public chat
|
||||||
|
// the author is not blocked
|
||||||
|
func (s *Server) isValidMentionNotification(pn *protobuf.PushNotification, registration *protobuf.PushNotificationRegistration) bool {
|
||||||
|
return s.isMentionNotification(pn) && !registration.BlockMentions && s.contains(registration.AllowedMentionsChatList, pn.ChatId) && !s.contains(registration.BlockedChatList, pn.Author)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *Server) isMessageNotification(pn *protobuf.PushNotification) bool {
|
||||||
|
return pn.Type == protobuf.PushNotification_MESSAGE
|
||||||
|
}
|
||||||
|
|
||||||
|
// isValidMentionNotification checks:
|
||||||
|
// this is a message
|
||||||
|
// the chat is not muted
|
||||||
|
// the author is not blocked
|
||||||
|
func (s *Server) isValidMessageNotification(pn *protobuf.PushNotification, registration *protobuf.PushNotificationRegistration) bool {
|
||||||
|
return s.isMessageNotification(pn) && !s.contains(registration.BlockedChatList, pn.ChatId) && !s.contains(registration.BlockedChatList, pn.Author)
|
||||||
|
}
|
||||||
|
|
|
@ -582,3 +582,298 @@ func (s *ServerSuite) TestbuildPushNotificationQueryResponseWithFiltering() {
|
||||||
s.Require().Equal(s.installationID, queryResponse.Info[0].InstallationId)
|
s.Require().Equal(s.installationID, queryResponse.Info[0].InstallationId)
|
||||||
s.Require().Equal(allowedKeyList, queryResponse.Info[0].AllowedKeyList)
|
s.Require().Equal(allowedKeyList, queryResponse.Info[0].AllowedKeyList)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (s *ServerSuite) TestPushNotificationMentions() {
|
||||||
|
existingChatID := []byte("existing-chat-id")
|
||||||
|
nonExistingChatID := []byte("non-existing-chat-id")
|
||||||
|
registration := &protobuf.PushNotificationRegistration{
|
||||||
|
DeviceToken: "abc",
|
||||||
|
AccessToken: s.accessToken,
|
||||||
|
Grant: s.grant,
|
||||||
|
TokenType: protobuf.PushNotificationRegistration_APN_TOKEN,
|
||||||
|
InstallationId: s.installationID,
|
||||||
|
AllowedMentionsChatList: [][]byte{existingChatID},
|
||||||
|
Version: 1,
|
||||||
|
}
|
||||||
|
payload, err := proto.Marshal(registration)
|
||||||
|
s.Require().NoError(err)
|
||||||
|
|
||||||
|
cyphertext, err := common.Encrypt(payload, s.sharedKey, rand.Reader)
|
||||||
|
s.Require().NoError(err)
|
||||||
|
response := s.server.buildPushNotificationRegistrationResponse(&s.key.PublicKey, cyphertext)
|
||||||
|
s.Require().NotNil(response)
|
||||||
|
s.Require().True(response.Success)
|
||||||
|
|
||||||
|
pushNotificationRequest := &protobuf.PushNotificationRequest{
|
||||||
|
MessageId: []byte("message-id"),
|
||||||
|
Requests: []*protobuf.PushNotification{
|
||||||
|
{
|
||||||
|
AccessToken: s.accessToken,
|
||||||
|
PublicKey: common.HashPublicKey(&s.key.PublicKey),
|
||||||
|
ChatId: existingChatID,
|
||||||
|
InstallationId: s.installationID,
|
||||||
|
Type: protobuf.PushNotification_MENTION,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
AccessToken: s.accessToken,
|
||||||
|
PublicKey: common.HashPublicKey(&s.key.PublicKey),
|
||||||
|
ChatId: nonExistingChatID,
|
||||||
|
InstallationId: s.installationID,
|
||||||
|
Type: protobuf.PushNotification_MENTION,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
pushNotificationResponse, requestAndRegistrations := s.server.buildPushNotificationRequestResponse(pushNotificationRequest)
|
||||||
|
s.Require().NotNil(pushNotificationResponse)
|
||||||
|
s.Require().NotNil(requestAndRegistrations)
|
||||||
|
|
||||||
|
// only one should succeed
|
||||||
|
s.Require().Len(requestAndRegistrations, 1)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *ServerSuite) TestPushNotificationDisabledMentions() {
|
||||||
|
existingChatID := []byte("existing-chat-id")
|
||||||
|
registration := &protobuf.PushNotificationRegistration{
|
||||||
|
DeviceToken: "abc",
|
||||||
|
AccessToken: s.accessToken,
|
||||||
|
Grant: s.grant,
|
||||||
|
TokenType: protobuf.PushNotificationRegistration_APN_TOKEN,
|
||||||
|
BlockMentions: true,
|
||||||
|
InstallationId: s.installationID,
|
||||||
|
AllowedMentionsChatList: [][]byte{existingChatID},
|
||||||
|
Version: 1,
|
||||||
|
}
|
||||||
|
payload, err := proto.Marshal(registration)
|
||||||
|
s.Require().NoError(err)
|
||||||
|
|
||||||
|
cyphertext, err := common.Encrypt(payload, s.sharedKey, rand.Reader)
|
||||||
|
s.Require().NoError(err)
|
||||||
|
response := s.server.buildPushNotificationRegistrationResponse(&s.key.PublicKey, cyphertext)
|
||||||
|
s.Require().NotNil(response)
|
||||||
|
s.Require().True(response.Success)
|
||||||
|
|
||||||
|
pushNotificationRequest := &protobuf.PushNotificationRequest{
|
||||||
|
MessageId: []byte("message-id"),
|
||||||
|
Requests: []*protobuf.PushNotification{
|
||||||
|
{
|
||||||
|
AccessToken: s.accessToken,
|
||||||
|
PublicKey: common.HashPublicKey(&s.key.PublicKey),
|
||||||
|
ChatId: existingChatID,
|
||||||
|
InstallationId: s.installationID,
|
||||||
|
Type: protobuf.PushNotification_MENTION,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
pushNotificationResponse, requestAndRegistrations := s.server.buildPushNotificationRequestResponse(pushNotificationRequest)
|
||||||
|
s.Require().NotNil(pushNotificationResponse)
|
||||||
|
s.Require().Nil(requestAndRegistrations)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *ServerSuite) TestBuildPushNotificationReport() {
|
||||||
|
accessToken := "a"
|
||||||
|
chatID := []byte("chat-id")
|
||||||
|
author := []byte("author")
|
||||||
|
blockedAuthor := []byte("blocked-author")
|
||||||
|
blockedChatID := []byte("blocked-chat-id")
|
||||||
|
blockedChatList := [][]byte{blockedChatID, blockedAuthor}
|
||||||
|
nonJoinedChatID := []byte("non-joined-chat-id")
|
||||||
|
allowedMentionsChatList := [][]byte{chatID}
|
||||||
|
validMessagePN := &protobuf.PushNotification{
|
||||||
|
Type: protobuf.PushNotification_MESSAGE,
|
||||||
|
ChatId: chatID,
|
||||||
|
Author: author,
|
||||||
|
AccessToken: accessToken,
|
||||||
|
}
|
||||||
|
validMentionPN := &protobuf.PushNotification{
|
||||||
|
Type: protobuf.PushNotification_MENTION,
|
||||||
|
ChatId: chatID,
|
||||||
|
AccessToken: accessToken,
|
||||||
|
}
|
||||||
|
validRegistration := &protobuf.PushNotificationRegistration{
|
||||||
|
AccessToken: accessToken,
|
||||||
|
BlockedChatList: blockedChatList,
|
||||||
|
AllowedMentionsChatList: allowedMentionsChatList,
|
||||||
|
}
|
||||||
|
blockedMentionsRegistration := &protobuf.PushNotificationRegistration{
|
||||||
|
AccessToken: accessToken,
|
||||||
|
BlockMentions: true,
|
||||||
|
BlockedChatList: blockedChatList,
|
||||||
|
AllowedMentionsChatList: allowedMentionsChatList,
|
||||||
|
}
|
||||||
|
|
||||||
|
testCases := []struct {
|
||||||
|
name string
|
||||||
|
pn *protobuf.PushNotification
|
||||||
|
registration *protobuf.PushNotificationRegistration
|
||||||
|
expectedError error
|
||||||
|
expectedResponse *reportResult
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
name: "valid message",
|
||||||
|
pn: validMessagePN,
|
||||||
|
registration: validRegistration,
|
||||||
|
expectedResponse: &reportResult{
|
||||||
|
sendNotification: true,
|
||||||
|
report: &protobuf.PushNotificationReport{
|
||||||
|
Success: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "valid mention",
|
||||||
|
pn: validMentionPN,
|
||||||
|
registration: validRegistration,
|
||||||
|
expectedResponse: &reportResult{
|
||||||
|
sendNotification: true,
|
||||||
|
report: &protobuf.PushNotificationReport{
|
||||||
|
Success: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "unknow push notification",
|
||||||
|
pn: &protobuf.PushNotification{
|
||||||
|
ChatId: chatID,
|
||||||
|
AccessToken: accessToken,
|
||||||
|
},
|
||||||
|
registration: validRegistration,
|
||||||
|
expectedError: errUnhandledPushNotificationType,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "empty registration",
|
||||||
|
pn: validMessagePN,
|
||||||
|
registration: nil,
|
||||||
|
expectedResponse: &reportResult{
|
||||||
|
sendNotification: false,
|
||||||
|
report: &protobuf.PushNotificationReport{
|
||||||
|
Success: false,
|
||||||
|
Error: protobuf.PushNotificationReport_NOT_REGISTERED,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "invalid access token message",
|
||||||
|
pn: &protobuf.PushNotification{
|
||||||
|
Type: protobuf.PushNotification_MESSAGE,
|
||||||
|
Author: author,
|
||||||
|
ChatId: chatID,
|
||||||
|
AccessToken: "invalid",
|
||||||
|
},
|
||||||
|
registration: validRegistration,
|
||||||
|
expectedResponse: &reportResult{
|
||||||
|
sendNotification: false,
|
||||||
|
report: &protobuf.PushNotificationReport{
|
||||||
|
Success: false,
|
||||||
|
Error: protobuf.PushNotificationReport_WRONG_TOKEN,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "invalid access token mention",
|
||||||
|
pn: &protobuf.PushNotification{
|
||||||
|
Type: protobuf.PushNotification_MENTION,
|
||||||
|
Author: author,
|
||||||
|
ChatId: chatID,
|
||||||
|
AccessToken: "invalid",
|
||||||
|
},
|
||||||
|
registration: validRegistration,
|
||||||
|
expectedResponse: &reportResult{
|
||||||
|
sendNotification: false,
|
||||||
|
report: &protobuf.PushNotificationReport{
|
||||||
|
Success: false,
|
||||||
|
Error: protobuf.PushNotificationReport_WRONG_TOKEN,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "blocked chat list message",
|
||||||
|
pn: &protobuf.PushNotification{
|
||||||
|
Type: protobuf.PushNotification_MESSAGE,
|
||||||
|
ChatId: blockedChatID,
|
||||||
|
Author: author,
|
||||||
|
AccessToken: accessToken,
|
||||||
|
},
|
||||||
|
registration: validRegistration,
|
||||||
|
expectedResponse: &reportResult{
|
||||||
|
sendNotification: false,
|
||||||
|
report: &protobuf.PushNotificationReport{
|
||||||
|
Success: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "blocked group chat message",
|
||||||
|
pn: &protobuf.PushNotification{
|
||||||
|
Type: protobuf.PushNotification_MESSAGE,
|
||||||
|
Author: blockedAuthor,
|
||||||
|
ChatId: chatID,
|
||||||
|
AccessToken: accessToken,
|
||||||
|
},
|
||||||
|
registration: validRegistration,
|
||||||
|
expectedResponse: &reportResult{
|
||||||
|
sendNotification: false,
|
||||||
|
report: &protobuf.PushNotificationReport{
|
||||||
|
Success: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "blocked chat list mention",
|
||||||
|
pn: &protobuf.PushNotification{
|
||||||
|
Type: protobuf.PushNotification_MENTION,
|
||||||
|
Author: blockedAuthor,
|
||||||
|
ChatId: chatID,
|
||||||
|
AccessToken: accessToken,
|
||||||
|
},
|
||||||
|
registration: validRegistration,
|
||||||
|
expectedResponse: &reportResult{
|
||||||
|
sendNotification: false,
|
||||||
|
report: &protobuf.PushNotificationReport{
|
||||||
|
Success: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "blocked mentions",
|
||||||
|
pn: &protobuf.PushNotification{
|
||||||
|
Type: protobuf.PushNotification_MENTION,
|
||||||
|
Author: author,
|
||||||
|
ChatId: chatID,
|
||||||
|
AccessToken: accessToken,
|
||||||
|
},
|
||||||
|
registration: blockedMentionsRegistration,
|
||||||
|
expectedResponse: &reportResult{
|
||||||
|
sendNotification: false,
|
||||||
|
report: &protobuf.PushNotificationReport{
|
||||||
|
Success: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "not in allowed mention chat list",
|
||||||
|
pn: &protobuf.PushNotification{
|
||||||
|
Type: protobuf.PushNotification_MENTION,
|
||||||
|
Author: author,
|
||||||
|
ChatId: nonJoinedChatID,
|
||||||
|
AccessToken: accessToken,
|
||||||
|
},
|
||||||
|
registration: validRegistration,
|
||||||
|
expectedResponse: &reportResult{
|
||||||
|
sendNotification: false,
|
||||||
|
report: &protobuf.PushNotificationReport{
|
||||||
|
Success: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, tc := range testCases {
|
||||||
|
s.Run(tc.name, func() {
|
||||||
|
response, err := s.server.buildPushNotificationReport(tc.pn, tc.registration)
|
||||||
|
s.Require().Equal(tc.expectedError, err)
|
||||||
|
s.Require().Equal(tc.expectedResponse, response)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -16,6 +16,7 @@ import (
|
||||||
coretypes "github.com/status-im/status-go/eth-node/core/types"
|
coretypes "github.com/status-im/status-go/eth-node/core/types"
|
||||||
"github.com/status-im/status-go/eth-node/crypto"
|
"github.com/status-im/status-go/eth-node/crypto"
|
||||||
"github.com/status-im/status-go/eth-node/types"
|
"github.com/status-im/status-go/eth-node/types"
|
||||||
|
"github.com/status-im/status-go/protocol/common"
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
|
@ -92,7 +93,7 @@ func (t *TransactionValidator) verifyTransactionSignature(ctx context.Context, f
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t *TransactionValidator) validateTokenTransfer(parameters *CommandParameters, transaction coretypes.Message) (*VerifyTransactionResponse, error) {
|
func (t *TransactionValidator) validateTokenTransfer(parameters *common.CommandParameters, transaction coretypes.Message) (*VerifyTransactionResponse, error) {
|
||||||
|
|
||||||
data := transaction.Data()
|
data := transaction.Data()
|
||||||
if len(data) != tokenTransferDataLength {
|
if len(data) != tokenTransferDataLength {
|
||||||
|
@ -153,7 +154,7 @@ func (t *TransactionValidator) validateToAddress(specifiedTo, actualTo string) b
|
||||||
return t.addresses[actualTo]
|
return t.addresses[actualTo]
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t *TransactionValidator) validateEthereumTransfer(parameters *CommandParameters, transaction coretypes.Message) (*VerifyTransactionResponse, error) {
|
func (t *TransactionValidator) validateEthereumTransfer(parameters *common.CommandParameters, transaction coretypes.Message) (*VerifyTransactionResponse, error) {
|
||||||
toAddress := strings.ToLower(transaction.To().Hex())
|
toAddress := strings.ToLower(transaction.To().Hex())
|
||||||
|
|
||||||
if !t.validateToAddress(parameters.Address, toAddress) {
|
if !t.validateToAddress(parameters.Address, toAddress) {
|
||||||
|
@ -197,7 +198,7 @@ type VerifyTransactionResponse struct {
|
||||||
// The address the transaction was actually sent
|
// The address the transaction was actually sent
|
||||||
Address string
|
Address string
|
||||||
|
|
||||||
Message *Message
|
Message *common.Message
|
||||||
Transaction *TransactionToValidate
|
Transaction *TransactionToValidate
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -205,7 +206,7 @@ type VerifyTransactionResponse struct {
|
||||||
// If a negative response is returned, i.e `Valid` is false, it should
|
// If a negative response is returned, i.e `Valid` is false, it should
|
||||||
// not be retried.
|
// not be retried.
|
||||||
// If an error is returned, validation can be retried.
|
// If an error is returned, validation can be retried.
|
||||||
func (t *TransactionValidator) validateTransaction(ctx context.Context, message coretypes.Message, parameters *CommandParameters, from *ecdsa.PublicKey) (*VerifyTransactionResponse, error) {
|
func (t *TransactionValidator) validateTransaction(ctx context.Context, message coretypes.Message, parameters *common.CommandParameters, from *ecdsa.PublicKey) (*VerifyTransactionResponse, error) {
|
||||||
fromAddress := types.BytesToAddress(message.From().Bytes())
|
fromAddress := types.BytesToAddress(message.From().Bytes())
|
||||||
|
|
||||||
err := t.verifyTransactionSignature(ctx, from, fromAddress, parameters.TransactionHash, parameters.Signature)
|
err := t.verifyTransactionSignature(ctx, from, fromAddress, parameters.TransactionHash, parameters.Signature)
|
||||||
|
@ -268,7 +269,7 @@ func (t *TransactionValidator) ValidateTransactions(ctx context.Context) ([]*Ver
|
||||||
}
|
}
|
||||||
validationResult.Message = message
|
validationResult.Message = message
|
||||||
} else {
|
} else {
|
||||||
commandParameters := &CommandParameters{}
|
commandParameters := &common.CommandParameters{}
|
||||||
commandParameters.TransactionHash = transaction.TransactionHash
|
commandParameters.TransactionHash = transaction.TransactionHash
|
||||||
commandParameters.Signature = transaction.Signature
|
commandParameters.Signature = transaction.Signature
|
||||||
|
|
||||||
|
@ -304,7 +305,7 @@ func (t *TransactionValidator) ValidateTransactions(ctx context.Context) ([]*Ver
|
||||||
return response, nil
|
return response, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t *TransactionValidator) ValidateTransaction(ctx context.Context, parameters *CommandParameters, from *ecdsa.PublicKey) (*VerifyTransactionResponse, error) {
|
func (t *TransactionValidator) ValidateTransaction(ctx context.Context, parameters *common.CommandParameters, from *ecdsa.PublicKey) (*VerifyTransactionResponse, error) {
|
||||||
t.logger.Debug("validating transaction", zap.Any("transaction", parameters), zap.Any("from", from))
|
t.logger.Debug("validating transaction", zap.Any("transaction", parameters), zap.Any("from", from))
|
||||||
hash := parameters.TransactionHash
|
hash := parameters.TransactionHash
|
||||||
c, cancel := context.WithTimeout(ctx, 10*time.Second)
|
c, cancel := context.WithTimeout(ctx, 10*time.Second)
|
||||||
|
|
|
@ -14,6 +14,7 @@ import (
|
||||||
coretypes "github.com/status-im/status-go/eth-node/core/types"
|
coretypes "github.com/status-im/status-go/eth-node/core/types"
|
||||||
"github.com/status-im/status-go/eth-node/crypto"
|
"github.com/status-im/status-go/eth-node/crypto"
|
||||||
"github.com/status-im/status-go/eth-node/types"
|
"github.com/status-im/status-go/eth-node/types"
|
||||||
|
"github.com/status-im/status-go/protocol/common"
|
||||||
"github.com/status-im/status-go/protocol/tt"
|
"github.com/status-im/status-go/protocol/tt"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -105,7 +106,7 @@ func (s *TransactionValidatorSuite) TestValidateTransactions() {
|
||||||
Transaction coretypes.Message
|
Transaction coretypes.Message
|
||||||
OverrideSignatureChatKey *ecdsa.PublicKey
|
OverrideSignatureChatKey *ecdsa.PublicKey
|
||||||
OverrideTransactionHash string
|
OverrideTransactionHash string
|
||||||
Parameters *CommandParameters
|
Parameters *common.CommandParameters
|
||||||
WalletKey *ecdsa.PrivateKey
|
WalletKey *ecdsa.PrivateKey
|
||||||
From *ecdsa.PublicKey
|
From *ecdsa.PublicKey
|
||||||
}{
|
}{
|
||||||
|
@ -123,7 +124,7 @@ func (s *TransactionValidatorSuite) TestValidateTransactions() {
|
||||||
nil,
|
nil,
|
||||||
false,
|
false,
|
||||||
),
|
),
|
||||||
Parameters: &CommandParameters{
|
Parameters: &common.CommandParameters{
|
||||||
Value: "23",
|
Value: "23",
|
||||||
},
|
},
|
||||||
WalletKey: senderWalletKey,
|
WalletKey: senderWalletKey,
|
||||||
|
@ -143,7 +144,7 @@ func (s *TransactionValidatorSuite) TestValidateTransactions() {
|
||||||
nil,
|
nil,
|
||||||
false,
|
false,
|
||||||
),
|
),
|
||||||
Parameters: &CommandParameters{
|
Parameters: &common.CommandParameters{
|
||||||
Value: "23",
|
Value: "23",
|
||||||
Address: strings.ToLower(myAddress1.Hex()),
|
Address: strings.ToLower(myAddress1.Hex()),
|
||||||
},
|
},
|
||||||
|
@ -162,7 +163,7 @@ func (s *TransactionValidatorSuite) TestValidateTransactions() {
|
||||||
nil,
|
nil,
|
||||||
false,
|
false,
|
||||||
),
|
),
|
||||||
Parameters: &CommandParameters{
|
Parameters: &common.CommandParameters{
|
||||||
Value: "23",
|
Value: "23",
|
||||||
Address: strings.ToLower(myAddress1.Hex()),
|
Address: strings.ToLower(myAddress1.Hex()),
|
||||||
},
|
},
|
||||||
|
@ -182,7 +183,7 @@ func (s *TransactionValidatorSuite) TestValidateTransactions() {
|
||||||
nil,
|
nil,
|
||||||
false,
|
false,
|
||||||
),
|
),
|
||||||
Parameters: &CommandParameters{
|
Parameters: &common.CommandParameters{
|
||||||
Value: "23",
|
Value: "23",
|
||||||
Address: strings.ToLower(myAddress1.Hex()),
|
Address: strings.ToLower(myAddress1.Hex()),
|
||||||
},
|
},
|
||||||
|
@ -202,7 +203,7 @@ func (s *TransactionValidatorSuite) TestValidateTransactions() {
|
||||||
false,
|
false,
|
||||||
),
|
),
|
||||||
OverrideTransactionHash: "0xdd9202df5e2f3611b5b6b716aef2a3543cc0bdd7506f50926e0869b83c8383b9",
|
OverrideTransactionHash: "0xdd9202df5e2f3611b5b6b716aef2a3543cc0bdd7506f50926e0869b83c8383b9",
|
||||||
Parameters: &CommandParameters{
|
Parameters: &common.CommandParameters{
|
||||||
Value: "23",
|
Value: "23",
|
||||||
},
|
},
|
||||||
WalletKey: senderWalletKey,
|
WalletKey: senderWalletKey,
|
||||||
|
@ -221,7 +222,7 @@ func (s *TransactionValidatorSuite) TestValidateTransactions() {
|
||||||
nil,
|
nil,
|
||||||
false,
|
false,
|
||||||
),
|
),
|
||||||
Parameters: &CommandParameters{
|
Parameters: &common.CommandParameters{
|
||||||
Value: "23",
|
Value: "23",
|
||||||
Address: strings.ToLower(myAddress2.Hex()),
|
Address: strings.ToLower(myAddress2.Hex()),
|
||||||
},
|
},
|
||||||
|
@ -240,7 +241,7 @@ func (s *TransactionValidatorSuite) TestValidateTransactions() {
|
||||||
nil,
|
nil,
|
||||||
false,
|
false,
|
||||||
),
|
),
|
||||||
Parameters: &CommandParameters{
|
Parameters: &common.CommandParameters{
|
||||||
Value: "23",
|
Value: "23",
|
||||||
},
|
},
|
||||||
WalletKey: senderWalletKey,
|
WalletKey: senderWalletKey,
|
||||||
|
@ -259,7 +260,7 @@ func (s *TransactionValidatorSuite) TestValidateTransactions() {
|
||||||
nil,
|
nil,
|
||||||
false,
|
false,
|
||||||
),
|
),
|
||||||
Parameters: &CommandParameters{
|
Parameters: &common.CommandParameters{
|
||||||
Value: "23",
|
Value: "23",
|
||||||
},
|
},
|
||||||
WalletKey: senderWalletKey,
|
WalletKey: senderWalletKey,
|
||||||
|
@ -279,7 +280,7 @@ func (s *TransactionValidatorSuite) TestValidateTransactions() {
|
||||||
buildData(transferFunction, myAddress1, big.NewInt(int64(23))),
|
buildData(transferFunction, myAddress1, big.NewInt(int64(23))),
|
||||||
false,
|
false,
|
||||||
),
|
),
|
||||||
Parameters: &CommandParameters{
|
Parameters: &common.CommandParameters{
|
||||||
Contract: contractString,
|
Contract: contractString,
|
||||||
Value: "23",
|
Value: "23",
|
||||||
},
|
},
|
||||||
|
@ -300,7 +301,7 @@ func (s *TransactionValidatorSuite) TestValidateTransactions() {
|
||||||
buildData(transferFunction, myAddress1, big.NewInt(int64(23))),
|
buildData(transferFunction, myAddress1, big.NewInt(int64(23))),
|
||||||
false,
|
false,
|
||||||
),
|
),
|
||||||
Parameters: &CommandParameters{
|
Parameters: &common.CommandParameters{
|
||||||
Contract: contractString,
|
Contract: contractString,
|
||||||
Address: strings.ToLower(myAddress1.Hex()),
|
Address: strings.ToLower(myAddress1.Hex()),
|
||||||
Value: "23",
|
Value: "23",
|
||||||
|
@ -322,7 +323,7 @@ func (s *TransactionValidatorSuite) TestValidateTransactions() {
|
||||||
buildData(transferFunction, myAddress1, big.NewInt(int64(13))),
|
buildData(transferFunction, myAddress1, big.NewInt(int64(13))),
|
||||||
false,
|
false,
|
||||||
),
|
),
|
||||||
Parameters: &CommandParameters{
|
Parameters: &common.CommandParameters{
|
||||||
Contract: contractString,
|
Contract: contractString,
|
||||||
Value: "23",
|
Value: "23",
|
||||||
},
|
},
|
||||||
|
@ -341,7 +342,7 @@ func (s *TransactionValidatorSuite) TestValidateTransactions() {
|
||||||
buildData(transferFunction, myAddress1, big.NewInt(int64(23))),
|
buildData(transferFunction, myAddress1, big.NewInt(int64(23))),
|
||||||
false,
|
false,
|
||||||
),
|
),
|
||||||
Parameters: &CommandParameters{
|
Parameters: &common.CommandParameters{
|
||||||
Contract: contractString,
|
Contract: contractString,
|
||||||
Address: strings.ToLower(myAddress1.Hex()),
|
Address: strings.ToLower(myAddress1.Hex()),
|
||||||
Value: "23",
|
Value: "23",
|
||||||
|
@ -362,7 +363,7 @@ func (s *TransactionValidatorSuite) TestValidateTransactions() {
|
||||||
buildData(transferFunction, myAddress1, big.NewInt(int64(23))),
|
buildData(transferFunction, myAddress1, big.NewInt(int64(23))),
|
||||||
false,
|
false,
|
||||||
),
|
),
|
||||||
Parameters: &CommandParameters{
|
Parameters: &common.CommandParameters{
|
||||||
Contract: contractString,
|
Contract: contractString,
|
||||||
Address: strings.ToLower(senderAddress.Hex()),
|
Address: strings.ToLower(senderAddress.Hex()),
|
||||||
Value: "23",
|
Value: "23",
|
||||||
|
@ -383,7 +384,7 @@ func (s *TransactionValidatorSuite) TestValidateTransactions() {
|
||||||
buildData(transferFunction, myAddress2, big.NewInt(int64(23))),
|
buildData(transferFunction, myAddress2, big.NewInt(int64(23))),
|
||||||
false,
|
false,
|
||||||
),
|
),
|
||||||
Parameters: &CommandParameters{
|
Parameters: &common.CommandParameters{
|
||||||
Contract: contractString,
|
Contract: contractString,
|
||||||
Address: strings.ToLower(myAddress1.Hex()),
|
Address: strings.ToLower(myAddress1.Hex()),
|
||||||
Value: "23",
|
Value: "23",
|
||||||
|
@ -403,7 +404,7 @@ func (s *TransactionValidatorSuite) TestValidateTransactions() {
|
||||||
buildData(notTransferFunction, myAddress1, big.NewInt(int64(23))),
|
buildData(notTransferFunction, myAddress1, big.NewInt(int64(23))),
|
||||||
false,
|
false,
|
||||||
),
|
),
|
||||||
Parameters: &CommandParameters{
|
Parameters: &common.CommandParameters{
|
||||||
Contract: contractString,
|
Contract: contractString,
|
||||||
Value: "23",
|
Value: "23",
|
||||||
},
|
},
|
||||||
|
|
|
@ -16,6 +16,7 @@ import (
|
||||||
"github.com/status-im/status-go/eth-node/types"
|
"github.com/status-im/status-go/eth-node/types"
|
||||||
"github.com/status-im/status-go/mailserver"
|
"github.com/status-im/status-go/mailserver"
|
||||||
"github.com/status-im/status-go/protocol"
|
"github.com/status-im/status-go/protocol"
|
||||||
|
"github.com/status-im/status-go/protocol/common"
|
||||||
"github.com/status-im/status-go/protocol/encryption/multidevice"
|
"github.com/status-im/status-go/protocol/encryption/multidevice"
|
||||||
"github.com/status-im/status-go/protocol/protobuf"
|
"github.com/status-im/status-go/protocol/protobuf"
|
||||||
"github.com/status-im/status-go/protocol/pushnotificationclient"
|
"github.com/status-im/status-go/protocol/pushnotificationclient"
|
||||||
|
@ -315,8 +316,8 @@ func (api *PublicAPI) SetInstallationMetadata(installationID string, data *multi
|
||||||
}
|
}
|
||||||
|
|
||||||
type ApplicationMessagesResponse struct {
|
type ApplicationMessagesResponse struct {
|
||||||
Messages []*protocol.Message `json:"messages"`
|
Messages []*common.Message `json:"messages"`
|
||||||
Cursor string `json:"cursor"`
|
Cursor string `json:"cursor"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func (api *PublicAPI) ChatMessages(chatID, cursor string, limit int) (*ApplicationMessagesResponse, error) {
|
func (api *PublicAPI) ChatMessages(chatID, cursor string, limit int) (*ApplicationMessagesResponse, error) {
|
||||||
|
@ -355,7 +356,7 @@ func (api *PublicAPI) UpdateMessageOutgoingStatus(id, newOutgoingStatus string)
|
||||||
return api.service.messenger.UpdateMessageOutgoingStatus(id, newOutgoingStatus)
|
return api.service.messenger.UpdateMessageOutgoingStatus(id, newOutgoingStatus)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (api *PublicAPI) SendChatMessage(ctx context.Context, message *protocol.Message) (*protocol.MessengerResponse, error) {
|
func (api *PublicAPI) SendChatMessage(ctx context.Context, message *common.Message) (*protocol.MessengerResponse, error) {
|
||||||
return api.service.messenger.SendChatMessage(ctx, message)
|
return api.service.messenger.SendChatMessage(ctx, message)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -505,6 +506,22 @@ func (api *PublicAPI) DisablePushNotificationsFromContactsOnly(ctx context.Conte
|
||||||
return api.service.messenger.DisablePushNotificationsFromContactsOnly()
|
return api.service.messenger.DisablePushNotificationsFromContactsOnly()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (api *PublicAPI) EnablePushNotificationsBlockMentions(ctx context.Context) error {
|
||||||
|
err := api.service.accountsDB.SaveSetting("push-notifications-block-mentions?", true)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return api.service.messenger.EnablePushNotificationsBlockMentions()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (api *PublicAPI) DisablePushNotificationsBlockMentions(ctx context.Context) error {
|
||||||
|
err := api.service.accountsDB.SaveSetting("push-notifications-block-mentions?", false)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return api.service.messenger.DisablePushNotificationsBlockMentions()
|
||||||
|
}
|
||||||
|
|
||||||
func (api *PublicAPI) AddPushNotificationsServer(ctx context.Context, publicKeyBytes types.HexBytes) error {
|
func (api *PublicAPI) AddPushNotificationsServer(ctx context.Context, publicKeyBytes types.HexBytes) error {
|
||||||
publicKey, err := crypto.UnmarshalPubkey(publicKeyBytes)
|
publicKey, err := crypto.UnmarshalPubkey(publicKeyBytes)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
|
@ -484,6 +484,7 @@ func buildMessengerOptions(
|
||||||
|
|
||||||
options = append(options, protocol.WithPushNotificationClientConfig(&pushnotificationclient.Config{
|
options = append(options, protocol.WithPushNotificationClientConfig(&pushnotificationclient.Config{
|
||||||
DefaultServers: config.DefaultPushNotificationsServers,
|
DefaultServers: config.DefaultPushNotificationsServers,
|
||||||
|
BlockMentions: settings.PushNotificationsBlockMentions,
|
||||||
SendEnabled: settings.SendPushNotifications,
|
SendEnabled: settings.SendPushNotifications,
|
||||||
AllowFromContactsOnly: settings.PushNotificationsFromContactsOnly,
|
AllowFromContactsOnly: settings.PushNotificationsFromContactsOnly,
|
||||||
RemoteNotificationsEnabled: settings.RemotePushNotificationsEnabled,
|
RemoteNotificationsEnabled: settings.RemotePushNotificationsEnabled,
|
||||||
|
|
|
@ -4,6 +4,7 @@ package shhext
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
"github.com/status-im/status-go/protocol/common"
|
||||||
|
|
||||||
"github.com/ethereum/go-ethereum/log"
|
"github.com/ethereum/go-ethereum/log"
|
||||||
|
|
||||||
|
@ -465,8 +466,8 @@ func (api *NimbusPublicAPI) VerifyENSNames(details []enstypes.ENSDetails) (map[s
|
||||||
}
|
}
|
||||||
|
|
||||||
type ApplicationMessagesResponse struct {
|
type ApplicationMessagesResponse struct {
|
||||||
Messages []*protocol.Message `json:"messages"`
|
Messages []*common.Message `json:"messages"`
|
||||||
Cursor string `json:"cursor"`
|
Cursor string `json:"cursor"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func (api *NimbusPublicAPI) ChatMessages(chatID, cursor string, limit int) (*ApplicationMessagesResponse, error) {
|
func (api *NimbusPublicAPI) ChatMessages(chatID, cursor string, limit int) (*ApplicationMessagesResponse, error) {
|
||||||
|
@ -501,7 +502,7 @@ func (api *PublicAPI) StartMessenger() error {
|
||||||
return api.service.StartMessenger()
|
return api.service.StartMessenger()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (api *NimbusPublicAPI) SendChatMessage(ctx context.Context, message *protocol.Message) (*protocol.MessengerResponse, error) {
|
func (api *NimbusPublicAPI) SendChatMessage(ctx context.Context, message *common.Message) (*protocol.MessengerResponse, error) {
|
||||||
return api.service.messenger.SendChatMessage(ctx, message)
|
return api.service.messenger.SendChatMessage(ctx, message)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue