Add parsing and storing of mentions

This commit is contained in:
Andrea Maria Piana 2020-09-01 12:34:28 +02:00
parent 57728224d4
commit 7d5d413222
No known key found for this signature in database
GPG Key ID: AA6CCA6DE0E06424
7 changed files with 153 additions and 2 deletions

View File

@ -12,6 +12,7 @@ import (
"github.com/golang/protobuf/proto"
"github.com/status-im/markdown"
"github.com/status-im/markdown/ast"
"github.com/status-im/status-go/protocol/protobuf"
)
@ -117,6 +118,9 @@ type Message struct {
// that has been updated
Replace string `json:"replace,omitempty"`
SigPubKey *ecdsa.PublicKey `json:"-"`
// Mentions is an array of mentions for a given message
Mentions []string
}
func (m *Message) MarshalJSON() ([]byte, error) {
@ -151,6 +155,7 @@ func (m *Message) MarshalJSON() ([]byte, error) {
Timestamp uint64 `json:"timestamp"`
ContentType protobuf.ChatMessage_ContentType `json:"contentType"`
MessageType protobuf.MessageType `json:"messageType"`
Mentions []string `json:"mentions,omitempty"`
}{
ID: m.ID,
WhisperTimestamp: m.WhisperTimestamp,
@ -174,6 +179,7 @@ func (m *Message) MarshalJSON() ([]byte, error) {
Audio: m.Base64Audio,
Timestamp: m.Timestamp,
ContentType: m.ContentType,
Mentions: m.Mentions,
MessageType: m.MessageType,
CommandParameters: m.CommandParameters,
}
@ -295,10 +301,33 @@ func (m *Message) parseAudio() error {
return nil
}
type MentionNodeVisitor struct {
mentions []string
}
func (v *MentionNodeVisitor) Visit(node ast.Node, entering bool) ast.WalkStatus {
// only on entering we fetch, otherwise we go on
if !entering {
return ast.GoToNext
}
switch n := node.(type) {
case *ast.Mention:
v.mentions = append(v.mentions, string(n.Literal))
}
return ast.GoToNext
}
func extractMentions(parsedText ast.Node) []string {
visitor := &MentionNodeVisitor{}
ast.Walk(parsedText, visitor)
return visitor.mentions
}
// PrepareContent return the parsed content of the message, the line-count and whether
// is a right-to-left message
func (m *Message) PrepareContent() error {
parsedText := markdown.Parse([]byte(m.Text), nil)
m.Mentions = extractMentions(parsedText)
jsonParsedText, err := json.Marshal(parsedText)
if err != nil {
return err

View File

@ -40,6 +40,7 @@ func (db sqlitePersistence) tableUserMessagesAllFields() string {
audio_type,
audio_duration_ms,
audio_base64,
mentions,
command_id,
command_value,
command_from,
@ -74,6 +75,7 @@ func (db sqlitePersistence) tableUserMessagesAllFieldsJoin() string {
m1.image_base64,
COALESCE(m1.audio_duration_ms,0),
m1.audio_base64,
m1.mentions,
m1.command_id,
m1.command_value,
m1.command_from,
@ -111,6 +113,7 @@ func (db sqlitePersistence) tableUserMessagesScanAllFields(row scanner, message
var quotedImage sql.NullString
var quotedAudio sql.NullString
var quotedAudioDuration sql.NullInt64
var serializedMentions []byte
var alias sql.NullString
var identicon sql.NullString
@ -138,6 +141,7 @@ func (db sqlitePersistence) tableUserMessagesScanAllFields(row scanner, message
&message.Base64Image,
&audio.DurationMs,
&message.Base64Audio,
&serializedMentions,
&command.ID,
&command.Value,
&command.From,
@ -177,6 +181,13 @@ func (db sqlitePersistence) tableUserMessagesScanAllFields(row scanner, message
message.Alias = alias.String
message.Identicon = identicon.String
if serializedMentions != nil {
err := json.Unmarshal(serializedMentions, &message.Mentions)
if err != nil {
return err
}
}
switch message.ContentType {
case protobuf.ChatMessage_STICKER:
message.Payload = &protobuf.ChatMessage_Sticker{Sticker: sticker}
@ -211,6 +222,15 @@ func (db sqlitePersistence) tableUserMessagesAllValues(message *Message) ([]inte
if command == nil {
command = &CommandParameters{}
}
var serializedMentions []byte
var err error
if len(message.Mentions) != 0 {
serializedMentions, err = json.Marshal(message.Mentions)
if err != nil {
return nil, err
}
}
return []interface{}{
message.ID,
message.WhisperTimestamp,
@ -235,6 +255,7 @@ func (db sqlitePersistence) tableUserMessagesAllValues(message *Message) ([]inte
audio.Type,
audio.DurationMs,
message.Base64Audio,
serializedMentions,
command.ID,
command.Value,
command.From,

View File

@ -7,6 +7,8 @@ import (
"github.com/stretchr/testify/require"
"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"
)
@ -94,3 +96,21 @@ func TestGetAudioMessageMIME(t *testing.T) {
_, err = getImageMessageMIME(unknown)
require.Error(t, err)
}
func TestPrepareContentMentions(t *testing.T) {
message := &Message{}
pk1, err := crypto.GenerateKey()
require.NoError(t, err)
pk1String := types.EncodeHex(crypto.FromECDSAPub(&pk1.PublicKey))
pk2, err := crypto.GenerateKey()
require.NoError(t, err)
pk2String := types.EncodeHex(crypto.FromECDSAPub(&pk2.PublicKey))
message.Text = "hey @" + pk1String + " @" + pk2String
require.NoError(t, message.PrepareContent())
require.Len(t, message.Mentions, 2)
require.Equal(t, message.Mentions[0], pk1String)
require.Equal(t, message.Mentions[1], pk2String)
}

View File

@ -22,6 +22,8 @@
// 1596805115_create_group_chat_invitations_table.up.sql (231B)
// 1597322655_add_invitation_admin_chat_field.up.sql (54B)
// 1597757544_add_nickname.up.sql (52B)
// 1598955122_add_mentions.down.sql (0)
// 1598955122_add_mentions.up.sql (52B)
// 1599641390_add_emoji_reactions_index.down.sql (67B)
// 1599641390_add_emoji_reactions_index.up.sql (126B)
// doc.go (850B)
@ -533,6 +535,46 @@ func _1597757544_add_nicknameUpSql() (*asset, error) {
return a, nil
}
var __1598955122_add_mentionsDownSql = []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\x01\x00\x00\xff\xff\x00\x00\x00\x00\x00\x00\x00\x00")
func _1598955122_add_mentionsDownSqlBytes() ([]byte, error) {
return bindataRead(
__1598955122_add_mentionsDownSql,
"1598955122_add_mentions.down.sql",
)
}
func _1598955122_add_mentionsDownSql() (*asset, error) {
bytes, err := _1598955122_add_mentionsDownSqlBytes()
if err != nil {
return nil, err
}
info := bindataFileInfo{name: "1598955122_add_mentions.down.sql", size: 0, mode: os.FileMode(0644), modTime: time.Unix(1599679300, 0)}
a := &asset{bytes: bytes, info: info, digest: [32]uint8{0xe3, 0xb0, 0xc4, 0x42, 0x98, 0xfc, 0x1c, 0x14, 0x9a, 0xfb, 0xf4, 0xc8, 0x99, 0x6f, 0xb9, 0x24, 0x27, 0xae, 0x41, 0xe4, 0x64, 0x9b, 0x93, 0x4c, 0xa4, 0x95, 0x99, 0x1b, 0x78, 0x52, 0xb8, 0x55}}
return a, nil
}
var __1598955122_add_mentionsUpSql = []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\x72\xf4\x09\x71\x0d\x52\x08\x71\x74\xf2\x71\x55\x28\x2d\x4e\x2d\x8a\xcf\x4d\x2d\x2e\x4e\x4c\x4f\x2d\x56\x70\x74\x71\x51\x70\xf6\xf7\x09\xf5\xf5\x53\xc8\x4d\xcd\x2b\xc9\xcc\xcf\x2b\x56\x70\xf2\xf1\x77\xb2\xe6\x02\x04\x00\x00\xff\xff\xca\xf8\x74\x41\x34\x00\x00\x00")
func _1598955122_add_mentionsUpSqlBytes() ([]byte, error) {
return bindataRead(
__1598955122_add_mentionsUpSql,
"1598955122_add_mentions.up.sql",
)
}
func _1598955122_add_mentionsUpSql() (*asset, error) {
bytes, err := _1598955122_add_mentionsUpSqlBytes()
if err != nil {
return nil, err
}
info := bindataFileInfo{name: "1598955122_add_mentions.up.sql", size: 52, mode: os.FileMode(0644), modTime: time.Unix(1599679300, 0)}
a := &asset{bytes: bytes, info: info, digest: [32]uint8{0x8d, 0x22, 0x17, 0x92, 0xd2, 0x11, 0x4e, 0x7, 0x93, 0x9a, 0x55, 0xfd, 0xb, 0x97, 0xc4, 0x63, 0x6a, 0x81, 0x97, 0xcd, 0xb2, 0xf8, 0x4b, 0x5f, 0x3c, 0xfa, 0x3a, 0x38, 0x53, 0x10, 0xed, 0x9d}}
return a, nil
}
var __1599641390_add_emoji_reactions_indexDownSql = []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\x72\x09\xf2\x0f\x50\xf0\xf4\x73\x71\x8d\x50\x48\xcd\xcd\xcf\xca\x8c\x2f\x4a\x4d\x4c\x2e\xc9\xcc\xcf\x2b\x8e\xcf\x4d\x2d\x2e\x4e\x4c\x4f\x8d\xcf\x4c\x89\xcf\xc9\x4f\x4e\xcc\x89\x4f\xce\x48\x2c\x01\xf1\x8a\x52\x4b\x8a\x12\x93\x4b\x52\x53\xe2\x33\x53\x2a\xac\xb9\x00\x01\x00\x00\xff\xff\xb2\x85\x84\xa0\x43\x00\x00\x00")
func _1599641390_add_emoji_reactions_indexDownSqlBytes() ([]byte, error) {
@ -548,7 +590,7 @@ func _1599641390_add_emoji_reactions_indexDownSql() (*asset, error) {
return nil, err
}
info := bindataFileInfo{name: "1599641390_add_emoji_reactions_index.down.sql", size: 67, mode: os.FileMode(0644), modTime: time.Unix(1599641440, 0)}
info := bindataFileInfo{name: "1599641390_add_emoji_reactions_index.down.sql", size: 67, mode: os.FileMode(0644), modTime: time.Unix(1599679300, 0)}
a := &asset{bytes: bytes, info: info, digest: [32]uint8{0x89, 0x39, 0x0, 0x51, 0x5b, 0x48, 0xc3, 0xf3, 0x6a, 0x96, 0xf1, 0xd2, 0xa6, 0x60, 0xa8, 0x68, 0x21, 0xb5, 0xa0, 0x11, 0x11, 0x99, 0xde, 0xad, 0xa6, 0xa7, 0x56, 0xc1, 0xb2, 0xa6, 0x63, 0xe4}}
return a, nil
}
@ -568,7 +610,7 @@ func _1599641390_add_emoji_reactions_indexUpSql() (*asset, error) {
return nil, err
}
info := bindataFileInfo{name: "1599641390_add_emoji_reactions_index.up.sql", size: 126, mode: os.FileMode(0644), modTime: time.Unix(1599641420, 0)}
info := bindataFileInfo{name: "1599641390_add_emoji_reactions_index.up.sql", size: 126, mode: os.FileMode(0644), modTime: time.Unix(1599679300, 0)}
a := &asset{bytes: bytes, info: info, digest: [32]uint8{0xf9, 0xd8, 0xdc, 0xa7, 0xb, 0x92, 0x7a, 0x61, 0x37, 0x24, 0x1c, 0x77, 0x5e, 0xe, 0x7e, 0xfc, 0x9f, 0x98, 0x7b, 0x65, 0xe7, 0xf9, 0x71, 0x57, 0x89, 0x2d, 0x90, 0x1b, 0xf6, 0x5e, 0x37, 0xe8}}
return a, nil
}
@ -728,6 +770,10 @@ var _bindata = map[string]func() (*asset, error){
"1597757544_add_nickname.up.sql": _1597757544_add_nicknameUpSql,
"1598955122_add_mentions.down.sql": _1598955122_add_mentionsDownSql,
"1598955122_add_mentions.up.sql": _1598955122_add_mentionsUpSql,
"1599641390_add_emoji_reactions_index.down.sql": _1599641390_add_emoji_reactions_indexDownSql,
"1599641390_add_emoji_reactions_index.up.sql": _1599641390_add_emoji_reactions_indexUpSql,
@ -798,6 +844,8 @@ var _bintree = &bintree{nil, map[string]*bintree{
"1596805115_create_group_chat_invitations_table.up.sql": &bintree{_1596805115_create_group_chat_invitations_tableUpSql, map[string]*bintree{}},
"1597322655_add_invitation_admin_chat_field.up.sql": &bintree{_1597322655_add_invitation_admin_chat_fieldUpSql, map[string]*bintree{}},
"1597757544_add_nickname.up.sql": &bintree{_1597757544_add_nicknameUpSql, map[string]*bintree{}},
"1598955122_add_mentions.down.sql": &bintree{_1598955122_add_mentionsDownSql, map[string]*bintree{}},
"1598955122_add_mentions.up.sql": &bintree{_1598955122_add_mentionsUpSql, map[string]*bintree{}},
"1599641390_add_emoji_reactions_index.down.sql": &bintree{_1599641390_add_emoji_reactions_indexDownSql, map[string]*bintree{}},
"1599641390_add_emoji_reactions_index.up.sql": &bintree{_1599641390_add_emoji_reactions_indexUpSql, map[string]*bintree{}},
"doc.go": &bintree{docGo, map[string]*bintree{}},

View File

@ -0,0 +1 @@
ALTER TABLE user_messages ADD COLUMN mentions BLOB;

View File

@ -11,6 +11,8 @@ import (
"github.com/stretchr/testify/require"
"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/sqlite"
)
@ -529,3 +531,33 @@ func TestSaveChat(t *testing.T) {
require.NoError(t, err)
require.Equal(t, &chat, retrievedChat)
}
func TestSaveMentions(t *testing.T) {
chatID := "chat-id"
db, err := openTestDB()
require.NoError(t, err)
p := sqlitePersistence{db: db}
key, err := crypto.GenerateKey()
require.NoError(t, err)
pkString := types.EncodeHex(crypto.FromECDSAPub(&key.PublicKey))
message := Message{
ID: "1",
LocalChatID: chatID,
ChatMessage: protobuf.ChatMessage{Text: "some-text"},
From: "me",
Mentions: []string{pkString},
}
err = p.SaveMessages([]*Message{&message})
require.NoError(t, err)
retrievedMessages, _, err := p.MessageByChatID(chatID, "", 10)
require.NoError(t, err)
require.Len(t, retrievedMessages, 1)
require.Len(t, retrievedMessages[0].Mentions, 1)
require.Equal(t, retrievedMessages[0].Mentions, message.Mentions)
}