2019-11-21 16:19:22 +00:00
|
|
|
package protocol
|
2019-10-14 14:10:48 +00:00
|
|
|
|
|
|
|
import (
|
|
|
|
"github.com/pkg/errors"
|
|
|
|
|
2019-11-21 16:19:22 +00:00
|
|
|
v1protocol "github.com/status-im/status-go/protocol/v1"
|
2019-10-14 14:10:48 +00:00
|
|
|
)
|
|
|
|
|
|
|
|
type persistentMessageHandler struct {
|
|
|
|
persistence *sqlitePersistence
|
|
|
|
}
|
|
|
|
|
|
|
|
func newPersistentMessageHandler(persistence *sqlitePersistence) *persistentMessageHandler {
|
|
|
|
return &persistentMessageHandler{persistence: persistence}
|
|
|
|
}
|
|
|
|
|
|
|
|
// HandleMembershipUpdate updates a Chat instance according to the membership updates.
|
|
|
|
// It retrieves chat, if exists, and merges membership updates from the message.
|
|
|
|
// Finally, the Chat is updated with the new group events.
|
2019-11-21 16:19:22 +00:00
|
|
|
func (h *persistentMessageHandler) HandleMembershipUpdate(m v1protocol.MembershipUpdateMessage) error {
|
2019-10-14 14:10:48 +00:00
|
|
|
chat, err := h.chatID(m.ChatID)
|
|
|
|
switch err {
|
|
|
|
case errChatNotFound:
|
2019-11-21 16:19:22 +00:00
|
|
|
group, err := v1protocol.NewGroupWithMembershipUpdates(m.ChatID, m.Updates)
|
2019-10-14 14:10:48 +00:00
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
newChat := createGroupChat()
|
|
|
|
newChat.updateChatFromProtocolGroup(group)
|
|
|
|
chat = &newChat
|
|
|
|
case nil:
|
|
|
|
existingGroup, err := newProtocolGroupFromChat(chat)
|
|
|
|
if err != nil {
|
|
|
|
return errors.Wrap(err, "failed to create a Group from Chat")
|
|
|
|
}
|
2019-11-21 16:19:22 +00:00
|
|
|
updateGroup, err := v1protocol.NewGroupWithMembershipUpdates(m.ChatID, m.Updates)
|
2019-10-14 14:10:48 +00:00
|
|
|
if err != nil {
|
|
|
|
return errors.Wrap(err, "invalid membership update")
|
|
|
|
}
|
2019-11-21 16:19:22 +00:00
|
|
|
merged := v1protocol.MergeFlatMembershipUpdates(existingGroup.Updates(), updateGroup.Updates())
|
|
|
|
newGroup, err := v1protocol.NewGroup(chat.ID, merged)
|
2019-10-14 14:10:48 +00:00
|
|
|
if err != nil {
|
|
|
|
return errors.Wrap(err, "failed to create a group with new membership updates")
|
|
|
|
}
|
|
|
|
chat.updateChatFromProtocolGroup(newGroup)
|
|
|
|
default:
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
return h.persistence.SaveChat(*chat)
|
|
|
|
}
|
|
|
|
|
|
|
|
func (h *persistentMessageHandler) chatID(chatID string) (*Chat, error) {
|
|
|
|
var chat *Chat
|
|
|
|
chats, err := h.persistence.Chats()
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
for _, ch := range chats {
|
Move to protobuf for Message type (#1706)
* Use a single Message type `v1/message.go` and `message.go` are the same now, and they embed `protobuf.ChatMessage`
* Use `SendChatMessage` for sending chat messages, this is basically the old `Send` but a bit more flexible so we can send different message types (stickers,commands), and not just text.
* Remove dedup from services/shhext. Because now we process in status-protocol, dedup makes less sense, as those messages are going to be processed anyway, so removing for now, we can re-evaluate if bringing it to status-go or not.
* Change the various retrieveX method to a single one:
`RetrieveAll` will be processing those messages that it can process (Currently only `Message`), and return the rest in `RawMessages` (still transit). The format for the response is:
`Chats`: -> The chats updated by receiving the message
`Messages`: -> The messages retrieved (already matched to a chat)
`Contacts`: -> The contacts updated by the messages
`RawMessages` -> Anything else that can't be parsed, eventually as we move everything to status-protocol-go this will go away.
2019-12-05 16:25:34 +00:00
|
|
|
if ch.ID == chatID {
|
2019-10-14 14:10:48 +00:00
|
|
|
chat = ch
|
|
|
|
break
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if chat == nil {
|
|
|
|
return nil, errChatNotFound
|
|
|
|
}
|
|
|
|
return chat, nil
|
|
|
|
}
|