Use same message with flag for emoji retraction and use compound id

This commit is contained in:
Andrea Maria Piana 2020-07-27 14:27:48 +02:00
parent 2bf1991190
commit 5a178939de
No known key found for this signature in database
GPG Key ID: AA6CCA6DE0E06424
13 changed files with 381 additions and 201 deletions

View File

@ -2,9 +2,13 @@ package protocol
import ( import (
"crypto/ecdsa" "crypto/ecdsa"
"encoding/json"
"fmt"
"github.com/golang/protobuf/proto" "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" "github.com/status-im/status-go/protocol/protobuf"
) )
@ -13,19 +17,18 @@ import (
type EmojiReaction struct { type EmojiReaction struct {
protobuf.EmojiReaction 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 is a public key of the author of the emoji reaction.
From string From string `json:"from,omitempty"`
// Retracted represents whether the user has chosen to remove a previously given reaction
Retracted bool
// SigPubKey is the ecdsa encoded public key of the emoji reaction author // SigPubKey is the ecdsa encoded public key of the emoji reaction author
SigPubKey *ecdsa.PublicKey `json:"-"` 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 // GetSigPubKey returns an ecdsa encoded public key
// this function is required to implement the ChatEntity interface // this function is required to implement the ChatEntity interface
func (e EmojiReaction) GetSigPubKey() *ecdsa.PublicKey { func (e EmojiReaction) GetSigPubKey() *ecdsa.PublicKey {
@ -43,3 +46,16 @@ func (e EmojiReaction) GetProtobuf() proto.Message {
func (e *EmojiReaction) SetMessageType(messageType protobuf.MessageType) { func (e *EmojiReaction) SetMessageType(messageType protobuf.MessageType) {
e.MessageType = 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)
}

View File

@ -670,10 +670,22 @@ func (m *MessageHandler) messageExists(messageID string, existingMessagesMap map
func (m *MessageHandler) HandleEmojiReaction(state *ReceivedMessageState, pbEmojiR protobuf.EmojiReaction) error { func (m *MessageHandler) HandleEmojiReaction(state *ReceivedMessageState, pbEmojiR protobuf.EmojiReaction) error {
logger := m.logger.With(zap.String("site", "HandleEmojiReaction")) 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 := &EmojiReaction{
EmojiReaction: pbEmojiR, EmojiReaction: pbEmojiR,
ID: state.CurrentMessageState.MessageID, From: from,
From: state.CurrentMessageState.Contact.ID,
SigPubKey: state.CurrentMessageState.PublicKey, SigPubKey: state.CurrentMessageState.PublicKey,
} }
chat, err := m.matchChatEntity(emojiReaction, state.AllChats, state.Timesource) 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 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") logger.Info("Handling emoji reaction")
if chat.LastClockValue < pbEmojiR.Clock { if chat.LastClockValue < pbEmojiR.Clock {
@ -690,9 +703,13 @@ func (m *MessageHandler) HandleEmojiReaction(state *ReceivedMessageState, pbEmoj
state.ModifiedChats[chat.ID] = true state.ModifiedChats[chat.ID] = true
state.AllChats[chat.ID] = chat 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 return nil
} }

View File

@ -707,56 +707,25 @@ func (db sqlitePersistence) BlockContact(contact *Contact) ([]*Chat, error) {
} }
func (db sqlitePersistence) SaveEmojiReaction(emojiReaction *EmojiReaction) (err error) { func (db sqlitePersistence) SaveEmojiReaction(emojiReaction *EmojiReaction) (err error) {
tx, err := db.db.BeginTx(context.Background(), &sql.TxOptions{}) query := "INSERT INTO emoji_reactions(id,clock_value,source,emoji_id,message_id,chat_id,retracted) VALUES (?,?,?,?,?,?,?)"
if err != nil { stmt, err := db.db.Prepare(query)
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)
if err != nil { if err != nil {
return return
} }
allValues := []interface{}{ _, err = stmt.Exec(
emojiReaction.ID, emojiReaction.ID(),
emojiReaction.Clock, emojiReaction.Clock,
emojiReaction.From, emojiReaction.From,
emojiReaction.Type, emojiReaction.Type,
emojiReaction.MessageId, emojiReaction.MessageId,
emojiReaction.ChatId, emojiReaction.ChatId,
emojiReaction.Retracted, emojiReaction.Retracted,
} )
_, err = stmt.Exec(allValues...)
return 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) { func (db sqlitePersistence) EmojiReactionByID(id string) (*EmojiReaction, error) {
tx, err := db.db.BeginTx(context.Background(), &sql.TxOptions{}) tx, err := db.db.BeginTx(context.Background(), &sql.TxOptions{})
if err != nil { if err != nil {
@ -772,20 +741,21 @@ func (db sqlitePersistence) EmojiReactionByID(id string) (*EmojiReaction, error)
}() }()
row := tx.QueryRow( row := tx.QueryRow(
fmt.Sprintf(` `SELECT
SELECT clock_value,
%s source,
emoji_id,
message_id,
chat_id,
retracted
FROM FROM
emoji_reactions emoji_reactions
WHERE WHERE
emoji_reactions.id = ? emoji_reactions.id = ?
`, db.tableEmojiReactionsAllFields()), `, id)
id,
)
emojiReaction := new(EmojiReaction) emojiReaction := new(EmojiReaction)
args := []interface{}{ args := []interface{}{
&emojiReaction.ID,
&emojiReaction.Clock, &emojiReaction.Clock,
&emojiReaction.From, &emojiReaction.From,
&emojiReaction.Type, &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 { func (db sqlitePersistence) RetractEmojiReaction(id string) error {
_, err := db.db.Exec(`UPDATE emoji_reactions SET retracted = 1 WHERE id = ?`, id) _, err := db.db.Exec(`UPDATE emoji_reactions SET retracted = 1 WHERE id = ?`, id)
return err return err

View File

@ -1778,6 +1778,9 @@ type ReceivedMessageState struct {
ModifiedInstallations map[string]bool ModifiedInstallations map[string]bool
// Map of existing messages // Map of existing messages
ExistingMessagesMap map[string]bool 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 to the client
Response *MessengerResponse Response *MessengerResponse
// Timesource is a time source for clock values/timestamps. // Timesource is a time source for clock values/timestamps.
@ -1795,6 +1798,7 @@ func (m *Messenger) handleRetrievedMessages(chatWithMessages map[transport.Filte
AllInstallations: m.allInstallations, AllInstallations: m.allInstallations,
ModifiedInstallations: m.modifiedInstallations, ModifiedInstallations: m.modifiedInstallations,
ExistingMessagesMap: make(map[string]bool), ExistingMessagesMap: make(map[string]bool),
EmojiReactions: make(map[string]*EmojiReaction),
Response: &MessengerResponse{}, Response: &MessengerResponse{},
Timesource: m.getTimesource(), Timesource: m.getTimesource(),
} }
@ -2040,13 +2044,6 @@ func (m *Messenger) handleRetrievedMessages(chatWithMessages map[transport.Filte
continue 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: default:
// Check if is an encrypted PushNotificationRegistration // Check if is an encrypted PushNotificationRegistration
if msg.Type == protobuf.ApplicationMetadataMessage_PUSH_NOTIFICATION_REGISTRATION { 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 { if len(contactsToSave) > 0 {
err = m.persistence.SaveContacts(contactsToSave) err = m.persistence.SaveContacts(contactsToSave)
if err != nil { 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() m.mutex.Lock()
defer m.mutex.Unlock() defer m.mutex.Unlock()
@ -3246,26 +3247,25 @@ func (m *Messenger) SendEmojiReaction(ctx context.Context, chatID, messageID str
ChatId: chatID, ChatId: chatID,
Type: protobuf.EmojiReaction_Type(emojiID), Type: protobuf.EmojiReaction_Type(emojiID),
}, },
From: types.EncodeHex(crypto.FromECDSAPub(&m.identity.PublicKey)), From: types.EncodeHex(crypto.FromECDSAPub(&m.identity.PublicKey)),
Retracted: false,
} }
encodedMessage, err := m.encodeChatEntity(chat, emojiR) encodedMessage, err := m.encodeChatEntity(chat, emojiR)
if err != nil { if err != nil {
return nil, err return nil, err
} }
id, err := m.dispatchMessage(ctx, &common.RawMessage{ _, err = m.dispatchMessage(ctx, &common.RawMessage{
LocalChatID: chatID, LocalChatID: chatID,
Payload: encodedMessage, Payload: encodedMessage,
MessageType: protobuf.ApplicationMetadataMessage_EMOJI_REACTION, MessageType: protobuf.ApplicationMetadataMessage_EMOJI_REACTION,
ResendAutomatically: true, // Don't resend using datasync, that would create quite a lot
// of traffic if clicking too eagelry
ResendAutomatically: false,
}) })
if err != nil { if err != nil {
return nil, err return nil, err
} }
emojiR.ID = types.EncodeHex(id)
response.EmojiReactions = []*EmojiReaction{emojiR} response.EmojiReactions = []*EmojiReaction{emojiR}
response.Chats = []*Chat{chat} response.Chats = []*Chat{chat}
@ -3281,44 +3281,45 @@ func (m *Messenger) SendEmojiReactionRetraction(ctx context.Context, emojiReacti
m.mutex.Lock() m.mutex.Lock()
defer m.mutex.Unlock() defer m.mutex.Unlock()
emojiReaction, err := m.persistence.EmojiReactionByID(emojiReactionID) emojiR, err := m.persistence.EmojiReactionByID(emojiReactionID)
if err != nil { if err != nil {
return nil, err return nil, err
} }
// Check that the sender is the key owner // Check that the sender is the key owner
pk := types.EncodeHex(crypto.FromECDSAPub(&m.identity.PublicKey)) pk := types.EncodeHex(crypto.FromECDSAPub(&m.identity.PublicKey))
if emojiReaction.From != pk { if emojiR.From != pk {
return nil, errors.Errorf("identity mismatch, "+ return nil, errors.Errorf("identity mismatch, "+
"emoji reactions can only be retracted by the reaction sender, "+ "emoji reactions can only be retracted by the reaction sender, "+
"emoji reaction sent by '%s', current identity '%s'", "emoji reaction sent by '%s', current identity '%s'",
emojiReaction.From, pk, emojiR.From, pk,
) )
} }
// Get chat and clock // Get chat and clock
chat, ok := m.allChats[emojiReaction.GetChatId()] chat, ok := m.allChats[emojiR.GetChatId()]
if !ok { if !ok {
return nil, ErrChatNotFound return nil, ErrChatNotFound
} }
clock, _ := chat.NextClockAndTimestamp(m.getTimesource()) clock, _ := chat.NextClockAndTimestamp(m.getTimesource())
// Build the EmojiReactionRetraction protobuf struct // Update the relevant fields
emojiRR := &protobuf.EmojiReactionRetraction{ emojiR.Clock = clock
Clock: clock, emojiR.Retracted = true
EmojiReactionId: emojiReactionID,
} encodedMessage, err := m.encodeChatEntity(chat, emojiR)
encodedMessage, err := proto.Marshal(emojiRR)
if err != nil { if err != nil {
return nil, err return nil, err
} }
// Send the marshalled EmojiReactionRetraction protobuf // Send the marshalled EmojiReactionRetraction protobuf
_, err = m.dispatchMessage(ctx, &common.RawMessage{ _, err = m.dispatchMessage(ctx, &common.RawMessage{
LocalChatID: emojiReaction.GetChatId(), LocalChatID: emojiR.GetChatId(),
Payload: encodedMessage, Payload: encodedMessage,
MessageType: protobuf.ApplicationMetadataMessage_EMOJI_REACTION_RETRACTION, MessageType: protobuf.ApplicationMetadataMessage_EMOJI_REACTION,
ResendAutomatically: true, // Don't resend using datasync, that would create quite a lot
// of traffic if clicking too eagelry
ResendAutomatically: false,
}) })
if err != nil { if err != nil {
return nil, err return nil, err
@ -3326,8 +3327,8 @@ func (m *Messenger) SendEmojiReactionRetraction(ctx context.Context, emojiReacti
// Update MessengerResponse // Update MessengerResponse
response := MessengerResponse{} response := MessengerResponse{}
emojiReaction.Retracted = true emojiR.Retracted = true
response.EmojiReactions = []*EmojiReaction{emojiReaction} response.EmojiReactions = []*EmojiReaction{emojiR}
response.Chats = []*Chat{chat} response.Chats = []*Chat{chat}
// Persist retraction state for emoji reaction // Persist retraction state for emoji reaction

View File

@ -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)
}

View File

@ -14,14 +14,10 @@
// 1591277220_add_index_messages.up.sql (240B) // 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.down.sql (0)
// 1593087212_add_mute_chat_and_raw_message_fields.up.sql (215B) // 1593087212_add_mute_chat_and_raw_message_fields.up.sql (215B)
// 1594390919_create_emoji_reaction_table.down.sql (27B) // 1594390919_create_emoji_reactions_table.down.sql (27B)
<<<<<<< HEAD // 1594390919_create_emoji_reactions_table.up.sql (265B)
// 1594390919_create_emoji_reactions_table.up.sql (234B)
// 1595862781_add_audio_data.down.sql (0) // 1595862781_add_audio_data.down.sql (0)
// 1595862781_add_audio_data.up.sql (246B) // 1595862781_add_audio_data.up.sql (246B)
=======
// 1594390919_create_emoji_reactions_table.up.sql (263B)
>>>>>>> 350ce45aa... make generate
// doc.go (850B) // doc.go (850B)
package migrations package migrations
@ -371,27 +367,27 @@ func _1593087212_add_mute_chat_and_raw_message_fieldsUpSql() (*asset, error) {
return a, nil 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( return bindataRead(
__1594390919_create_emoji_reaction_tableDownSql, __1594390919_create_emoji_reactions_tableDownSql,
"1594390919_create_emoji_reaction_table.down.sql", "1594390919_create_emoji_reactions_table.down.sql",
) )
} }
func _1594390919_create_emoji_reaction_tableDownSql() (*asset, error) { func _1594390919_create_emoji_reactions_tableDownSql() (*asset, error) {
bytes, err := _1594390919_create_emoji_reaction_tableDownSqlBytes() bytes, err := _1594390919_create_emoji_reactions_tableDownSqlBytes()
if err != nil { if err != nil {
return nil, err 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}} 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 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) { func _1594390919_create_emoji_reactions_tableUpSqlBytes() ([]byte, error) {
return bindataRead( return bindataRead(
@ -406,20 +402,8 @@ func _1594390919_create_emoji_reactions_tableUpSql() (*asset, error) {
return nil, err return nil, err
} }
<<<<<<< HEAD info := bindataFileInfo{name: "1594390919_create_emoji_reactions_table.up.sql", size: 265, mode: os.FileMode(0644), modTime: time.Unix(1595865239, 0)}
<<<<<<< HEAD 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}}
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}}
return a, nil 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, "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, "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{}}, "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.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{}}, "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{}}, "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.down.sql": &bintree{_1595862781_add_audio_dataDownSql, map[string]*bintree{}},
"1595862781_add_audio_data.up.sql": &bintree{_1595862781_add_audio_dataUpSql, map[string]*bintree{}}, "1595862781_add_audio_data.up.sql": &bintree{_1595862781_add_audio_dataUpSql, map[string]*bintree{}},

View File

@ -6,4 +6,4 @@ CREATE TABLE IF NOT EXISTS emoji_reactions (
message_id VARCHAR NOT NULL, message_id VARCHAR NOT NULL,
chat_id VARCHAR NOT NULL, chat_id VARCHAR NOT NULL,
retracted INT DEFAULT 0 retracted INT DEFAULT 0
); );

View File

@ -61,14 +61,22 @@ func (EmojiReaction_Type) EnumDescriptor() ([]byte, []int) {
} }
type EmojiReaction struct { type EmojiReaction struct {
Clock uint64 `protobuf:"varint,1,opt,name=clock,proto3" json:"clock,omitempty"` // clock Lamport timestamp of the chat message
ChatId string `protobuf:"bytes,2,opt,name=chat_id,json=chatId,proto3" json:"chat_id,omitempty"` Clock uint64 `protobuf:"varint,1,opt,name=clock,proto3" json:"clock,omitempty"`
MessageId string `protobuf:"bytes,3,opt,name=message_id,json=messageId,proto3" json:"message_id,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
MessageType MessageType `protobuf:"varint,4,opt,name=message_type,json=messageType,proto3,enum=protobuf.MessageType" json:"message_type,omitempty"` // target message also stores the chat_id
Type EmojiReaction_Type `protobuf:"varint,5,opt,name=type,proto3,enum=protobuf.EmojiReaction_Type" json:"type,omitempty"` ChatId string `protobuf:"bytes,2,opt,name=chat_id,json=chatId,proto3" json:"chat_id,omitempty"`
XXX_NoUnkeyedLiteral struct{} `json:"-"` // message_id the ID of the target message that the user wishes to react to
XXX_unrecognized []byte `json:"-"` MessageId string `protobuf:"bytes,3,opt,name=message_id,json=messageId,proto3" json:"message_id,omitempty"`
XXX_sizecache int32 `json:"-"` // 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{} } func (m *EmojiReaction) Reset() { *m = EmojiReaction{} }
@ -131,81 +139,40 @@ func (m *EmojiReaction) GetType() EmojiReaction_Type {
return EmojiReaction_UNKNOWN_EMOJI_REACTION_TYPE return EmojiReaction_UNKNOWN_EMOJI_REACTION_TYPE
} }
type EmojiReactionRetraction struct { func (m *EmojiReaction) GetRetracted() bool {
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 {
if m != nil { if m != nil {
return m.Clock return m.Retracted
} }
return 0 return false
}
func (m *EmojiReactionRetraction) GetEmojiReactionId() string {
if m != nil {
return m.EmojiReactionId
}
return ""
} }
func init() { func init() {
proto.RegisterEnum("protobuf.EmojiReaction_Type", EmojiReaction_Type_name, EmojiReaction_Type_value) proto.RegisterEnum("protobuf.EmojiReaction_Type", EmojiReaction_Type_name, EmojiReaction_Type_value)
proto.RegisterType((*EmojiReaction)(nil), "protobuf.EmojiReaction") proto.RegisterType((*EmojiReaction)(nil), "protobuf.EmojiReaction")
proto.RegisterType((*EmojiReactionRetraction)(nil), "protobuf.EmojiReactionRetraction")
} }
func init() { proto.RegisterFile("emoji_reaction.proto", fileDescriptor_0a088c907bbc7ed6) } func init() { proto.RegisterFile("emoji_reaction.proto", fileDescriptor_0a088c907bbc7ed6) }
var fileDescriptor_0a088c907bbc7ed6 = []byte{ var fileDescriptor_0a088c907bbc7ed6 = []byte{
// 320 bytes of a gzipped FileDescriptorProto // 305 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x7c, 0x91, 0xcf, 0x4e, 0xf2, 0x40, 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x54, 0x8e, 0xdf, 0x4f, 0x82, 0x50,
0x14, 0xc5, 0xbf, 0xc2, 0x14, 0xe8, 0xe5, 0x43, 0xc6, 0x09, 0x06, 0xe2, 0x9f, 0x48, 0x58, 0x11, 0x14, 0xc7, 0x43, 0x01, 0xe5, 0x98, 0x75, 0x77, 0x66, 0x8b, 0x95, 0x2d, 0xe6, 0x13, 0x4f, 0xac,
0x17, 0x8d, 0xd1, 0x8d, 0xdb, 0x2a, 0x0d, 0x54, 0x61, 0x4a, 0x86, 0x56, 0x42, 0x5c, 0x4c, 0xa0, 0xd5, 0x4b, 0xaf, 0x94, 0x4c, 0x29, 0x05, 0x77, 0x85, 0x9c, 0x4f, 0x0c, 0xe1, 0x56, 0x56, 0x08,
0x1d, 0x15, 0xb5, 0xb4, 0x81, 0xb2, 0xe0, 0xd9, 0x7c, 0x39, 0xd3, 0xa1, 0xa4, 0x76, 0xe3, 0x6a, 0xc3, 0xeb, 0x83, 0x7f, 0x6a, 0xff, 0x4d, 0xe3, 0xaa, 0x73, 0x3d, 0x9d, 0x7d, 0x7f, 0x7c, 0xce,
0x72, 0xee, 0x39, 0xbf, 0xc9, 0x99, 0x3b, 0xd0, 0x10, 0x41, 0xf8, 0xb1, 0xe4, 0x6b, 0x31, 0xf7, 0xbe, 0xd0, 0x61, 0x59, 0xfe, 0xb5, 0x8c, 0x4a, 0x16, 0x27, 0x7c, 0x99, 0xaf, 0xac, 0xa2, 0xcc,
0xe2, 0x65, 0xb8, 0xd2, 0xa3, 0x75, 0x18, 0x87, 0xa4, 0x22, 0x8f, 0xc5, 0xf6, 0xf5, 0xb4, 0x2a, 0x79, 0x8e, 0x4d, 0x71, 0x16, 0x9b, 0xf7, 0xab, 0x16, 0x5b, 0x6d, 0xb2, 0xf5, 0xce, 0xee, 0xfd,
0x56, 0xdb, 0x60, 0xb3, 0x1f, 0x77, 0xbe, 0x0b, 0x50, 0x33, 0x93, 0x3c, 0x4b, 0xe3, 0xa4, 0x01, 0xd6, 0xa0, 0xed, 0x54, 0x7d, 0xba, 0xaf, 0x63, 0x07, 0x94, 0xe4, 0x27, 0x4f, 0xbe, 0x75, 0xc9,
0xaa, 0xf7, 0x15, 0x7a, 0x9f, 0x2d, 0xa5, 0xad, 0x74, 0x11, 0xdb, 0x0b, 0xd2, 0x84, 0xb2, 0xf7, 0x90, 0x4c, 0x99, 0xee, 0x04, 0x5e, 0x42, 0x23, 0xf9, 0x8c, 0x79, 0xb4, 0x4c, 0xf5, 0x9a, 0x21,
0x3e, 0x8f, 0xf9, 0xd2, 0x6f, 0x15, 0xda, 0x4a, 0x57, 0x63, 0xa5, 0x44, 0x5a, 0x3e, 0xb9, 0x00, 0x99, 0x1a, 0x55, 0x2b, 0xe9, 0xa6, 0x78, 0x03, 0x90, 0xb1, 0xf5, 0x3a, 0xfe, 0x60, 0x55, 0x56,
0x08, 0xc4, 0x66, 0x33, 0x7f, 0x13, 0x89, 0x57, 0x94, 0x9e, 0x96, 0x4e, 0x2c, 0x9f, 0xdc, 0xc1, 0x17, 0x99, 0xb6, 0x77, 0xdc, 0x14, 0x1f, 0xe1, 0xf4, 0x10, 0xf3, 0x6d, 0xc1, 0x74, 0xd9, 0x90,
0xff, 0x83, 0x1d, 0xef, 0x22, 0xd1, 0x42, 0x6d, 0xa5, 0x7b, 0x74, 0x73, 0xa2, 0x1f, 0xda, 0xe8, 0xcc, 0xb3, 0xfb, 0x0b, 0xeb, 0xb0, 0xc6, 0x1a, 0xef, 0xd2, 0x60, 0x5b, 0x30, 0xda, 0xca, 0x8e,
0xa3, 0xbd, 0xeb, 0xec, 0x22, 0xc1, 0xaa, 0x41, 0x26, 0xc8, 0x35, 0x20, 0x49, 0xa8, 0x92, 0x38, 0x02, 0xef, 0x40, 0x16, 0x84, 0x22, 0x88, 0xee, 0x91, 0xf8, 0x37, 0xd7, 0x12, 0xa0, 0x68, 0x62,
0xcf, 0x88, 0x5c, 0x5d, 0x5d, 0x82, 0x32, 0xd9, 0x89, 0x00, 0x49, 0xf2, 0x12, 0xce, 0x5c, 0xfa, 0x17, 0xb4, 0x92, 0xf1, 0x32, 0x4e, 0x38, 0x4b, 0x75, 0xd5, 0x90, 0xcc, 0x26, 0x3d, 0x1a, 0xbd,
0x44, 0xed, 0x29, 0xe5, 0xe6, 0xc8, 0x7e, 0xb4, 0x38, 0x33, 0x8d, 0x07, 0xc7, 0xb2, 0x29, 0x77, 0x02, 0x64, 0xf1, 0xf7, 0x16, 0xae, 0x43, 0xef, 0xd5, 0xf3, 0x67, 0x5e, 0xe4, 0x8c, 0xfd, 0x17,
0x66, 0x63, 0x13, 0xff, 0x23, 0x15, 0x40, 0x43, 0xfb, 0xd9, 0xc4, 0x0a, 0xa9, 0x81, 0xe6, 0x0c, 0x37, 0xa2, 0x8e, 0xfd, 0x1c, 0xb8, 0xbe, 0x17, 0x05, 0xf3, 0x89, 0x43, 0x4e, 0xb0, 0x09, 0xf2,
0xdc, 0xd1, 0xfd, 0x84, 0xbb, 0x63, 0x5c, 0x20, 0x75, 0xa8, 0xa6, 0xb2, 0x67, 0x4f, 0x29, 0x2e, 0xc8, 0x7f, 0x73, 0x88, 0x84, 0x6d, 0xd0, 0x82, 0x61, 0x38, 0x7e, 0x9a, 0x46, 0xe1, 0x84, 0xd4,
0x12, 0x0d, 0xd4, 0xa1, 0xe1, 0xf6, 0x07, 0x18, 0x91, 0x32, 0x14, 0x27, 0x46, 0x0f, 0xab, 0xc9, 0xf0, 0x1c, 0x5a, 0x7b, 0xd9, 0xf7, 0x67, 0x1e, 0xa9, 0xa3, 0x06, 0xca, 0xc8, 0x0e, 0x07, 0x43,
0xcc, 0xa0, 0x7d, 0x36, 0xc3, 0xa5, 0xce, 0x0b, 0x34, 0x73, 0x6d, 0x98, 0x88, 0xd7, 0x7f, 0xae, 0x22, 0x63, 0x03, 0xea, 0x53, 0xbb, 0x4f, 0x94, 0xca, 0xb3, 0xbd, 0x01, 0x9d, 0x13, 0x75, 0xa1,
0xf1, 0x0a, 0x8e, 0xf3, 0xbf, 0x93, 0x2d, 0xb4, 0x2e, 0x7e, 0xdf, 0x64, 0xf9, 0x8b, 0x92, 0x7c, 0x8a, 0xc9, 0x0f, 0x7f, 0x01, 0x00, 0x00, 0xff, 0xff, 0x03, 0x65, 0x6e, 0x92, 0x91, 0x01, 0x00,
0xf1, 0xed, 0x4f, 0x00, 0x00, 0x00, 0xff, 0xff, 0x18, 0x16, 0x6b, 0xcc, 0xd0, 0x01, 0x00, 0x00, 0x00,
} }

View File

@ -30,9 +30,7 @@ message EmojiReaction {
SAD = 5; SAD = 5;
ANGRY = 6; ANGRY = 6;
} }
}
message EmojiReactionRetraction { // whether this is a rectraction of a previously sent emoji
uint64 clock = 1; bool retracted = 6;
string emoji_reaction_id = 2;
} }

View File

@ -240,9 +240,7 @@ func init() {
proto.RegisterType((*MembershipUpdateMessage)(nil), "protobuf.MembershipUpdateMessage") proto.RegisterType((*MembershipUpdateMessage)(nil), "protobuf.MembershipUpdateMessage")
} }
func init() { func init() { proto.RegisterFile("membership_update_message.proto", fileDescriptor_8d37dd0dc857a6be) }
proto.RegisterFile("membership_update_message.proto", fileDescriptor_8d37dd0dc857a6be)
}
var fileDescriptor_8d37dd0dc857a6be = []byte{ var fileDescriptor_8d37dd0dc857a6be = []byte{
// 393 bytes of a gzipped FileDescriptorProto // 393 bytes of a gzipped FileDescriptorProto

View File

@ -232,8 +232,6 @@ func (m *StatusMessage) HandleApplication() error {
return m.unmarshalProtobufData(new(protobuf.PushNotificationResponse)) return m.unmarshalProtobufData(new(protobuf.PushNotificationResponse))
case protobuf.ApplicationMetadataMessage_EMOJI_REACTION: case protobuf.ApplicationMetadataMessage_EMOJI_REACTION:
return m.unmarshalProtobufData(new(protobuf.EmojiReaction)) return m.unmarshalProtobufData(new(protobuf.EmojiReaction))
case protobuf.ApplicationMetadataMessage_EMOJI_REACTION_RETRACTION:
return m.unmarshalProtobufData(new(protobuf.EmojiReactionRetraction))
case protobuf.ApplicationMetadataMessage_PUSH_NOTIFICATION_REGISTRATION: case protobuf.ApplicationMetadataMessage_PUSH_NOTIFICATION_REGISTRATION:
// This message is a bit different as it's encrypted, so we pass it straight through // This message is a bit different as it's encrypted, so we pass it straight through
v := reflect.ValueOf(m.DecryptedPayload) v := reflect.ValueOf(m.DecryptedPayload)

View File

@ -17,6 +17,7 @@ import (
"github.com/status-im/status-go/mailserver" "github.com/status-im/status-go/mailserver"
"github.com/status-im/status-go/protocol" "github.com/status-im/status-go/protocol"
"github.com/status-im/status-go/protocol/encryption/multidevice" "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/pushnotificationclient"
"github.com/status-im/status-go/protocol/transport" "github.com/status-im/status-go/protocol/transport"
"github.com/status-im/status-go/services/ext/mailservers" "github.com/status-im/status-go/services/ext/mailservers"
@ -511,6 +512,16 @@ func (api *PublicAPI) RegisteredForPushNotifications() (bool, error) {
return api.service.messenger.RegisteredForPushNotifications() 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. // Echo is a method for testing purposes.
func (api *PublicAPI) Echo(ctx context.Context, message string) (string, error) { func (api *PublicAPI) Echo(ctx context.Context, message string) (string, error) {
return message, nil return message, nil