Send notification when your contact invites you to group chat (#2361)

This commit is contained in:
Brian Sztamfater 2021-09-27 11:02:25 -03:00 committed by GitHub
parent da63894a5a
commit d65494d1f8
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 143 additions and 3 deletions

View File

@ -465,6 +465,9 @@ func (m *Message) GetSimplifiedText(identity string, canonicalNames map[string]s
if m.ContentType == protobuf.ChatMessage_COMMUNITY {
return "Community", nil
}
if m.ContentType == protobuf.ChatMessage_SYSTEM_MESSAGE_CONTENT_PRIVATE_GROUP {
return "Group", nil
}
if m.ParsedTextAst == nil {
err := m.PrepareContent(identity)

View File

@ -74,6 +74,15 @@ func NewCommunityRequestToJoinNotification(id string, community *communities.Com
return body.toCommunityRequestToJoinNotification(id)
}
func NewPrivateGroupInviteNotification(id string, chat *Chat, contact *Contact) *localnotifications.Notification {
body := &NotificationBody{
Chat: chat,
Contact: contact,
}
return body.toPrivateGroupInviteNotification(id)
}
func (n NotificationBody) toMessageNotification(id string, contacts *contactMap) (*localnotifications.Notification, error) {
var title string
if n.Chat.PrivateGroupChat() || n.Chat.Public() || n.Chat.CommunityChat() {
@ -123,6 +132,24 @@ func (n NotificationBody) toMessageNotification(id string, contacts *contactMap)
}, nil
}
func (n NotificationBody) toPrivateGroupInviteNotification(id string) *localnotifications.Notification {
return &localnotifications.Notification{
ID: gethcommon.HexToHash(id),
Body: n,
Title: n.Contact.CanonicalName() + " invited you to " + n.Chat.Name,
Message: n.Contact.CanonicalName() + " wants you to join group " + n.Chat.Name,
BodyType: localnotifications.TypeMessage,
Category: localnotifications.CategoryGroupInvite,
Deeplink: n.Chat.DeepLink(),
Author: localnotifications.NotificationAuthor{
Name: n.Contact.CanonicalName(),
Icon: n.Contact.CanonicalImage(),
ID: n.Contact.ID,
},
Image: "",
}
}
func (n NotificationBody) toCommunityRequestToJoinNotification(id string) *localnotifications.Notification {
return &localnotifications.Notification{
ID: gethcommon.HexToHash(id),

View File

@ -60,6 +60,7 @@ func (m *Messenger) HandleMembershipUpdate(messageState *ReceivedMessageState, c
//if chat.InvitationAdmin exists means we are waiting for invitation request approvement, and in that case
//we need to create a new chat instance like we don't have a chat and just use a regular invitation flow
waitingForApproval := chat != nil && len(chat.InvitationAdmin) > 0
ourKey := contactIDFromPublicKey(&m.identity.PublicKey)
if chat == nil || waitingForApproval {
if len(message.Events) == 0 {
@ -96,7 +97,6 @@ func (m *Messenger) HandleMembershipUpdate(messageState *ReceivedMessageState, c
return err
}
ourKey := contactIDFromPublicKey(&m.identity.PublicKey)
// A new chat must contain us
if !group.IsMember(ourKey) {
return errors.New("can't create a new group chat without us being a member")
@ -107,6 +107,16 @@ func (m *Messenger) HandleMembershipUpdate(messageState *ReceivedMessageState, c
isActive := messageState.CurrentMessageState.Contact.IsAdded() || messageState.CurrentMessageState.Contact.ID == ourKey || waitingForApproval
newChat.Active = isActive
chat = &newChat
chat.updateChatFromGroupMembershipChanges(group)
if err != nil {
return errors.Wrap(err, "failed to get group creator")
}
if chat.Active && messageState.CurrentMessageState.Contact.ID != ourKey {
messageState.Response.AddNotification(NewPrivateGroupInviteNotification(chat.ID, chat, messageState.CurrentMessageState.Contact))
}
} else {
existingGroup, err := newProtocolGroupFromChat(chat)
if err != nil {
@ -121,10 +131,9 @@ func (m *Messenger) HandleMembershipUpdate(messageState *ReceivedMessageState, c
if err != nil {
return errors.Wrap(err, "failed to create a group with new membership updates")
}
chat.updateChatFromGroupMembershipChanges(group)
}
chat.updateChatFromGroupMembershipChanges(group)
if !chat.Active {
m.createMessageNotification(chat, messageState)
}
@ -181,6 +190,7 @@ func (m *Messenger) createMessageNotification(chat *Chat, messageState *Received
Timestamp: messageState.CurrentMessageState.WhisperTimestamp,
ChatID: chat.ID,
}
err := m.addActivityCenterNotification(messageState, notification)
if err != nil {
m.logger.Warn("failed to create activity center notification", zap.Error(err))

View File

@ -1,11 +1,20 @@
package protocol
import (
"crypto/ecdsa"
"testing"
"github.com/stretchr/testify/suite"
"go.uber.org/zap"
gethbridge "github.com/status-im/status-go/eth-node/bridge/geth"
"github.com/status-im/status-go/eth-node/crypto"
"github.com/status-im/status-go/eth-node/types"
"github.com/status-im/status-go/protocol/protobuf"
"github.com/status-im/status-go/protocol/tt"
v1protocol "github.com/status-im/status-go/protocol/v1"
localnotifications "github.com/status-im/status-go/services/local-notifications"
"github.com/status-im/status-go/waku"
)
func TestEventToSystemMessageSuite(t *testing.T) {
@ -14,6 +23,37 @@ func TestEventToSystemMessageSuite(t *testing.T) {
type EventToSystemMessageSuite struct {
suite.Suite
m *Messenger // main instance of Messenger
privateKey *ecdsa.PrivateKey // private key for the main instance of Messenger
// If one wants to send messages between different instances of Messenger,
// a single waku service should be shared.
shh types.Waku
logger *zap.Logger
}
func (s *EventToSystemMessageSuite) newMessenger() *Messenger {
privateKey, err := crypto.GenerateKey()
s.Require().NoError(err)
messenger, err := newMessengerWithKey(s.shh, privateKey, s.logger, nil)
s.Require().NoError(err)
return messenger
}
func (s *EventToSystemMessageSuite) SetupTest() {
s.logger = tt.MustCreateTestLogger()
config := waku.DefaultConfig
config.MinimumAcceptedPoW = 0
shh := waku.New(&config, s.logger)
s.shh = gethbridge.NewGethWakuWrapper(shh)
s.Require().NoError(shh.Start())
s.m = s.newMessenger()
s.privateKey = s.m.identity
_, err := s.m.Start()
s.Require().NoError(err)
}
func (s *EventToSystemMessageSuite) TestRun() {
@ -78,3 +118,62 @@ func (s *EventToSystemMessageSuite) TestRun() {
}
}
func (s *EventToSystemMessageSuite) TestHandleMembershipUpdate() {
adminPrivateKey, err := crypto.GenerateKey()
s.Require().NoError(err)
adminPublicKey := types.EncodeHex(crypto.FromECDSAPub(&adminPrivateKey.PublicKey))
ourPublicKey := types.EncodeHex(crypto.FromECDSAPub(&s.m.identity.PublicKey))
event1 := v1protocol.MembershipUpdateEvent{
Type: protobuf.MembershipUpdateEvent_CHAT_CREATED,
Name: "test",
ChatID: "test-" + adminPublicKey,
ClockValue: 100,
}
err = event1.Sign(adminPrivateKey)
s.Require().NoError(err)
event2 := v1protocol.MembershipUpdateEvent{
Type: protobuf.MembershipUpdateEvent_MEMBERS_ADDED,
Members: []string{adminPublicKey, ourPublicKey},
ChatID: "test-" + adminPublicKey,
ClockValue: 100,
}
err = event2.Sign(adminPrivateKey)
s.Require().NoError(err)
testMembershipUpdateMessageStruct2 := v1protocol.MembershipUpdateMessage{
ChatID: "test-" + adminPublicKey,
Events: []v1protocol.MembershipUpdateEvent{
event1,
event2,
},
}
rawMembershipUpdateMessage2, err := testMembershipUpdateMessageStruct2.ToProtobuf()
s.Require().NoError(err)
contact, err := BuildContactFromPublicKey(&adminPrivateKey.PublicKey)
s.Require().NoError(err)
contact.SystemTags = []string{contactAdded}
currentMessageState := &CurrentMessageState{
Contact: contact,
}
state := &ReceivedMessageState{
Response: &MessengerResponse{},
Timesource: s.m.transport,
CurrentMessageState: currentMessageState,
ExistingMessagesMap: map[string]bool{},
AllChats: s.m.allChats,
}
err = s.m.HandleMembershipUpdate(state, nil, *rawMembershipUpdateMessage2, defaultSystemMessagesTranslations)
s.Require().NoError(err)
s.Require().Len(state.Response.Notifications(), 1)
s.Require().Equal(state.Response.Notifications()[0].Category, localnotifications.CategoryGroupInvite)
}

View File

@ -3,6 +3,7 @@ package localnotifications
const (
CategoryTransaction PushCategory = "transaction"
CategoryMessage PushCategory = "newMessage"
CategoryGroupInvite PushCategory = "groupInvite"
CategoryCommunityRequestToJoin = "communityRequestToJoin"
TypeTransaction NotificationType = "transaction"