Use same message with flag for emoji retraction and use compound id
This commit is contained in:
parent
2bf1991190
commit
5a178939de
|
@ -2,9 +2,13 @@ package protocol
|
|||
|
||||
import (
|
||||
"crypto/ecdsa"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
|
||||
"github.com/golang/protobuf/proto"
|
||||
|
||||
"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"
|
||||
)
|
||||
|
||||
|
@ -13,19 +17,18 @@ import (
|
|||
type EmojiReaction struct {
|
||||
protobuf.EmojiReaction
|
||||
|
||||
// ID calculated as keccak256(compressedAuthorPubKey, data) where data is unencrypted payload.
|
||||
ID string
|
||||
|
||||
// From is a public key of the author of the emoji reaction.
|
||||
From string
|
||||
|
||||
// Retracted represents whether the user has chosen to remove a previously given reaction
|
||||
Retracted bool
|
||||
From string `json:"from,omitempty"`
|
||||
|
||||
// SigPubKey is the ecdsa encoded public key of the emoji reaction author
|
||||
SigPubKey *ecdsa.PublicKey `json:"-"`
|
||||
}
|
||||
|
||||
// ID is the Keccak256() contatenation of From-ChatID-MessageID-EmojiType
|
||||
func (e EmojiReaction) ID() string {
|
||||
return types.EncodeHex(crypto.Keccak256([]byte(fmt.Sprintf("%s%s%s%d", e.From, e.ChatId, e.MessageId, e.Type))))
|
||||
}
|
||||
|
||||
// GetSigPubKey returns an ecdsa encoded public key
|
||||
// this function is required to implement the ChatEntity interface
|
||||
func (e EmojiReaction) GetSigPubKey() *ecdsa.PublicKey {
|
||||
|
@ -43,3 +46,16 @@ func (e EmojiReaction) GetProtobuf() proto.Message {
|
|||
func (e *EmojiReaction) SetMessageType(messageType protobuf.MessageType) {
|
||||
e.MessageType = messageType
|
||||
}
|
||||
|
||||
func (e *EmojiReaction) MarshalJSON() ([]byte, error) {
|
||||
type EmojiAlias EmojiReaction
|
||||
item := struct {
|
||||
*EmojiAlias
|
||||
ID string `json:"id"`
|
||||
}{
|
||||
EmojiAlias: (*EmojiAlias)(e),
|
||||
ID: e.ID(),
|
||||
}
|
||||
|
||||
return json.Marshal(item)
|
||||
}
|
||||
|
|
|
@ -670,10 +670,22 @@ func (m *MessageHandler) messageExists(messageID string, existingMessagesMap map
|
|||
|
||||
func (m *MessageHandler) HandleEmojiReaction(state *ReceivedMessageState, pbEmojiR protobuf.EmojiReaction) error {
|
||||
logger := m.logger.With(zap.String("site", "HandleEmojiReaction"))
|
||||
from := state.CurrentMessageState.Contact.ID
|
||||
|
||||
// check that the user can actually send an emoji for this message
|
||||
existingEmoji, err := m.persistence.EmojiReactionByFromMessageIDAndType(from, pbEmojiR.MessageId, pbEmojiR.Type)
|
||||
if err != errRecordNotFound && err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if existingEmoji != nil && existingEmoji.Clock >= pbEmojiR.Clock {
|
||||
// this is not a valid emoji, ignoring
|
||||
return nil
|
||||
}
|
||||
|
||||
emojiReaction := &EmojiReaction{
|
||||
EmojiReaction: pbEmojiR,
|
||||
ID: state.CurrentMessageState.MessageID,
|
||||
From: state.CurrentMessageState.Contact.ID,
|
||||
From: from,
|
||||
SigPubKey: state.CurrentMessageState.PublicKey,
|
||||
}
|
||||
chat, err := m.matchChatEntity(emojiReaction, state.AllChats, state.Timesource)
|
||||
|
@ -681,6 +693,7 @@ func (m *MessageHandler) HandleEmojiReaction(state *ReceivedMessageState, pbEmoj
|
|||
return err // matchChatEntity returns a descriptive error message
|
||||
}
|
||||
|
||||
// TODO: make sure the user can actualy send an emoji for this chat.
|
||||
logger.Info("Handling emoji reaction")
|
||||
|
||||
if chat.LastClockValue < pbEmojiR.Clock {
|
||||
|
@ -690,9 +703,13 @@ func (m *MessageHandler) HandleEmojiReaction(state *ReceivedMessageState, pbEmoj
|
|||
state.ModifiedChats[chat.ID] = true
|
||||
state.AllChats[chat.ID] = chat
|
||||
|
||||
return nil
|
||||
}
|
||||
// save emoji reaction
|
||||
err = m.persistence.SaveEmojiReaction(emojiReaction)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
state.EmojiReactions[emojiReaction.ID()] = emojiReaction
|
||||
|
||||
func (m *MessageHandler) HandleEmojiReactionRetraction(state *ReceivedMessageState, pbEmojiR protobuf.EmojiReactionRetraction) error {
|
||||
return nil
|
||||
}
|
||||
|
|
|
@ -707,56 +707,25 @@ func (db sqlitePersistence) BlockContact(contact *Contact) ([]*Chat, error) {
|
|||
}
|
||||
|
||||
func (db sqlitePersistence) SaveEmojiReaction(emojiReaction *EmojiReaction) (err error) {
|
||||
tx, err := db.db.BeginTx(context.Background(), &sql.TxOptions{})
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
defer func() {
|
||||
if err == nil {
|
||||
err = tx.Commit()
|
||||
return
|
||||
}
|
||||
// don't shadow original error
|
||||
_ = tx.Rollback()
|
||||
}()
|
||||
|
||||
allFields := db.tableEmojiReactionsAllFields()
|
||||
valuesVector := strings.Repeat("?, ", db.tableEmojiReactionsAllFieldsCount()-1) + "?"
|
||||
query := "INSERT INTO emoji_reactions(" + allFields + ") VALUES (" + valuesVector + ")" // nolint: gosec
|
||||
stmt, err := tx.Prepare(query)
|
||||
query := "INSERT INTO emoji_reactions(id,clock_value,source,emoji_id,message_id,chat_id,retracted) VALUES (?,?,?,?,?,?,?)"
|
||||
stmt, err := db.db.Prepare(query)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
allValues := []interface{}{
|
||||
emojiReaction.ID,
|
||||
_, err = stmt.Exec(
|
||||
emojiReaction.ID(),
|
||||
emojiReaction.Clock,
|
||||
emojiReaction.From,
|
||||
emojiReaction.Type,
|
||||
emojiReaction.MessageId,
|
||||
emojiReaction.ChatId,
|
||||
emojiReaction.Retracted,
|
||||
}
|
||||
|
||||
_, err = stmt.Exec(allValues...)
|
||||
)
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
func (db sqlitePersistence) tableEmojiReactionsAllFields() string {
|
||||
return `id,
|
||||
clock_value,
|
||||
source,
|
||||
emoji_id,
|
||||
message_id,
|
||||
chat_id,
|
||||
retracted`
|
||||
}
|
||||
|
||||
func (db sqlitePersistence) tableEmojiReactionsAllFieldsCount() int {
|
||||
return strings.Count(db.tableEmojiReactionsAllFields(), ",") + 1
|
||||
}
|
||||
|
||||
func (db sqlitePersistence) EmojiReactionByID(id string) (*EmojiReaction, error) {
|
||||
tx, err := db.db.BeginTx(context.Background(), &sql.TxOptions{})
|
||||
if err != nil {
|
||||
|
@ -772,20 +741,21 @@ func (db sqlitePersistence) EmojiReactionByID(id string) (*EmojiReaction, error)
|
|||
}()
|
||||
|
||||
row := tx.QueryRow(
|
||||
fmt.Sprintf(`
|
||||
SELECT
|
||||
%s
|
||||
`SELECT
|
||||
clock_value,
|
||||
source,
|
||||
emoji_id,
|
||||
message_id,
|
||||
chat_id,
|
||||
retracted
|
||||
FROM
|
||||
emoji_reactions
|
||||
WHERE
|
||||
emoji_reactions.id = ?
|
||||
`, db.tableEmojiReactionsAllFields()),
|
||||
id,
|
||||
)
|
||||
`, id)
|
||||
|
||||
emojiReaction := new(EmojiReaction)
|
||||
args := []interface{}{
|
||||
&emojiReaction.ID,
|
||||
&emojiReaction.Clock,
|
||||
&emojiReaction.From,
|
||||
&emojiReaction.Type,
|
||||
|
@ -805,6 +775,61 @@ func (db sqlitePersistence) EmojiReactionByID(id string) (*EmojiReaction, error)
|
|||
}
|
||||
}
|
||||
|
||||
func (db sqlitePersistence) EmojiReactionByFromMessageIDAndType(from string, messageID string, emojiType protobuf.EmojiReaction_Type) (*EmojiReaction, error) {
|
||||
tx, err := db.db.BeginTx(context.Background(), &sql.TxOptions{})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer func() {
|
||||
if err == nil {
|
||||
err = tx.Commit()
|
||||
return
|
||||
}
|
||||
// don't shadow original error
|
||||
_ = tx.Rollback()
|
||||
}()
|
||||
|
||||
row := tx.QueryRow(
|
||||
`SELECT
|
||||
clock_value,
|
||||
source,
|
||||
emoji_id,
|
||||
message_id,
|
||||
chat_id,
|
||||
retracted
|
||||
|
||||
FROM
|
||||
emoji_reactions
|
||||
WHERE
|
||||
emoji_reactions.source = ?
|
||||
AND
|
||||
emoji_reactions.message_id = ?
|
||||
AND
|
||||
emoji_reactions.emoji_id = ?
|
||||
`,
|
||||
from,
|
||||
messageID,
|
||||
emojiType,
|
||||
)
|
||||
|
||||
emojiReaction := new(EmojiReaction)
|
||||
err = row.Scan(&emojiReaction.Clock,
|
||||
&emojiReaction.From,
|
||||
&emojiReaction.Type,
|
||||
&emojiReaction.MessageId,
|
||||
&emojiReaction.ChatId,
|
||||
&emojiReaction.Retracted)
|
||||
|
||||
switch err {
|
||||
case sql.ErrNoRows:
|
||||
return nil, errRecordNotFound
|
||||
case nil:
|
||||
return emojiReaction, nil
|
||||
default:
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
func (db sqlitePersistence) RetractEmojiReaction(id string) error {
|
||||
_, err := db.db.Exec(`UPDATE emoji_reactions SET retracted = 1 WHERE id = ?`, id)
|
||||
return err
|
||||
|
|
|
@ -1778,6 +1778,9 @@ type ReceivedMessageState struct {
|
|||
ModifiedInstallations map[string]bool
|
||||
// Map of existing messages
|
||||
ExistingMessagesMap map[string]bool
|
||||
// EmojiReactions is a list of emoji reactions for the current batch
|
||||
// indexed by from-message-id-emoji-type
|
||||
EmojiReactions map[string]*EmojiReaction
|
||||
// Response to the client
|
||||
Response *MessengerResponse
|
||||
// Timesource is a time source for clock values/timestamps.
|
||||
|
@ -1795,6 +1798,7 @@ func (m *Messenger) handleRetrievedMessages(chatWithMessages map[transport.Filte
|
|||
AllInstallations: m.allInstallations,
|
||||
ModifiedInstallations: m.modifiedInstallations,
|
||||
ExistingMessagesMap: make(map[string]bool),
|
||||
EmojiReactions: make(map[string]*EmojiReaction),
|
||||
Response: &MessengerResponse{},
|
||||
Timesource: m.getTimesource(),
|
||||
}
|
||||
|
@ -2040,13 +2044,6 @@ func (m *Messenger) handleRetrievedMessages(chatWithMessages map[transport.Filte
|
|||
continue
|
||||
}
|
||||
|
||||
case protobuf.EmojiReactionRetraction:
|
||||
logger.Debug("Handling EmojiReactionRetraction")
|
||||
err = m.handler.HandleEmojiReactionRetraction(messageState, msg.ParsedMessage.Interface().(protobuf.EmojiReactionRetraction))
|
||||
if err != nil {
|
||||
logger.Warn("failed to handle EmojiReactionRetraction", zap.Error(err))
|
||||
continue
|
||||
}
|
||||
default:
|
||||
// Check if is an encrypted PushNotificationRegistration
|
||||
if msg.Type == protobuf.ApplicationMetadataMessage_PUSH_NOTIFICATION_REGISTRATION {
|
||||
|
@ -2122,6 +2119,10 @@ func (m *Messenger) handleRetrievedMessages(chatWithMessages map[transport.Filte
|
|||
}
|
||||
}
|
||||
|
||||
for _, emojiReaction := range messageState.EmojiReactions {
|
||||
messageState.Response.EmojiReactions = append(messageState.Response.EmojiReactions, emojiReaction)
|
||||
}
|
||||
|
||||
if len(contactsToSave) > 0 {
|
||||
err = m.persistence.SaveContacts(contactsToSave)
|
||||
if err != nil {
|
||||
|
@ -3227,7 +3228,7 @@ func generateAliasAndIdenticon(pk string) (string, string, error) {
|
|||
|
||||
}
|
||||
|
||||
func (m *Messenger) SendEmojiReaction(ctx context.Context, chatID, messageID string, emojiID int) (*MessengerResponse, error) {
|
||||
func (m *Messenger) SendEmojiReaction(ctx context.Context, chatID, messageID string, emojiID protobuf.EmojiReaction_Type) (*MessengerResponse, error) {
|
||||
m.mutex.Lock()
|
||||
defer m.mutex.Unlock()
|
||||
|
||||
|
@ -3246,26 +3247,25 @@ func (m *Messenger) SendEmojiReaction(ctx context.Context, chatID, messageID str
|
|||
ChatId: chatID,
|
||||
Type: protobuf.EmojiReaction_Type(emojiID),
|
||||
},
|
||||
From: types.EncodeHex(crypto.FromECDSAPub(&m.identity.PublicKey)),
|
||||
Retracted: false,
|
||||
From: types.EncodeHex(crypto.FromECDSAPub(&m.identity.PublicKey)),
|
||||
}
|
||||
encodedMessage, err := m.encodeChatEntity(chat, emojiR)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
id, err := m.dispatchMessage(ctx, &common.RawMessage{
|
||||
LocalChatID: chatID,
|
||||
Payload: encodedMessage,
|
||||
MessageType: protobuf.ApplicationMetadataMessage_EMOJI_REACTION,
|
||||
ResendAutomatically: true,
|
||||
_, err = m.dispatchMessage(ctx, &common.RawMessage{
|
||||
LocalChatID: chatID,
|
||||
Payload: encodedMessage,
|
||||
MessageType: protobuf.ApplicationMetadataMessage_EMOJI_REACTION,
|
||||
// Don't resend using datasync, that would create quite a lot
|
||||
// of traffic if clicking too eagelry
|
||||
ResendAutomatically: false,
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
emojiR.ID = types.EncodeHex(id)
|
||||
|
||||
response.EmojiReactions = []*EmojiReaction{emojiR}
|
||||
response.Chats = []*Chat{chat}
|
||||
|
||||
|
@ -3281,44 +3281,45 @@ func (m *Messenger) SendEmojiReactionRetraction(ctx context.Context, emojiReacti
|
|||
m.mutex.Lock()
|
||||
defer m.mutex.Unlock()
|
||||
|
||||
emojiReaction, err := m.persistence.EmojiReactionByID(emojiReactionID)
|
||||
emojiR, err := m.persistence.EmojiReactionByID(emojiReactionID)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Check that the sender is the key owner
|
||||
pk := types.EncodeHex(crypto.FromECDSAPub(&m.identity.PublicKey))
|
||||
if emojiReaction.From != pk {
|
||||
if emojiR.From != pk {
|
||||
return nil, errors.Errorf("identity mismatch, "+
|
||||
"emoji reactions can only be retracted by the reaction sender, "+
|
||||
"emoji reaction sent by '%s', current identity '%s'",
|
||||
emojiReaction.From, pk,
|
||||
emojiR.From, pk,
|
||||
)
|
||||
}
|
||||
|
||||
// Get chat and clock
|
||||
chat, ok := m.allChats[emojiReaction.GetChatId()]
|
||||
chat, ok := m.allChats[emojiR.GetChatId()]
|
||||
if !ok {
|
||||
return nil, ErrChatNotFound
|
||||
}
|
||||
clock, _ := chat.NextClockAndTimestamp(m.getTimesource())
|
||||
|
||||
// Build the EmojiReactionRetraction protobuf struct
|
||||
emojiRR := &protobuf.EmojiReactionRetraction{
|
||||
Clock: clock,
|
||||
EmojiReactionId: emojiReactionID,
|
||||
}
|
||||
encodedMessage, err := proto.Marshal(emojiRR)
|
||||
// Update the relevant fields
|
||||
emojiR.Clock = clock
|
||||
emojiR.Retracted = true
|
||||
|
||||
encodedMessage, err := m.encodeChatEntity(chat, emojiR)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Send the marshalled EmojiReactionRetraction protobuf
|
||||
_, err = m.dispatchMessage(ctx, &common.RawMessage{
|
||||
LocalChatID: emojiReaction.GetChatId(),
|
||||
Payload: encodedMessage,
|
||||
MessageType: protobuf.ApplicationMetadataMessage_EMOJI_REACTION_RETRACTION,
|
||||
ResendAutomatically: true,
|
||||
LocalChatID: emojiR.GetChatId(),
|
||||
Payload: encodedMessage,
|
||||
MessageType: protobuf.ApplicationMetadataMessage_EMOJI_REACTION,
|
||||
// Don't resend using datasync, that would create quite a lot
|
||||
// of traffic if clicking too eagelry
|
||||
ResendAutomatically: false,
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
@ -3326,8 +3327,8 @@ func (m *Messenger) SendEmojiReactionRetraction(ctx context.Context, emojiReacti
|
|||
|
||||
// Update MessengerResponse
|
||||
response := MessengerResponse{}
|
||||
emojiReaction.Retracted = true
|
||||
response.EmojiReactions = []*EmojiReaction{emojiReaction}
|
||||
emojiR.Retracted = true
|
||||
response.EmojiReactions = []*EmojiReaction{emojiR}
|
||||
response.Chats = []*Chat{chat}
|
||||
|
||||
// Persist retraction state for emoji reaction
|
||||
|
|
|
@ -0,0 +1,165 @@
|
|||
package protocol
|
||||
|
||||
import (
|
||||
"context"
|
||||
"crypto/ecdsa"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"testing"
|
||||
|
||||
"github.com/google/uuid"
|
||||
"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"
|
||||
"github.com/status-im/status-go/waku"
|
||||
)
|
||||
|
||||
func TestMessengerEmojiSuite(t *testing.T) {
|
||||
suite.Run(t, new(MessengerEmojiSuite))
|
||||
}
|
||||
|
||||
type MessengerEmojiSuite 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
|
||||
|
||||
tmpFiles []*os.File // files to clean up
|
||||
logger *zap.Logger
|
||||
}
|
||||
|
||||
func (s *MessengerEmojiSuite) 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(nil))
|
||||
|
||||
s.m = s.newMessenger(s.shh)
|
||||
s.privateKey = s.m.identity
|
||||
}
|
||||
|
||||
func (s *MessengerEmojiSuite) newMessengerWithKey(shh types.Waku, privateKey *ecdsa.PrivateKey) *Messenger {
|
||||
tmpFile, err := ioutil.TempFile("", "")
|
||||
s.Require().NoError(err)
|
||||
|
||||
options := []Option{
|
||||
WithCustomLogger(s.logger),
|
||||
WithMessagesPersistenceEnabled(),
|
||||
WithDatabaseConfig(tmpFile.Name(), "some-key"),
|
||||
WithDatasync(),
|
||||
}
|
||||
installationID := uuid.New().String()
|
||||
m, err := NewMessenger(
|
||||
privateKey,
|
||||
&testNode{shh: shh},
|
||||
installationID,
|
||||
options...,
|
||||
)
|
||||
s.Require().NoError(err)
|
||||
|
||||
err = m.Init()
|
||||
s.Require().NoError(err)
|
||||
|
||||
s.tmpFiles = append(s.tmpFiles, tmpFile)
|
||||
|
||||
return m
|
||||
}
|
||||
|
||||
func (s *MessengerEmojiSuite) newMessenger(shh types.Waku) *Messenger {
|
||||
privateKey, err := crypto.GenerateKey()
|
||||
s.Require().NoError(err)
|
||||
|
||||
return s.newMessengerWithKey(s.shh, privateKey)
|
||||
}
|
||||
|
||||
func (s *MessengerEmojiSuite) TestSendEmoji() {
|
||||
alice := s.m
|
||||
key, err := crypto.GenerateKey()
|
||||
s.Require().NoError(err)
|
||||
|
||||
bob := s.newMessengerWithKey(s.shh, key)
|
||||
|
||||
chatID := "status"
|
||||
|
||||
chat := CreatePublicChat(chatID, alice.transport)
|
||||
|
||||
err = alice.SaveChat(&chat)
|
||||
s.Require().NoError(err)
|
||||
|
||||
err = alice.Join(chat)
|
||||
s.Require().NoError(err)
|
||||
|
||||
err = bob.SaveChat(&chat)
|
||||
s.Require().NoError(err)
|
||||
|
||||
err = bob.Join(chat)
|
||||
s.Require().NoError(err)
|
||||
|
||||
// Send chat message from bob to alice
|
||||
|
||||
message := buildTestMessage(chat)
|
||||
_, err = alice.SendChatMessage(context.Background(), message)
|
||||
s.NoError(err)
|
||||
|
||||
// Wait for message to arrive to bob
|
||||
response, err := WaitOnMessengerResponse(
|
||||
bob,
|
||||
func(r *MessengerResponse) bool { return len(r.Messages) > 0 },
|
||||
"no messages",
|
||||
)
|
||||
s.Require().NoError(err)
|
||||
|
||||
s.Require().Len(response.Messages, 1)
|
||||
|
||||
messageID := response.Messages[0].ID
|
||||
|
||||
// Respond with an emoji, donald trump style
|
||||
|
||||
response, err = bob.SendEmojiReaction(context.Background(), chat.ID, messageID, protobuf.EmojiReaction_SAD)
|
||||
s.Require().NoError(err)
|
||||
s.Require().Len(response.EmojiReactions, 1)
|
||||
|
||||
emojiID := response.EmojiReactions[0].ID()
|
||||
|
||||
// Wait for the emoji to arrive to alice
|
||||
response, err = WaitOnMessengerResponse(
|
||||
alice,
|
||||
func(r *MessengerResponse) bool { return len(r.EmojiReactions) > 0 },
|
||||
"no emoji",
|
||||
)
|
||||
s.Require().NoError(err)
|
||||
|
||||
s.Require().Len(response.EmojiReactions, 1)
|
||||
s.Require().Equal(response.EmojiReactions[0].ID(), emojiID)
|
||||
s.Require().Equal(response.EmojiReactions[0].Type, protobuf.EmojiReaction_SAD)
|
||||
|
||||
// Retract the emoji
|
||||
response, err = bob.SendEmojiReactionRetraction(context.Background(), emojiID)
|
||||
s.Require().NoError(err)
|
||||
s.Require().Len(response.EmojiReactions, 1)
|
||||
s.Require().True(response.EmojiReactions[0].Retracted)
|
||||
|
||||
// Wait for the emoji to arrive to alice
|
||||
response, err = WaitOnMessengerResponse(
|
||||
alice,
|
||||
func(r *MessengerResponse) bool { return len(r.EmojiReactions) > 0 },
|
||||
"no emoji",
|
||||
)
|
||||
s.Require().NoError(err)
|
||||
|
||||
s.Require().Len(response.EmojiReactions, 1)
|
||||
s.Require().Equal(response.EmojiReactions[0].ID(), emojiID)
|
||||
s.Require().Equal(response.EmojiReactions[0].Type, protobuf.EmojiReaction_SAD)
|
||||
s.Require().True(response.EmojiReactions[0].Retracted)
|
||||
}
|
|
@ -14,14 +14,10 @@
|
|||
// 1591277220_add_index_messages.up.sql (240B)
|
||||
// 1593087212_add_mute_chat_and_raw_message_fields.down.sql (0)
|
||||
// 1593087212_add_mute_chat_and_raw_message_fields.up.sql (215B)
|
||||
// 1594390919_create_emoji_reaction_table.down.sql (27B)
|
||||
<<<<<<< HEAD
|
||||
// 1594390919_create_emoji_reactions_table.up.sql (234B)
|
||||
// 1594390919_create_emoji_reactions_table.down.sql (27B)
|
||||
// 1594390919_create_emoji_reactions_table.up.sql (265B)
|
||||
// 1595862781_add_audio_data.down.sql (0)
|
||||
// 1595862781_add_audio_data.up.sql (246B)
|
||||
=======
|
||||
// 1594390919_create_emoji_reactions_table.up.sql (263B)
|
||||
>>>>>>> 350ce45aa... make generate
|
||||
// doc.go (850B)
|
||||
|
||||
package migrations
|
||||
|
@ -371,27 +367,27 @@ func _1593087212_add_mute_chat_and_raw_message_fieldsUpSql() (*asset, error) {
|
|||
return a, nil
|
||||
}
|
||||
|
||||
var __1594390919_create_emoji_reaction_tableDownSql = []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\x72\x09\xf2\x0f\x50\x08\x71\x74\xf2\x71\x55\x48\xcd\xcd\xcf\xca\x8c\x2f\x4a\x4d\x4c\x2e\xc9\xcc\xcf\x2b\xb6\x06\x04\x00\x00\xff\xff\x54\xc5\xdd\x49\x1b\x00\x00\x00")
|
||||
var __1594390919_create_emoji_reactions_tableDownSql = []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\x72\x09\xf2\x0f\x50\x08\x71\x74\xf2\x71\x55\x48\xcd\xcd\xcf\xca\x8c\x2f\x4a\x4d\x4c\x2e\xc9\xcc\xcf\x2b\xb6\x06\x04\x00\x00\xff\xff\x54\xc5\xdd\x49\x1b\x00\x00\x00")
|
||||
|
||||
func _1594390919_create_emoji_reaction_tableDownSqlBytes() ([]byte, error) {
|
||||
func _1594390919_create_emoji_reactions_tableDownSqlBytes() ([]byte, error) {
|
||||
return bindataRead(
|
||||
__1594390919_create_emoji_reaction_tableDownSql,
|
||||
"1594390919_create_emoji_reaction_table.down.sql",
|
||||
__1594390919_create_emoji_reactions_tableDownSql,
|
||||
"1594390919_create_emoji_reactions_table.down.sql",
|
||||
)
|
||||
}
|
||||
|
||||
func _1594390919_create_emoji_reaction_tableDownSql() (*asset, error) {
|
||||
bytes, err := _1594390919_create_emoji_reaction_tableDownSqlBytes()
|
||||
func _1594390919_create_emoji_reactions_tableDownSql() (*asset, error) {
|
||||
bytes, err := _1594390919_create_emoji_reactions_tableDownSqlBytes()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
info := bindataFileInfo{name: "1594390919_create_emoji_reaction_table.down.sql", size: 27, mode: os.FileMode(0644), modTime: time.Unix(1595864971, 0)}
|
||||
info := bindataFileInfo{name: "1594390919_create_emoji_reactions_table.down.sql", size: 27, mode: os.FileMode(0644), modTime: time.Unix(1595865239, 0)}
|
||||
a := &asset{bytes: bytes, info: info, digest: [32]uint8{0x6f, 0xbb, 0xdb, 0x8c, 0xd1, 0x17, 0x1b, 0x19, 0x2a, 0x80, 0xc6, 0xb1, 0xc5, 0x47, 0x74, 0x97, 0x32, 0x30, 0x5, 0xa9, 0x9c, 0xa7, 0x60, 0xa, 0xfe, 0xfb, 0x41, 0x6b, 0x25, 0xad, 0x84, 0x20}}
|
||||
return a, nil
|
||||
}
|
||||
|
||||
var __1594390919_create_emoji_reactions_tableUpSql = []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\x74\xce\xbf\x4e\xc3\x30\x10\xc7\xf1\xbd\x52\xdf\xe1\x37\x82\xc4\xc0\xce\x64\xcc\x45\x58\x18\xa7\x72\xaf\xa8\x9d\x22\xcb\x3d\x81\x21\xc1\x92\xed\xf0\xfc\x88\x64\xe1\x8f\x98\x3f\x77\xdf\x3b\xed\x49\x31\x81\xd5\xad\x25\x98\x0e\xae\x67\xd0\xd1\xec\x79\x0f\x99\xf2\x6b\x1a\x8a\x84\xd8\x52\x7e\xaf\xb8\xd8\x6e\x80\x74\xc6\x93\xf2\xfa\x5e\x79\xec\xbc\x79\x54\xfe\x84\x07\x3a\xa1\x77\xd0\xbd\xeb\xac\xd1\x0c\x4f\x3b\xab\x34\x5d\x7d\x8d\xc7\x31\xc7\xb7\xe1\x23\x8c\xb3\xc0\x38\x5e\xf2\xee\x60\xed\x82\x35\xcf\x25\x0a\x98\x8e\xbf\x60\xbd\x9c\xce\x7f\x57\x26\xa9\x35\x3c\xcb\xf0\xed\x8d\x1f\x1e\x5f\x42\xfb\x17\x8b\xb4\x12\x62\x93\xb5\x7b\x47\x9d\x3a\x58\xc6\xf5\x76\x73\x79\xf3\x19\x00\x00\xff\xff\x66\x93\x81\x54\x07\x01\x00\x00")
|
||||
var __1594390919_create_emoji_reactions_tableUpSql = []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\x74\xce\xbf\x4e\xc3\x30\x10\xc7\xf1\x3d\x52\xde\xe1\x37\x82\xc4\xc0\xce\x64\xcc\x45\x58\x18\xa7\x72\xaf\xa8\x9d\x22\xcb\x3d\x81\xa1\xc5\x92\xed\xf0\xfc\x88\x64\xe1\x8f\x98\x3f\x77\xdf\x3b\xed\x49\x31\x81\xd5\xad\x25\x98\x01\x6e\x64\xd0\xde\x6c\x79\x0b\x39\xe7\xd7\x34\x15\x09\xb1\xa5\xfc\x5e\x71\xd1\x77\x40\x3a\xe2\x49\x79\x7d\xaf\x3c\x36\xde\x3c\x2a\x7f\xc0\x03\x1d\x30\x3a\xe8\xd1\x0d\xd6\x68\x86\xa7\x8d\x55\x9a\xae\xbe\xc6\xe3\x29\xc7\xb7\xe9\x23\x9c\x66\x81\x71\xbc\xe4\xdd\xce\xda\x05\x6b\x9e\x4b\x14\x30\xed\x7f\xc1\x7a\x39\x1d\xff\xae\x9c\xa5\xd6\xf0\x2c\xd3\xb7\x37\x7e\x78\x7c\x09\xed\x5f\x2c\xd2\x4a\x88\x4d\xd6\xee\x1d\x0d\x6a\x67\x19\xd7\x7d\x77\x79\xd3\x77\x9f\x01\x00\x00\xff\xff\xf2\xdf\x03\x4e\x09\x01\x00\x00")
|
||||
|
||||
func _1594390919_create_emoji_reactions_tableUpSqlBytes() ([]byte, error) {
|
||||
return bindataRead(
|
||||
|
@ -406,20 +402,8 @@ func _1594390919_create_emoji_reactions_tableUpSql() (*asset, error) {
|
|||
return nil, err
|
||||
}
|
||||
|
||||
<<<<<<< HEAD
|
||||
<<<<<<< HEAD
|
||||
info := bindataFileInfo{name: "1594390919_create_emoji_reactions_table.up.sql", size: 234, mode: os.FileMode(0644), modTime: time.Unix(1595864971, 0)}
|
||||
=======
|
||||
<<<<<<< HEAD
|
||||
info := bindataFileInfo{name: "1594390919_create_emoji_reactions_table.up.sql", size: 234, mode: os.FileMode(0644), modTime: time.Unix(1595840825, 0)}
|
||||
>>>>>>> 350ce45aa... make generate
|
||||
a := &asset{bytes: bytes, info: info, digest: [32]uint8{0x5f, 0xcb, 0xf0, 0xaf, 0xa8, 0x82, 0xec, 0x10, 0xd0, 0xae, 0x83, 0x78, 0xa7, 0x90, 0x84, 0x3d, 0xc0, 0xfe, 0x6, 0xe6, 0xc8, 0x8b, 0xda, 0xe0, 0x1a, 0x81, 0x86, 0x61, 0xe9, 0xb0, 0xa2, 0x31}}
|
||||
=======
|
||||
info := bindataFileInfo{name: "1594390919_create_emoji_reactions_table.up.sql", size: 263, mode: os.FileMode(0644), modTime: time.Unix(1595339114, 0)}
|
||||
=======
|
||||
info := bindataFileInfo{name: "1594390919_create_emoji_reactions_table.up.sql", size: 263, mode: os.FileMode(0644), modTime: time.Unix(1595840951, 0)}
|
||||
>>>>>>> 546b68df9... Added general protobuf umarshaller function
|
||||
a := &asset{bytes: bytes, info: info, digest: [32]uint8{0x60, 0xab, 0x81, 0xa6, 0x1a, 0x5a, 0x9, 0xee, 0x72, 0x18, 0x5d, 0xe7, 0xf1, 0x94, 0x66, 0x2d, 0x38, 0x29, 0x57, 0xf8, 0xec, 0x1c, 0x1b, 0x1f, 0xc6, 0x1d, 0xb5, 0x2e, 0xe8, 0x15, 0x8, 0x74}}
|
||||
info := bindataFileInfo{name: "1594390919_create_emoji_reactions_table.up.sql", size: 265, mode: os.FileMode(0644), modTime: time.Unix(1595865239, 0)}
|
||||
a := &asset{bytes: bytes, info: info, digest: [32]uint8{0x13, 0x28, 0xa4, 0x70, 0xf0, 0xfe, 0xd, 0xc2, 0x16, 0xc3, 0x1d, 0xbb, 0x3c, 0x1, 0xf6, 0x58, 0x69, 0x2a, 0x27, 0x21, 0xbc, 0x8b, 0xc8, 0x1a, 0xd, 0x36, 0x2d, 0x29, 0x0, 0xc3, 0xfa, 0xad}}
|
||||
return a, nil
|
||||
}
|
||||
|
||||
|
@ -602,7 +586,7 @@ var _bindata = map[string]func() (*asset, error){
|
|||
|
||||
"1593087212_add_mute_chat_and_raw_message_fields.up.sql": _1593087212_add_mute_chat_and_raw_message_fieldsUpSql,
|
||||
|
||||
"1594390919_create_emoji_reaction_table.down.sql": _1594390919_create_emoji_reaction_tableDownSql,
|
||||
"1594390919_create_emoji_reactions_table.down.sql": _1594390919_create_emoji_reactions_tableDownSql,
|
||||
|
||||
"1594390919_create_emoji_reactions_table.up.sql": _1594390919_create_emoji_reactions_tableUpSql,
|
||||
|
||||
|
@ -668,7 +652,7 @@ var _bintree = &bintree{nil, map[string]*bintree{
|
|||
"1591277220_add_index_messages.up.sql": &bintree{_1591277220_add_index_messagesUpSql, map[string]*bintree{}},
|
||||
"1593087212_add_mute_chat_and_raw_message_fields.down.sql": &bintree{_1593087212_add_mute_chat_and_raw_message_fieldsDownSql, map[string]*bintree{}},
|
||||
"1593087212_add_mute_chat_and_raw_message_fields.up.sql": &bintree{_1593087212_add_mute_chat_and_raw_message_fieldsUpSql, map[string]*bintree{}},
|
||||
"1594390919_create_emoji_reaction_table.down.sql": &bintree{_1594390919_create_emoji_reaction_tableDownSql, map[string]*bintree{}},
|
||||
"1594390919_create_emoji_reactions_table.down.sql": &bintree{_1594390919_create_emoji_reactions_tableDownSql, map[string]*bintree{}},
|
||||
"1594390919_create_emoji_reactions_table.up.sql": &bintree{_1594390919_create_emoji_reactions_tableUpSql, map[string]*bintree{}},
|
||||
"1595862781_add_audio_data.down.sql": &bintree{_1595862781_add_audio_dataDownSql, map[string]*bintree{}},
|
||||
"1595862781_add_audio_data.up.sql": &bintree{_1595862781_add_audio_dataUpSql, map[string]*bintree{}},
|
||||
|
|
|
@ -6,4 +6,4 @@ CREATE TABLE IF NOT EXISTS emoji_reactions (
|
|||
message_id VARCHAR NOT NULL,
|
||||
chat_id VARCHAR NOT NULL,
|
||||
retracted INT DEFAULT 0
|
||||
);
|
||||
);
|
||||
|
|
|
@ -61,14 +61,22 @@ func (EmojiReaction_Type) EnumDescriptor() ([]byte, []int) {
|
|||
}
|
||||
|
||||
type EmojiReaction struct {
|
||||
Clock uint64 `protobuf:"varint,1,opt,name=clock,proto3" json:"clock,omitempty"`
|
||||
ChatId string `protobuf:"bytes,2,opt,name=chat_id,json=chatId,proto3" json:"chat_id,omitempty"`
|
||||
MessageId string `protobuf:"bytes,3,opt,name=message_id,json=messageId,proto3" json:"message_id,omitempty"`
|
||||
MessageType MessageType `protobuf:"varint,4,opt,name=message_type,json=messageType,proto3,enum=protobuf.MessageType" json:"message_type,omitempty"`
|
||||
Type EmojiReaction_Type `protobuf:"varint,5,opt,name=type,proto3,enum=protobuf.EmojiReaction_Type" json:"type,omitempty"`
|
||||
XXX_NoUnkeyedLiteral struct{} `json:"-"`
|
||||
XXX_unrecognized []byte `json:"-"`
|
||||
XXX_sizecache int32 `json:"-"`
|
||||
// clock Lamport timestamp of the chat message
|
||||
Clock uint64 `protobuf:"varint,1,opt,name=clock,proto3" json:"clock,omitempty"`
|
||||
// chat_id the ID of the chat the message belongs to, for query efficiency the chat_id is stored in the db even though the
|
||||
// target message also stores the chat_id
|
||||
ChatId string `protobuf:"bytes,2,opt,name=chat_id,json=chatId,proto3" json:"chat_id,omitempty"`
|
||||
// message_id the ID of the target message that the user wishes to react to
|
||||
MessageId string `protobuf:"bytes,3,opt,name=message_id,json=messageId,proto3" json:"message_id,omitempty"`
|
||||
// message_type is (somewhat confusingly) the ID of the type of chat the message belongs to
|
||||
MessageType MessageType `protobuf:"varint,4,opt,name=message_type,json=messageType,proto3,enum=protobuf.MessageType" json:"message_type,omitempty"`
|
||||
// type the ID of the emoji the user wishes to react with
|
||||
Type EmojiReaction_Type `protobuf:"varint,5,opt,name=type,proto3,enum=protobuf.EmojiReaction_Type" json:"type,omitempty"`
|
||||
// whether this is a rectraction of a previously sent emoji
|
||||
Retracted bool `protobuf:"varint,6,opt,name=retracted,proto3" json:"retracted,omitempty"`
|
||||
XXX_NoUnkeyedLiteral struct{} `json:"-"`
|
||||
XXX_unrecognized []byte `json:"-"`
|
||||
XXX_sizecache int32 `json:"-"`
|
||||
}
|
||||
|
||||
func (m *EmojiReaction) Reset() { *m = EmojiReaction{} }
|
||||
|
@ -131,81 +139,40 @@ func (m *EmojiReaction) GetType() EmojiReaction_Type {
|
|||
return EmojiReaction_UNKNOWN_EMOJI_REACTION_TYPE
|
||||
}
|
||||
|
||||
type EmojiReactionRetraction struct {
|
||||
Clock uint64 `protobuf:"varint,1,opt,name=clock,proto3" json:"clock,omitempty"`
|
||||
EmojiReactionId string `protobuf:"bytes,2,opt,name=emoji_reaction_id,json=emojiReactionId,proto3" json:"emoji_reaction_id,omitempty"`
|
||||
XXX_NoUnkeyedLiteral struct{} `json:"-"`
|
||||
XXX_unrecognized []byte `json:"-"`
|
||||
XXX_sizecache int32 `json:"-"`
|
||||
}
|
||||
|
||||
func (m *EmojiReactionRetraction) Reset() { *m = EmojiReactionRetraction{} }
|
||||
func (m *EmojiReactionRetraction) String() string { return proto.CompactTextString(m) }
|
||||
func (*EmojiReactionRetraction) ProtoMessage() {}
|
||||
func (*EmojiReactionRetraction) Descriptor() ([]byte, []int) {
|
||||
return fileDescriptor_0a088c907bbc7ed6, []int{1}
|
||||
}
|
||||
|
||||
func (m *EmojiReactionRetraction) XXX_Unmarshal(b []byte) error {
|
||||
return xxx_messageInfo_EmojiReactionRetraction.Unmarshal(m, b)
|
||||
}
|
||||
func (m *EmojiReactionRetraction) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
|
||||
return xxx_messageInfo_EmojiReactionRetraction.Marshal(b, m, deterministic)
|
||||
}
|
||||
func (m *EmojiReactionRetraction) XXX_Merge(src proto.Message) {
|
||||
xxx_messageInfo_EmojiReactionRetraction.Merge(m, src)
|
||||
}
|
||||
func (m *EmojiReactionRetraction) XXX_Size() int {
|
||||
return xxx_messageInfo_EmojiReactionRetraction.Size(m)
|
||||
}
|
||||
func (m *EmojiReactionRetraction) XXX_DiscardUnknown() {
|
||||
xxx_messageInfo_EmojiReactionRetraction.DiscardUnknown(m)
|
||||
}
|
||||
|
||||
var xxx_messageInfo_EmojiReactionRetraction proto.InternalMessageInfo
|
||||
|
||||
func (m *EmojiReactionRetraction) GetClock() uint64 {
|
||||
func (m *EmojiReaction) GetRetracted() bool {
|
||||
if m != nil {
|
||||
return m.Clock
|
||||
return m.Retracted
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
func (m *EmojiReactionRetraction) GetEmojiReactionId() string {
|
||||
if m != nil {
|
||||
return m.EmojiReactionId
|
||||
}
|
||||
return ""
|
||||
return false
|
||||
}
|
||||
|
||||
func init() {
|
||||
proto.RegisterEnum("protobuf.EmojiReaction_Type", EmojiReaction_Type_name, EmojiReaction_Type_value)
|
||||
proto.RegisterType((*EmojiReaction)(nil), "protobuf.EmojiReaction")
|
||||
proto.RegisterType((*EmojiReactionRetraction)(nil), "protobuf.EmojiReactionRetraction")
|
||||
}
|
||||
|
||||
func init() { proto.RegisterFile("emoji_reaction.proto", fileDescriptor_0a088c907bbc7ed6) }
|
||||
|
||||
var fileDescriptor_0a088c907bbc7ed6 = []byte{
|
||||
// 320 bytes of a gzipped FileDescriptorProto
|
||||
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x7c, 0x91, 0xcf, 0x4e, 0xf2, 0x40,
|
||||
0x14, 0xc5, 0xbf, 0xc2, 0x14, 0xe8, 0xe5, 0x43, 0xc6, 0x09, 0x06, 0xe2, 0x9f, 0x48, 0x58, 0x11,
|
||||
0x17, 0x8d, 0xd1, 0x8d, 0xdb, 0x2a, 0x0d, 0x54, 0x61, 0x4a, 0x86, 0x56, 0x42, 0x5c, 0x4c, 0xa0,
|
||||
0x1d, 0x15, 0xb5, 0xb4, 0x81, 0xb2, 0xe0, 0xd9, 0x7c, 0x39, 0xd3, 0xa1, 0xa4, 0x76, 0xe3, 0x6a,
|
||||
0x72, 0xee, 0x39, 0xbf, 0xc9, 0x99, 0x3b, 0xd0, 0x10, 0x41, 0xf8, 0xb1, 0xe4, 0x6b, 0x31, 0xf7,
|
||||
0xe2, 0x65, 0xb8, 0xd2, 0xa3, 0x75, 0x18, 0x87, 0xa4, 0x22, 0x8f, 0xc5, 0xf6, 0xf5, 0xb4, 0x2a,
|
||||
0x56, 0xdb, 0x60, 0xb3, 0x1f, 0x77, 0xbe, 0x0b, 0x50, 0x33, 0x93, 0x3c, 0x4b, 0xe3, 0xa4, 0x01,
|
||||
0xaa, 0xf7, 0x15, 0x7a, 0x9f, 0x2d, 0xa5, 0xad, 0x74, 0x11, 0xdb, 0x0b, 0xd2, 0x84, 0xb2, 0xf7,
|
||||
0x3e, 0x8f, 0xf9, 0xd2, 0x6f, 0x15, 0xda, 0x4a, 0x57, 0x63, 0xa5, 0x44, 0x5a, 0x3e, 0xb9, 0x00,
|
||||
0x08, 0xc4, 0x66, 0x33, 0x7f, 0x13, 0x89, 0x57, 0x94, 0x9e, 0x96, 0x4e, 0x2c, 0x9f, 0xdc, 0xc1,
|
||||
0xff, 0x83, 0x1d, 0xef, 0x22, 0xd1, 0x42, 0x6d, 0xa5, 0x7b, 0x74, 0x73, 0xa2, 0x1f, 0xda, 0xe8,
|
||||
0xa3, 0xbd, 0xeb, 0xec, 0x22, 0xc1, 0xaa, 0x41, 0x26, 0xc8, 0x35, 0x20, 0x49, 0xa8, 0x92, 0x38,
|
||||
0xcf, 0x88, 0x5c, 0x5d, 0x5d, 0x82, 0x32, 0xd9, 0x89, 0x00, 0x49, 0xf2, 0x12, 0xce, 0x5c, 0xfa,
|
||||
0x44, 0xed, 0x29, 0xe5, 0xe6, 0xc8, 0x7e, 0xb4, 0x38, 0x33, 0x8d, 0x07, 0xc7, 0xb2, 0x29, 0x77,
|
||||
0x66, 0x63, 0x13, 0xff, 0x23, 0x15, 0x40, 0x43, 0xfb, 0xd9, 0xc4, 0x0a, 0xa9, 0x81, 0xe6, 0x0c,
|
||||
0xdc, 0xd1, 0xfd, 0x84, 0xbb, 0x63, 0x5c, 0x20, 0x75, 0xa8, 0xa6, 0xb2, 0x67, 0x4f, 0x29, 0x2e,
|
||||
0x12, 0x0d, 0xd4, 0xa1, 0xe1, 0xf6, 0x07, 0x18, 0x91, 0x32, 0x14, 0x27, 0x46, 0x0f, 0xab, 0xc9,
|
||||
0xcc, 0xa0, 0x7d, 0x36, 0xc3, 0xa5, 0xce, 0x0b, 0x34, 0x73, 0x6d, 0x98, 0x88, 0xd7, 0x7f, 0xae,
|
||||
0xf1, 0x0a, 0x8e, 0xf3, 0xbf, 0x93, 0x2d, 0xb4, 0x2e, 0x7e, 0xdf, 0x64, 0xf9, 0x8b, 0x92, 0x7c,
|
||||
0xf1, 0xed, 0x4f, 0x00, 0x00, 0x00, 0xff, 0xff, 0x18, 0x16, 0x6b, 0xcc, 0xd0, 0x01, 0x00, 0x00,
|
||||
// 305 bytes of a gzipped FileDescriptorProto
|
||||
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x54, 0x8e, 0xdf, 0x4f, 0x82, 0x50,
|
||||
0x14, 0xc7, 0x43, 0x01, 0xe5, 0x98, 0x75, 0x77, 0x66, 0x8b, 0x95, 0x2d, 0xe6, 0x13, 0x4f, 0xac,
|
||||
0xd5, 0x4b, 0xaf, 0x94, 0x4c, 0x29, 0x05, 0x77, 0x85, 0x9c, 0x4f, 0x0c, 0xe1, 0x56, 0x56, 0x08,
|
||||
0xc3, 0xeb, 0x83, 0x7f, 0x6a, 0xff, 0x4d, 0xe3, 0xaa, 0x73, 0x3d, 0x9d, 0x7d, 0x7f, 0x7c, 0xce,
|
||||
0xbe, 0xd0, 0x61, 0x59, 0xfe, 0xb5, 0x8c, 0x4a, 0x16, 0x27, 0x7c, 0x99, 0xaf, 0xac, 0xa2, 0xcc,
|
||||
0x79, 0x8e, 0x4d, 0x71, 0x16, 0x9b, 0xf7, 0xab, 0x16, 0x5b, 0x6d, 0xb2, 0xf5, 0xce, 0xee, 0xfd,
|
||||
0xd6, 0xa0, 0xed, 0x54, 0x7d, 0xba, 0xaf, 0x63, 0x07, 0x94, 0xe4, 0x27, 0x4f, 0xbe, 0x75, 0xc9,
|
||||
0x90, 0x4c, 0x99, 0xee, 0x04, 0x5e, 0x42, 0x23, 0xf9, 0x8c, 0x79, 0xb4, 0x4c, 0xf5, 0x9a, 0x21,
|
||||
0x99, 0x1a, 0x55, 0x2b, 0xe9, 0xa6, 0x78, 0x03, 0x90, 0xb1, 0xf5, 0x3a, 0xfe, 0x60, 0x55, 0x56,
|
||||
0x17, 0x99, 0xb6, 0x77, 0xdc, 0x14, 0x1f, 0xe1, 0xf4, 0x10, 0xf3, 0x6d, 0xc1, 0x74, 0xd9, 0x90,
|
||||
0xcc, 0xb3, 0xfb, 0x0b, 0xeb, 0xb0, 0xc6, 0x1a, 0xef, 0xd2, 0x60, 0x5b, 0x30, 0xda, 0xca, 0x8e,
|
||||
0x02, 0xef, 0x40, 0x16, 0x84, 0x22, 0x88, 0xee, 0x91, 0xf8, 0x37, 0xd7, 0x12, 0xa0, 0x68, 0x62,
|
||||
0x17, 0xb4, 0x92, 0xf1, 0x32, 0x4e, 0x38, 0x4b, 0x75, 0xd5, 0x90, 0xcc, 0x26, 0x3d, 0x1a, 0xbd,
|
||||
0x02, 0x64, 0xf1, 0xf7, 0x16, 0xae, 0x43, 0xef, 0xd5, 0xf3, 0x67, 0x5e, 0xe4, 0x8c, 0xfd, 0x17,
|
||||
0x37, 0xa2, 0x8e, 0xfd, 0x1c, 0xb8, 0xbe, 0x17, 0x05, 0xf3, 0x89, 0x43, 0x4e, 0xb0, 0x09, 0xf2,
|
||||
0xc8, 0x7f, 0x73, 0x88, 0x84, 0x6d, 0xd0, 0x82, 0x61, 0x38, 0x7e, 0x9a, 0x46, 0xe1, 0x84, 0xd4,
|
||||
0xf0, 0x1c, 0x5a, 0x7b, 0xd9, 0xf7, 0x67, 0x1e, 0xa9, 0xa3, 0x06, 0xca, 0xc8, 0x0e, 0x07, 0x43,
|
||||
0x22, 0x63, 0x03, 0xea, 0x53, 0xbb, 0x4f, 0x94, 0xca, 0xb3, 0xbd, 0x01, 0x9d, 0x13, 0x75, 0xa1,
|
||||
0x8a, 0xc9, 0x0f, 0x7f, 0x01, 0x00, 0x00, 0xff, 0xff, 0x03, 0x65, 0x6e, 0x92, 0x91, 0x01, 0x00,
|
||||
0x00,
|
||||
}
|
||||
|
|
|
@ -30,9 +30,7 @@ message EmojiReaction {
|
|||
SAD = 5;
|
||||
ANGRY = 6;
|
||||
}
|
||||
}
|
||||
|
||||
message EmojiReactionRetraction {
|
||||
uint64 clock = 1;
|
||||
string emoji_reaction_id = 2;
|
||||
// whether this is a rectraction of a previously sent emoji
|
||||
bool retracted = 6;
|
||||
}
|
||||
|
|
|
@ -240,9 +240,7 @@ func init() {
|
|||
proto.RegisterType((*MembershipUpdateMessage)(nil), "protobuf.MembershipUpdateMessage")
|
||||
}
|
||||
|
||||
func init() {
|
||||
proto.RegisterFile("membership_update_message.proto", fileDescriptor_8d37dd0dc857a6be)
|
||||
}
|
||||
func init() { proto.RegisterFile("membership_update_message.proto", fileDescriptor_8d37dd0dc857a6be) }
|
||||
|
||||
var fileDescriptor_8d37dd0dc857a6be = []byte{
|
||||
// 393 bytes of a gzipped FileDescriptorProto
|
||||
|
|
|
@ -232,8 +232,6 @@ func (m *StatusMessage) HandleApplication() error {
|
|||
return m.unmarshalProtobufData(new(protobuf.PushNotificationResponse))
|
||||
case protobuf.ApplicationMetadataMessage_EMOJI_REACTION:
|
||||
return m.unmarshalProtobufData(new(protobuf.EmojiReaction))
|
||||
case protobuf.ApplicationMetadataMessage_EMOJI_REACTION_RETRACTION:
|
||||
return m.unmarshalProtobufData(new(protobuf.EmojiReactionRetraction))
|
||||
case protobuf.ApplicationMetadataMessage_PUSH_NOTIFICATION_REGISTRATION:
|
||||
// This message is a bit different as it's encrypted, so we pass it straight through
|
||||
v := reflect.ValueOf(m.DecryptedPayload)
|
||||
|
|
|
@ -17,6 +17,7 @@ import (
|
|||
"github.com/status-im/status-go/mailserver"
|
||||
"github.com/status-im/status-go/protocol"
|
||||
"github.com/status-im/status-go/protocol/encryption/multidevice"
|
||||
"github.com/status-im/status-go/protocol/protobuf"
|
||||
"github.com/status-im/status-go/protocol/pushnotificationclient"
|
||||
"github.com/status-im/status-go/protocol/transport"
|
||||
"github.com/status-im/status-go/services/ext/mailservers"
|
||||
|
@ -511,6 +512,16 @@ func (api *PublicAPI) RegisteredForPushNotifications() (bool, error) {
|
|||
return api.service.messenger.RegisteredForPushNotifications()
|
||||
}
|
||||
|
||||
// Emoji
|
||||
|
||||
func (api *PublicAPI) SendEmojiReaction(ctx context.Context, chatID, messageID string, emojiID protobuf.EmojiReaction_Type) (*protocol.MessengerResponse, error) {
|
||||
return api.service.messenger.SendEmojiReaction(ctx, chatID, messageID, emojiID)
|
||||
}
|
||||
|
||||
func (api *PublicAPI) SendEmojiReactionRetraction(ctx context.Context, emojiReactionID string) (*protocol.MessengerResponse, error) {
|
||||
return api.service.messenger.SendEmojiReactionRetraction(ctx, emojiReactionID)
|
||||
}
|
||||
|
||||
// Echo is a method for testing purposes.
|
||||
func (api *PublicAPI) Echo(ctx context.Context, message string) (string, error) {
|
||||
return message, nil
|
||||
|
|
Loading…
Reference in New Issue