From 7b230d5c9d27e175b7101d165d1586427ef52583 Mon Sep 17 00:00:00 2001 From: Samuel Hawksby-Robinson Date: Wed, 18 Nov 2020 12:41:36 +0000 Subject: [PATCH] Updated message handling from public and private chat --- images/database.go | 10 +----- images/encode.go | 12 +++++++ protocol/message_handler.go | 63 ++++++++++++++++++++++++++++++++++++- protocol/messenger.go | 35 ++++++++++++++++----- 4 files changed, 103 insertions(+), 17 deletions(-) diff --git a/images/database.go b/images/database.go index 15ac467fb..63b8f2fff 100644 --- a/images/database.go +++ b/images/database.go @@ -3,7 +3,6 @@ package images import ( "context" "database/sql" - "encoding/base64" "encoding/json" "errors" ) @@ -114,14 +113,7 @@ func (i IdentityImage) GetType() (ImageType, error) { } func (i IdentityImage) GetDataURI() (string, error) { - mt, err := GetMimeType(i.Payload) - if err != nil { - return "", err - } - - b64 := base64.StdEncoding.EncodeToString(i.Payload) - - return "data:image/" + mt + ";base64," + b64, nil + return GetPayloadDataURI(i.Payload) } func (i IdentityImage) MarshalJSON() ([]byte, error) { diff --git a/images/encode.go b/images/encode.go index 03ba5d767..5422b8ec3 100644 --- a/images/encode.go +++ b/images/encode.go @@ -2,6 +2,7 @@ package images import ( "bytes" + "encoding/base64" "fmt" "image" "image/jpeg" @@ -55,3 +56,14 @@ func EncodeToBestSize(bb *bytes.Buffer, img image.Image, size ResizeDimension) e return nil } + +func GetPayloadDataURI(payload []byte) (string, error) { + mt, err := GetMimeType(payload) + if err != nil { + return "", err + } + + b64 := base64.StdEncoding.EncodeToString(payload) + + return "data:image/" + mt + ";base64," + b64, nil +} diff --git a/protocol/message_handler.go b/protocol/message_handler.go index 103c45251..ae13ae8ce 100644 --- a/protocol/message_handler.go +++ b/protocol/message_handler.go @@ -4,8 +4,8 @@ import ( "crypto/ecdsa" "encoding/hex" "fmt" - "github.com/pkg/errors" + "github.com/status-im/status-go/images" "go.uber.org/zap" "github.com/status-im/status-go/eth-node/crypto" @@ -799,3 +799,64 @@ func (m *MessageHandler) HandleGroupChatInvitation(state *ReceivedMessageState, return nil } + +// HandleChatIdentity handles an incoming protobuf.ChatIdentity +// extracts contact information stored in the protobuf and adds it to the user's contact for update. +func (m *MessageHandler) HandleChatIdentity(state *ReceivedMessageState, ci protobuf.ChatIdentity) error { + logger := m.logger.With(zap.String("site", "HandleChatIdentity")) + contact := state.CurrentMessageState.Contact + chat, ok := state.AllChats[contact.ID] + if !ok { + chat = OneToOneFromPublicKey(state.CurrentMessageState.PublicKey, state.Timesource) + // We don't want to show the chat to the user + chat.Active = false + } + + logger.Info("Handling contact update") + + // TODO investigate potential race condition where user updates this contact's details and the contact update's + // clock value is just less than the ChatIdentity clock and the ChatIdentity is processed first. + // In this case the contact update would not be processed + // + // TODO Potential fix: create an ChatIdentity last updated field on the contact table. + if contact.LastUpdated < ci.Clock { + logger.Info("Updating contact") + if !contact.HasBeenAdded() && contact.ID != contactIDFromPublicKey(&m.identity.PublicKey) { + contact.SystemTags = append(contact.SystemTags, contactRequestReceived) + } + + // TODO handle ENS things + /* if contact.Name != message.EnsName { + contact.Name = message.EnsName + contact.ENSVerified = false + } */ + + // Get the largest + var name string + var iiSize int + for n, ii := range ci.Images { + if iiSize < len(ii.Payload) { + iiSize = len(ii.Payload) + name = n + } + } + + dataUri, err := images.GetPayloadDataURI(ci.Images[name].Payload) + if err != nil { + return err + } + contact.Photo = dataUri + contact.LastUpdated = ci.Clock + state.ModifiedContacts[contact.ID] = true + state.AllContacts[contact.ID] = contact + } + + if chat.LastClockValue < ci.Clock { + chat.LastClockValue = ci.Clock + } + + state.ModifiedChats[chat.ID] = true + state.AllChats[chat.ID] = chat + + return nil +} diff --git a/protocol/messenger.go b/protocol/messenger.go index 4393863ff..6b3ca062b 100644 --- a/protocol/messenger.go +++ b/protocol/messenger.go @@ -456,16 +456,17 @@ func (m *Messenger) handleSendContactCode() error { m.logger.Error("could not build contact code advertisement", zap.Error(err)) } + if contactCodeAdvertisement == nil { + contactCodeAdvertisement = &protobuf.ContactCodeAdvertisement{} + } err = m.handleContactCodeChatIdentity(contactCodeAdvertisement) if err != nil { return err } - if contactCodeAdvertisement != nil { - payload, err = proto.Marshal(contactCodeAdvertisement) - if err != nil { - return err - } + payload, err = proto.Marshal(contactCodeAdvertisement) + if err != nil { + return err } contactCodeTopic := transport.ContactCodeTopic(&m.identity.PublicKey) @@ -562,7 +563,7 @@ func (m *Messenger) shouldPublishChatIdentity(chatId string) (bool, error) { // createChatIdentity creates a context based protobuf.ChatIdentity. // context 'public-chat' will attach only the 'thumbnail' IdentityImage -// contect 'private-chat' will attach all IdentityImage +// context 'private-chat' will attach all IdentityImage func (m *Messenger) createChatIdentity(context string) (*protobuf.ChatIdentity, error) { ci := &protobuf.ChatIdentity{ Clock: m.transport.GetCurrentTime(), @@ -2665,13 +2666,26 @@ func (m *Messenger) handleRetrievedMessages(chatWithMessages map[transport.Filte continue case protobuf.ContactCodeAdvertisement: logger.Debug("Received ContactCodeAdvertisement") + + cca := msg.ParsedMessage.Interface().(protobuf.ContactCodeAdvertisement) + if cca.ChatIdentity != nil { + + logger.Debug("Received ContactCodeAdvertisement ChatIdentity") + err = m.handler.HandleChatIdentity(messageState, *cca.ChatIdentity) + if err != nil { + logger.Warn("failed to handle ContactCodeAdvertisement ChatIdentity", zap.Error(err)) + // No continue as Chat Identity may fail but the rest of the cca may process fine. + } + } + if m.pushNotificationClient == nil { continue } logger.Debug("Handling ContactCodeAdvertisement") - if err := m.pushNotificationClient.HandleContactCodeAdvertisement(publicKey, msg.ParsedMessage.Interface().(protobuf.ContactCodeAdvertisement)); err != nil { + if err := m.pushNotificationClient.HandleContactCodeAdvertisement(publicKey, cca); err != nil { logger.Warn("failed to handle ContactCodeAdvertisement", zap.Error(err)) } + // We continue in any case, no changes to messenger continue @@ -2724,6 +2738,13 @@ func (m *Messenger) handleRetrievedMessages(chatWithMessages map[transport.Filte logger.Warn("failed to handle GroupChatInvitation", zap.Error(err)) continue } + case protobuf.ChatIdentity: + logger.Debug("Received ChatIdentity") + err = m.handler.HandleChatIdentity(messageState, msg.ParsedMessage.Interface().(protobuf.ChatIdentity)) + if err != nil { + logger.Warn("failed to handle ChatIdentity", zap.Error(err)) + continue + } default: // Check if is an encrypted PushNotificationRegistration