status-go/protocol/messenger_messages.go

113 lines
2.8 KiB
Go

package protocol
import (
"context"
"errors"
"github.com/status-im/status-go/protocol/common"
"github.com/status-im/status-go/protocol/protobuf"
"github.com/status-im/status-go/protocol/requests"
)
var ErrInvalidEditAuthor = errors.New("sender is not the author of the message")
var ErrInvalidEditContentType = errors.New("only text messages can be replaced")
func (m *Messenger) EditMessage(ctx context.Context, request *requests.EditMessage) (*MessengerResponse, error) {
err := request.Validate()
if err != nil {
return nil, err
}
message, err := m.persistence.MessageByID(request.ID.String())
if err != nil {
return nil, err
}
if message.From != common.PubkeyToHex(&m.identity.PublicKey) {
return nil, ErrInvalidEditAuthor
}
if message.ContentType != protobuf.ChatMessage_TEXT_PLAIN {
return nil, ErrInvalidEditContentType
}
// A valid added chat is required.
chat, ok := m.allChats.Load(message.ChatId)
if !ok {
return nil, errors.New("Chat not found")
}
clock, _ := chat.NextClockAndTimestamp(m.getTimesource())
editMessage := &EditMessage{}
editMessage.Text = request.Text
editMessage.ChatId = message.ChatId
editMessage.MessageId = request.ID.String()
editMessage.Clock = clock
err = m.applyEditMessage(&editMessage.EditMessage, message)
if err != nil {
return nil, err
}
encodedMessage, err := m.encodeChatEntity(chat, editMessage)
if err != nil {
return nil, err
}
rawMessage := common.RawMessage{
LocalChatID: chat.ID,
Payload: encodedMessage,
MessageType: protobuf.ApplicationMetadataMessage_EDIT_MESSAGE,
SkipGroupMessageWrap: true,
ResendAutomatically: true,
}
_, err = m.dispatchMessage(ctx, rawMessage)
if err != nil {
return nil, err
}
if chat.LastMessage != nil && chat.LastMessage.ID == message.ID {
chat.LastMessage = message
err := m.saveChat(chat)
if err != nil {
return nil, err
}
}
response := &MessengerResponse{}
response.AddMessage(message)
response.AddChat(chat)
return response, nil
}
func (m *Messenger) applyEditMessage(editMessage *protobuf.EditMessage, message *common.Message) error {
if err := ValidateText(editMessage.Text); err != nil {
return err
}
message.Text = editMessage.Text
message.EditedAt = editMessage.Clock
// Save original message as edit so we can retrieve history
if message.EditedAt == 0 {
originalEdit := EditMessage{}
originalEdit.Clock = message.Clock
originalEdit.LocalChatID = message.LocalChatID
originalEdit.MessageId = message.ID
originalEdit.Text = message.Text
originalEdit.From = message.From
err := m.persistence.SaveEdit(originalEdit)
if err != nil {
return err
}
}
err := message.PrepareContent(common.PubkeyToHex(&m.identity.PublicKey))
if err != nil {
return err
}
return m.persistence.SaveMessages([]*common.Message{message})
}