diff --git a/VERSION b/VERSION index 2f4c74eb2..25a153f0a 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -0.56.0 +0.56.1 diff --git a/_assets/tests/test.aac b/_assets/tests/test.aac new file mode 100644 index 000000000..681c94e4f Binary files /dev/null and b/_assets/tests/test.aac differ diff --git a/protocol/audio/type.go b/protocol/audio/type.go new file mode 100644 index 000000000..a0be3bab2 --- /dev/null +++ b/protocol/audio/type.go @@ -0,0 +1,29 @@ +package audio + +import ( + "github.com/status-im/status-go/protocol/protobuf" +) + +func aac(buf []byte) bool { + return len(buf) > 1 && + ((buf[0] == 0xFF && buf[1] == 0xF1) || + (buf[0] == 0xFF && buf[1] == 0xF9)) +} + +func amr(buf []byte) bool { + return len(buf) > 11 && + buf[0] == 0x23 && buf[1] == 0x21 && + buf[2] == 0x41 && buf[3] == 0x4D && + buf[4] == 0x52 && buf[5] == 0x0A +} + +func Type(buf []byte) protobuf.AudioMessage_AudioType { + switch { + case aac(buf): + return protobuf.AudioMessage_AAC + case amr(buf): + return protobuf.AudioMessage_AMR + default: + return protobuf.AudioMessage_UNKNOWN_AUDIO_TYPE + } +} diff --git a/protocol/common/feature_flags.go b/protocol/common/feature_flags.go index 9473e1da1..18e81da26 100644 --- a/protocol/common/feature_flags.go +++ b/protocol/common/feature_flags.go @@ -5,4 +5,7 @@ type FeatureFlags struct { // using datasync, breaking change for non-v1 clients. Public messages // are not impacted Datasync bool + + // PushNotification indicates whether we should be enabling the push notification feature + PushNotifications bool } diff --git a/protocol/message.go b/protocol/message.go index 27c6e885b..b6f363bc2 100644 --- a/protocol/message.go +++ b/protocol/message.go @@ -22,6 +22,10 @@ type QuotedMessage struct { Text string `json:"text"` // Base64Image is the converted base64 image Base64Image string `json:"image,omitempty"` + // Base64Audio is the converted base64 audio + Base64Audio string `json:"audio,omitempty"` + // AudioDurationMs is the audio duration in milliseconds + AudioDurationMs uint64 `json:"audioDurationMs,omitempty"` } type CommandState int @@ -102,6 +106,10 @@ type Message struct { Base64Image string `json:"image,omitempty"` // ImagePath is the path of the image to be sent ImagePath string `json:"imagePath,omitempty"` + // Base64Audio is the converted base64 audio + Base64Audio string `json:"audio,omitempty"` + // AudioPath is the path of the audio to be sent + AudioPath string `json:"audioPath,omitempty"` // Replace indicates that this is a replacement of a message // that has been updated @@ -134,6 +142,8 @@ func (m *Message) MarshalJSON() ([]byte, error) { ResponseTo string `json:"responseTo"` EnsName string `json:"ensName"` Image string `json:"image,omitempty"` + Audio string `json:"audio,omitempty"` + AudioDurationMs uint64 `json:"audioDurationMs,omitempty"` Sticker *StickerAlias `json:"sticker"` CommandParameters *CommandParameters `json:"commandParameters"` Timestamp uint64 `json:"timestamp"` @@ -159,6 +169,7 @@ func (m *Message) MarshalJSON() ([]byte, error) { ResponseTo: m.ResponseTo, EnsName: m.EnsName, Image: m.Base64Image, + Audio: m.Base64Audio, Timestamp: m.Timestamp, ContentType: m.ContentType, MessageType: m.MessageType, @@ -171,6 +182,11 @@ func (m *Message) MarshalJSON() ([]byte, error) { Hash: sticker.Hash, } } + + if audio := m.GetAudio(); audio != nil { + item.AudioDurationMs = audio.DurationMs + } + return json.Marshal(item) } @@ -178,11 +194,12 @@ func (m *Message) UnmarshalJSON(data []byte) error { type Alias Message aux := struct { *Alias - ResponseTo string `json:"responseTo"` - EnsName string `json:"ensName"` - ChatID string `json:"chatId"` - Sticker *protobuf.StickerMessage `json:"sticker"` - ContentType protobuf.ChatMessage_ContentType `json:"contentType"` + ResponseTo string `json:"responseTo"` + EnsName string `json:"ensName"` + ChatID string `json:"chatId"` + Sticker *protobuf.StickerMessage `json:"sticker"` + AudioDurationMs uint64 `json:"audioDurationMs"` + ContentType protobuf.ChatMessage_ContentType `json:"contentType"` }{ Alias: (*Alias)(m), } @@ -192,6 +209,11 @@ func (m *Message) UnmarshalJSON(data []byte) error { if aux.ContentType == protobuf.ChatMessage_STICKER { m.Payload = &protobuf.ChatMessage_Sticker{Sticker: aux.Sticker} } + if aux.ContentType == protobuf.ChatMessage_AUDIO { + m.Payload = &protobuf.ChatMessage_Audio{ + Audio: &protobuf.AudioMessage{DurationMs: aux.AudioDurationMs}, + } + } m.ResponseTo = aux.ResponseTo m.EnsName = aux.EnsName m.ChatId = aux.ChatID @@ -239,6 +261,37 @@ func (m *Message) parseImage() error { return nil } +// parseAudio check the message contains an audio, and if so +// it creates a base64 encoded version of it. +func (m *Message) parseAudio() error { + if m.ContentType != protobuf.ChatMessage_AUDIO { + return nil + } + audio := m.GetAudio() + if audio == nil { + return errors.New("audio empty") + } + + payload := audio.Payload + + e64 := base64.StdEncoding + + maxEncLen := e64.EncodedLen(len(payload)) + encBuf := make([]byte, maxEncLen) + + e64.Encode(encBuf, payload) + + mime, err := getAudioMessageMIME(audio) + + if err != nil { + return err + } + + m.Base64Audio = fmt.Sprintf("data:audio/%s;base64,%s", mime, encBuf) + + return nil +} + // PrepareContent return the parsed content of the message, the line-count and whether // is a right-to-left message func (m *Message) PrepareContent() error { @@ -250,7 +303,10 @@ func (m *Message) PrepareContent() error { m.ParsedText = jsonParsedText m.LineCount = strings.Count(m.Text, "\n") m.RTL = isRTL(m.Text) - return m.parseImage() + if err := m.parseImage(); err != nil { + return err + } + return m.parseAudio() } func getImageMessageMIME(i *protobuf.ImageMessage) (string, error) { @@ -266,3 +322,14 @@ func getImageMessageMIME(i *protobuf.ImageMessage) (string, error) { } return "", errors.New("image format not supported") } + +func getAudioMessageMIME(i *protobuf.AudioMessage) (string, error) { + switch i.Type { + case protobuf.AudioMessage_AAC: + return "aac", nil + case protobuf.AudioMessage_AMR: + return "amr", nil + } + + return "", errors.New("audio format not supported") +} diff --git a/protocol/message_persistence.go b/protocol/message_persistence.go index b52fe7454..d25d62a8f 100644 --- a/protocol/message_persistence.go +++ b/protocol/message_persistence.go @@ -36,6 +36,10 @@ func (db sqlitePersistence) tableUserMessagesAllFields() string { image_payload, image_type, image_base64, + audio_payload, + audio_type, + audio_duration_ms, + audio_base64, command_id, command_value, command_from, @@ -68,6 +72,8 @@ func (db sqlitePersistence) tableUserMessagesAllFieldsJoin() string { m1.sticker_pack, m1.sticker_hash, m1.image_base64, + m1.audio_duration_ms, + m1.audio_base64, m1.command_id, m1.command_value, m1.command_from, @@ -83,6 +89,8 @@ func (db sqlitePersistence) tableUserMessagesAllFieldsJoin() string { m2.source, m2.text, m2.image_base64, + m2.audio_duration_ms, + m2.audio_base64, c.alias, c.identicon` } @@ -99,11 +107,14 @@ func (db sqlitePersistence) tableUserMessagesScanAllFields(row scanner, message var quotedText sql.NullString var quotedFrom sql.NullString var quotedImage sql.NullString + var quotedAudio sql.NullString + var quotedAudioDuration sql.NullInt64 var alias sql.NullString var identicon sql.NullString sticker := &protobuf.StickerMessage{} command := &CommandParameters{} + audio := &protobuf.AudioMessage{} args := []interface{}{ &message.ID, @@ -123,6 +134,8 @@ func (db sqlitePersistence) tableUserMessagesScanAllFields(row scanner, message &sticker.Pack, &sticker.Hash, &message.Base64Image, + &audio.DurationMs, + &message.Base64Audio, &command.ID, &command.Value, &command.From, @@ -138,6 +151,8 @@ func (db sqlitePersistence) tableUserMessagesScanAllFields(row scanner, message "edFrom, "edText, "edImage, + "edAudioDuration, + "edAudio, &alias, &identicon, } @@ -148,9 +163,11 @@ func (db sqlitePersistence) tableUserMessagesScanAllFields(row scanner, message if quotedText.Valid { message.QuotedMessage = &QuotedMessage{ - From: quotedFrom.String, - Text: quotedText.String, - Base64Image: quotedImage.String, + From: quotedFrom.String, + Text: quotedText.String, + Base64Image: quotedImage.String, + AudioDurationMs: uint64(quotedAudioDuration.Int64), + Base64Audio: quotedAudio.String, } } message.Alias = alias.String @@ -159,6 +176,10 @@ func (db sqlitePersistence) tableUserMessagesScanAllFields(row scanner, message message.Payload = &protobuf.ChatMessage_Sticker{Sticker: sticker} } + if message.ContentType == protobuf.ChatMessage_AUDIO { + message.Payload = &protobuf.ChatMessage_Audio{Audio: audio} + } + if message.ContentType == protobuf.ChatMessage_TRANSACTION_COMMAND { message.CommandParameters = command } @@ -177,6 +198,11 @@ func (db sqlitePersistence) tableUserMessagesAllValues(message *Message) ([]inte image = &protobuf.ImageMessage{} } + audio := message.GetAudio() + if audio == nil { + audio = &protobuf.AudioMessage{} + } + command := message.CommandParameters if command == nil { command = &CommandParameters{} @@ -201,6 +227,10 @@ func (db sqlitePersistence) tableUserMessagesAllValues(message *Message) ([]inte image.Payload, image.Type, message.Base64Image, + audio.Payload, + audio.Type, + audio.DurationMs, + message.Base64Audio, command.ID, command.Value, command.From, diff --git a/protocol/message_test.go b/protocol/message_test.go index 94693d153..b8dbe80fd 100644 --- a/protocol/message_test.go +++ b/protocol/message_test.go @@ -11,6 +11,7 @@ import ( ) const expectedJPEG = "data:image/jpeg;base64,/9j/2wBDAAMCAgICAgMCAgIDAwMDBAYEBAQEBAgGBgUGCQgKCgkICQkKDA8MCgsOCwkJDRENDg8QEBEQCgwSExIQEw8QEBD/yQALCAABAAEBAREA/8wABgAQEAX/2gAIAQEAAD8A0s8g/9k=" +const expectedAAC = "data:audio/aac;base64,//FQgBw//NoATGF2YzUyLjcwLjAAQniptokphEFCg5qs1v9fn48+qz1rfWNhwvz+CqB5dipmq3T2PlT1Ld6sPj+19fUt1C3NKV0KowiqohZVCrdf19WMatvV3YbIvAuy/q2RafA8UiZPmZY7DdmHZtP9ri25kedWSiMKQRt79ttlod55LkuX7/f7/f7/f7/YGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYHNqo8g5qs1v9fn48+qz1rfWNhwvz+CqAAAAAAAAAAAAAAAAAAAAAAABw//FQgCNf/CFXbUZfDKFRgsYlKDegtXJH9eLkT54uRM1ckDYDcXRzZGF6Kz5Yps5fTeLY6w7gclwly+0PJL3udY3PyekTFI65bdniF3OjvHeafzZfWTs0qRMSkdll1sbb4SNT5e8vX98ytot6jEZ0NhJi2pBVP/tKV2JMyo36n9uxR2tKR+FoLCsP4SVi49kmvaSCWm5bQD96OmVQA9Q40bqnOa7rT8j9N0TlK991XdcenGTLbyS6eUnN2U1ckf14uRPni5EzVyQAAAAAAAAAAx6Q1flBp+KH2LhgH2Xx+14QB2/jcizm6ngck4vB9DoH9/Vcb7E8Dy+D/1ii1pSPwsUUUXCSsXHsk17SBfKwn2uHr6QAAAAAAAHA//FQgBt//CF3VO1KFCFWcd/r04m+O0758/tXHUlvaqEK9lvhUZXEZMXKMV/LQ6B3/mOl/Mrfs6jpD2b7f+n4yt+tm2x5ZmnpD++dZo/V9VgblI3OW/s1b8qt0h1RBiIRIIYIYQIBeCM8yy7etkwt1JAajRSoZGwwNZ07TTFTyMR1mTUVVUTW97vaDaHU5DV1snBf0mN4fraa+rf/vpdZ8FxqatGjNxPh35UuVfpNqc48W4nZ6rOO/16cTfHad8+f2rjqS3tVAAAAAAAAAAAAAAAAAAAAAAAAAAAO//FQgBm//CEXVPU+GiFsPr7x6+N6v+m+q511I4SgtYVyoyWjcMWMxkaxxDGSx1qVcarjDESt8zLQehx/lkil/GrHBy/NfJcHek0XtfanZJLHNXO2rUnFklPAlQSBS4l0pIoXIfORcXx0UYj1nTsSe1/0wXDkkFCfxWHtqRayOmWm3oS6JGdnZdtjesjByefiS8dLW1tVVVC58ijoxN3gmGFYj07+YJ6eth9fePXxvV/031XOupHCUAAAAAAAAAAAAAAAAAAAAAAAAAAA4P/xUIAcf/whN1T9NsMOEK5rxxxxXnid+f0/Ia195vi6oGH1ZVr6kjqScdSF9lt3qXH+Lxf0fo/Oe53r99IUPzybv/YWGZ7Vgk31MGw+DMp05+3y9fPERUTHlt1c9sUyoqCaD5bdXVz2wkG0hnpDmFy8r0fr3VBn/C7Rmg+L0/45EWfdocGq3HQ1uRro0GJK+vsvo837NR82s01l/n97rsWn7RYNBM3WRcDY3cJKosqMJhgdHtj9yflthd65rxxxxXnid+f0/Ia195vi6oAAAAAAAAAAAAAAAAAAAAAAAAAAAABw" func TestPrepareContentImage(t *testing.T) { file, err := os.Open("../_assets/tests/test.jpg") @@ -29,7 +30,7 @@ func TestPrepareContentImage(t *testing.T) { message.Payload = &protobuf.ChatMessage_Image{Image: &image} require.NoError(t, message.PrepareContent()) - require.Equal(t, message.Base64Image, expectedJPEG) + require.Equal(t, expectedJPEG, message.Base64Image) } func TestGetImageMessageMIME(t *testing.T) { @@ -57,3 +58,39 @@ func TestGetImageMessageMIME(t *testing.T) { _, err = getImageMessageMIME(unknown) require.Error(t, err) } + +func TestPrepareContentAudio(t *testing.T) { + file, err := os.Open("../_assets/tests/test.aac") + require.NoError(t, err) + defer file.Close() + + payload, err := ioutil.ReadAll(file) + require.NoError(t, err) + + message := &Message{} + message.ContentType = protobuf.ChatMessage_AUDIO + audio := protobuf.AudioMessage{ + Payload: payload, + Type: protobuf.AudioMessage_AAC, + } + message.Payload = &protobuf.ChatMessage_Audio{Audio: &audio} + + require.NoError(t, message.PrepareContent()) + require.Equal(t, expectedAAC, message.Base64Audio) +} + +func TestGetAudioMessageMIME(t *testing.T) { + aac := &protobuf.AudioMessage{Type: protobuf.AudioMessage_AAC} + mime, err := getAudioMessageMIME(aac) + require.NoError(t, err) + require.Equal(t, "aac", mime) + + amr := &protobuf.AudioMessage{Type: protobuf.AudioMessage_AMR} + mime, err = getAudioMessageMIME(amr) + require.NoError(t, err) + require.Equal(t, "amr", mime) + + unknown := &protobuf.ImageMessage{Type: protobuf.ImageMessage_UNKNOWN_IMAGE_TYPE} + _, err = getImageMessageMIME(unknown) + require.Error(t, err) +} diff --git a/protocol/message_validator.go b/protocol/message_validator.go index 2891e9420..67b4a6a35 100644 --- a/protocol/message_validator.go +++ b/protocol/message_validator.go @@ -209,5 +209,22 @@ func ValidateReceivedChatMessage(message *protobuf.ChatMessage, whisperTimestamp } } + if message.ContentType == protobuf.ChatMessage_AUDIO { + if message.Payload == nil { + return errors.New("no audio content") + } + audio := message.GetAudio() + if audio == nil { + return errors.New("no audio content") + } + if len(audio.Payload) == 0 { + return errors.New("audio payload empty") + } + + if audio.Type == protobuf.AudioMessage_UNKNOWN_AUDIO_TYPE { + return errors.New("audio type unknown") + } + } + return nil } diff --git a/protocol/message_validator_test.go b/protocol/message_validator_test.go index 3a6d52374..c0f61985c 100644 --- a/protocol/message_validator_test.go +++ b/protocol/message_validator_test.go @@ -402,6 +402,68 @@ func (s *MessageValidatorSuite) TestValidatePlainTextMessage() { ContentType: protobuf.ChatMessage_IMAGE, }, }, + { + Name: "Valid audio message", + WhisperTimestamp: 2, + Valid: true, + Message: protobuf.ChatMessage{ + ChatId: "a", + Text: "valid", + Clock: 2, + Timestamp: 3, + ResponseTo: "", + EnsName: "", + Payload: &protobuf.ChatMessage_Audio{ + Audio: &protobuf.AudioMessage{ + Type: 1, + Payload: []byte("some-payload"), + }, + }, + MessageType: protobuf.ChatMessage_ONE_TO_ONE, + ContentType: protobuf.ChatMessage_AUDIO, + }, + }, + { + Name: "Invalid audio message, type unknown", + WhisperTimestamp: 2, + Valid: false, + Message: protobuf.ChatMessage{ + ChatId: "a", + Text: "valid", + Clock: 2, + Timestamp: 3, + ResponseTo: "", + EnsName: "", + Payload: &protobuf.ChatMessage_Audio{ + Audio: &protobuf.AudioMessage{ + Type: protobuf.AudioMessage_UNKNOWN_AUDIO_TYPE, + Payload: []byte("some-payload"), + }, + }, + MessageType: protobuf.ChatMessage_ONE_TO_ONE, + ContentType: protobuf.ChatMessage_STICKER, + }, + }, + { + Name: "Invalid audio message, missing payload", + WhisperTimestamp: 2, + Valid: false, + Message: protobuf.ChatMessage{ + ChatId: "a", + Text: "valid", + Clock: 2, + Timestamp: 3, + ResponseTo: "", + EnsName: "", + Payload: &protobuf.ChatMessage_Audio{ + Audio: &protobuf.AudioMessage{ + Type: 1, + }, + }, + MessageType: protobuf.ChatMessage_ONE_TO_ONE, + ContentType: protobuf.ChatMessage_AUDIO, + }, + }, } for _, tc := range testCases { diff --git a/protocol/messenger.go b/protocol/messenger.go index 1b1bb70d5..514ad7231 100644 --- a/protocol/messenger.go +++ b/protocol/messenger.go @@ -19,6 +19,7 @@ import ( "github.com/status-im/status-go/eth-node/crypto" "github.com/status-im/status-go/eth-node/types" enstypes "github.com/status-im/status-go/eth-node/types/ens" + "github.com/status-im/status-go/protocol/audio" "github.com/status-im/status-go/protocol/common" "github.com/status-im/status-go/protocol/encryption" "github.com/status-im/status-go/protocol/encryption/multidevice" @@ -1382,6 +1383,32 @@ func (m *Messenger) SendChatMessage(ctx context.Context, message *Message) (*Mes message.Payload = &protobuf.ChatMessage_Image{Image: &image} } + + if len(message.AudioPath) != 0 { + file, err := os.Open(message.AudioPath) + if err != nil { + return nil, err + } + defer file.Close() + + payload, err := ioutil.ReadAll(file) + if err != nil { + return nil, err + + } + audioMessage := message.GetAudio() + if audioMessage == nil { + return nil, errors.New("no audio has been passed") + } + audioMessage.Payload = payload + audioMessage.Type = audio.Type(payload) + message.Payload = &protobuf.ChatMessage_Audio{Audio: audioMessage} + err = os.Remove(message.AudioPath) + if err != nil { + return nil, err + } + } + logger := m.logger.With(zap.String("site", "Send"), zap.String("chatID", message.ChatId)) var response MessengerResponse @@ -1432,7 +1459,7 @@ func (m *Messenger) SendChatMessage(ctx context.Context, message *Message) (*Mes id, err := m.dispatchMessage(ctx, &common.RawMessage{ LocalChatID: chat.ID, - SendPushNotification: !chat.Public(), + SendPushNotification: m.featureFlags.PushNotifications && !chat.Public(), Payload: encodedMessage, MessageType: protobuf.ApplicationMetadataMessage_CHAT_MESSAGE, ResendAutomatically: true, diff --git a/protocol/messenger_config.go b/protocol/messenger_config.go index f404a11ae..b83f2c173 100644 --- a/protocol/messenger_config.go +++ b/protocol/messenger_config.go @@ -116,6 +116,13 @@ func WithDatasync() func(c *config) error { } } +func WithPushNotifications() func(c *config) error { + return func(c *config) error { + c.featureFlags.PushNotifications = true + return nil + } +} + func WithEnvelopesMonitorConfig(emc *transport.EnvelopesMonitorConfig) Option { return func(c *config) error { c.envelopesMonitorConfig = emc diff --git a/protocol/migrations/migrations.go b/protocol/migrations/migrations.go index 0831a664d..6ee4cc021 100644 --- a/protocol/migrations/migrations.go +++ b/protocol/migrations/migrations.go @@ -14,6 +14,8 @@ // 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) +// 1595862781_add_audio_data.down.sql (0) +// 1595862781_add_audio_data.up.sql (246B) // doc.go (850B) package migrations @@ -338,7 +340,7 @@ func _1593087212_add_mute_chat_and_raw_message_fieldsDownSql() (*asset, error) { return nil, err } - info := bindataFileInfo{name: "1593087212_add_mute_chat_and_raw_message_fields.down.sql", size: 0, mode: os.FileMode(0644), modTime: time.Unix(1595832279, 0)} + info := bindataFileInfo{name: "1593087212_add_mute_chat_and_raw_message_fields.down.sql", size: 0, mode: os.FileMode(0644), modTime: time.Unix(1595862768, 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 } @@ -358,11 +360,51 @@ func _1593087212_add_mute_chat_and_raw_message_fieldsUpSql() (*asset, error) { return nil, err } - info := bindataFileInfo{name: "1593087212_add_mute_chat_and_raw_message_fields.up.sql", size: 215, mode: os.FileMode(0644), modTime: time.Unix(1595832279, 0)} + info := bindataFileInfo{name: "1593087212_add_mute_chat_and_raw_message_fields.up.sql", size: 215, mode: os.FileMode(0644), modTime: time.Unix(1595862768, 0)} a := &asset{bytes: bytes, info: info, digest: [32]uint8{0x73, 0x99, 0x61, 0xd1, 0xaa, 0xb4, 0xbf, 0xaf, 0xd7, 0x20, 0x17, 0x40, 0xf9, 0x2, 0xfb, 0xcc, 0x40, 0x2a, 0xd, 0x86, 0x36, 0x30, 0x88, 0x89, 0x25, 0x80, 0x42, 0xb0, 0x5b, 0xe9, 0x73, 0x78}} return a, nil } +var __1595862781_add_audio_dataDownSql = []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 _1595862781_add_audio_dataDownSqlBytes() ([]byte, error) { + return bindataRead( + __1595862781_add_audio_dataDownSql, + "1595862781_add_audio_data.down.sql", + ) +} + +func _1595862781_add_audio_dataDownSql() (*asset, error) { + bytes, err := _1595862781_add_audio_dataDownSqlBytes() + if err != nil { + return nil, err + } + + info := bindataFileInfo{name: "1595862781_add_audio_data.down.sql", size: 0, mode: os.FileMode(0644), modTime: time.Unix(1595862768, 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 __1595862781_add_audio_dataUpSql = []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\x94\xcb\x41\xaa\xc3\x20\x10\x06\xe0\x7d\x4e\xf1\x93\x33\x3c\xde\x26\x2b\x53\x2d\x14\xa6\x0a\x65\x84\xee\x64\x8a\x52\x02\x4d\x0d\x99\xb8\xc8\xed\x7b\x06\x0f\xf0\x19\x62\xf7\x00\x9b\x99\x1c\x9a\x96\x3d\xad\x45\x55\xde\x45\x61\xac\xc5\x25\x50\xbc\x7b\x48\xcb\x4b\x4d\x9b\x9c\x9f\x2a\x19\x33\x85\x79\x1a\x3a\xe0\x71\x6e\x05\x37\xcf\x5d\x28\xb7\x5d\x8e\xa5\x7e\xd3\xaa\xdd\xf6\x25\x5a\xfe\xff\xc0\xee\xc9\xf0\x81\xe1\x23\x11\xac\xbb\x9a\x48\x8c\x71\x9c\x86\x5f\x00\x00\x00\xff\xff\xeb\x6f\xa0\x62\xf6\x00\x00\x00") + +func _1595862781_add_audio_dataUpSqlBytes() ([]byte, error) { + return bindataRead( + __1595862781_add_audio_dataUpSql, + "1595862781_add_audio_data.up.sql", + ) +} + +func _1595862781_add_audio_dataUpSql() (*asset, error) { + bytes, err := _1595862781_add_audio_dataUpSqlBytes() + if err != nil { + return nil, err + } + + info := bindataFileInfo{name: "1595862781_add_audio_data.up.sql", size: 246, mode: os.FileMode(0644), modTime: time.Unix(1595862893, 0)} + a := &asset{bytes: bytes, info: info, digest: [32]uint8{0xae, 0xd2, 0xee, 0x55, 0xfb, 0x36, 0xa4, 0x92, 0x66, 0xe, 0x81, 0x62, 0x1e, 0x7a, 0x69, 0xa, 0xd5, 0x4b, 0xa5, 0x6a, 0x8d, 0x1d, 0xce, 0xf3, 0x3e, 0xc0, 0x5f, 0x9c, 0x66, 0x1b, 0xb4, 0xed}} + return a, nil +} + var _docGo = []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\x84\x52\x3f\x8f\xdb\x3e\x0c\xdd\xf3\x29\x1e\x6e\xb9\xe5\x22\x07\xf8\xfd\xa6\xdb\x3a\x74\xe8\xd2\x2e\xd9\x0b\x46\xa6\x6d\x22\x32\xe5\x8a\xf4\x39\xf9\xf6\x85\x74\x17\x9c\x51\x14\xe8\x4a\x89\x8f\xef\x5f\xd7\xe1\x3c\x89\x61\x90\xc4\x10\x83\x72\x64\x33\x2a\x77\x5c\x38\xd2\x6a\x8c\xa7\x51\x7c\x5a\x2f\x21\xe6\xb9\x33\x27\x5f\xed\x28\x73\x37\xcb\x58\xc8\xb9\x7b\xfb\xff\xe9\xd0\x75\x88\xa4\xcf\x8e\x89\xb4\x4f\xdc\xb0\x0c\xe6\x54\x5c\x74\xc4\x26\x3e\x81\xb0\x14\x1e\xe4\x16\xf0\xc5\x91\x98\xcc\xe1\x13\xf9\xb3\xc1\x27\x46\x24\xe3\x0a\x33\xe4\x82\x31\x1f\x2f\xa2\x3d\x39\x85\x3a\xfa\x36\xec\x26\x95\x61\xa4\x94\xb8\xc7\x50\xf2\xdc\x76\x8d\x66\x46\x2f\x85\xa3\xe7\x72\x7f\x01\x99\xb1\x43\x69\x66\xab\xfb\x13\xbd\x31\x34\x7f\x9c\x07\x69\xff\x6f\x45\xd8\x72\xb9\x1a\xc8\xc0\xb7\x85\xa3\x73\x1f\x0e\x15\xeb\xfb\x8f\xf3\xd7\x57\x9c\x27\xae\xf0\x55\x5a\x1e\x1a\x85\x66\x9e\x32\xf7\x06\xcf\x18\x72\x4a\x79\x6b\x0f\xab\xca\x0d\x2e\x33\x9b\xd3\xbc\x20\x66\x7d\x63\x75\xc9\x5a\xd1\x56\x4d\x72\xe5\xf6\xcf\xb7\x0c\x51\x71\xa1\xf4\xee\x5e\x93\x7e\x7e\x37\xe8\x11\x44\x5c\x4b\x61\xf5\x74\x6f\x2b\xac\xb1\xdc\x97\x8a\x85\x77\xe6\x92\xd5\x9a\xbc\xa5\x64\xcf\x31\xa7\xdd\xbc\xa2\xd9\x44\x85\x3f\x1d\x73\xba\x24\x7e\xc1\x36\x49\x9c\x30\x33\xa9\xb5\x40\xda\x87\x44\xce\xe6\x9f\xfb\x10\x85\x73\x99\xad\x0a\xae\xfc\xaa\xbb\x15\xb3\x16\xe7\x91\xc3\x8e\x50\x33\x7f\xa1\xf8\x51\x85\xc7\x95\xd5\xd8\x40\x7f\x98\xf2\x08\x79\x63\x50\xdf\xe3\x74\x3a\x9d\xfe\xfb\x19\x42\x68\x5d\xe0\x1b\xcd\x4b\xa5\xe9\xb5\xa3\x9b\xa4\x84\x0b\x43\x46\xcd\x85\xfb\xca\x8a\x6f\x62\xad\x64\x31\x09\xab\xd7\xcc\x2a\x5e\x4e\x3d\x97\xaa\x47\xf7\x7a\xfe\x66\x59\x38\x1c\x16\x8a\x57\x1a\x19\xf6\x2b\x89\x73\x0d\x7a\xcc\xaf\x23\x2b\xd7\x3a\xec\xcb\x77\x5c\xae\xe3\xde\xec\x63\x46\x08\xdd\xe7\x20\x8c\x19\xe1\xf0\x3b\x00\x00\xff\xff\x12\xcd\x7f\xc4\x52\x03\x00\x00") func docGoBytes() ([]byte, error) { @@ -502,6 +544,10 @@ 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, + "1595862781_add_audio_data.down.sql": _1595862781_add_audio_dataDownSql, + + "1595862781_add_audio_data.up.sql": _1595862781_add_audio_dataUpSql, + "doc.go": docGo, } @@ -560,7 +606,9 @@ 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{}}, - "doc.go": &bintree{docGo, 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{}}, + "doc.go": &bintree{docGo, map[string]*bintree{}}, }} // RestoreAsset restores an asset under the given directory. diff --git a/protocol/migrations/sqlite/1595862781_add_audio_data.down.sql b/protocol/migrations/sqlite/1595862781_add_audio_data.down.sql new file mode 100644 index 000000000..e69de29bb diff --git a/protocol/migrations/sqlite/1595862781_add_audio_data.up.sql b/protocol/migrations/sqlite/1595862781_add_audio_data.up.sql new file mode 100644 index 000000000..e984a834d --- /dev/null +++ b/protocol/migrations/sqlite/1595862781_add_audio_data.up.sql @@ -0,0 +1,4 @@ +ALTER TABLE user_messages ADD COLUMN audio_payload BLOB; +ALTER TABLE user_messages ADD COLUMN audio_type INT; +ALTER TABLE user_messages ADD COLUMN audio_duration_ms INT; +ALTER TABLE user_messages ADD COLUMN audio_base64 TEXT NOT NULL DEFAULT ""; diff --git a/protocol/persistence.go b/protocol/persistence.go index 7ed18fd96..bb5ad5b33 100644 --- a/protocol/persistence.go +++ b/protocol/persistence.go @@ -32,6 +32,10 @@ func (db sqlitePersistence) SaveChat(chat Chat) error { func (db sqlitePersistence) SaveChats(chats []*Chat) error { tx, err := db.db.BeginTx(context.Background(), &sql.TxOptions{}) + if err != nil { + return err + } + defer func() { if err == nil { err = tx.Commit() @@ -52,6 +56,10 @@ func (db sqlitePersistence) SaveChats(chats []*Chat) error { func (db sqlitePersistence) SaveContacts(contacts []*Contact) error { tx, err := db.db.BeginTx(context.Background(), &sql.TxOptions{}) + if err != nil { + return err + } + defer func() { if err == nil { err = tx.Commit() diff --git a/protocol/protobuf/chat_message.pb.go b/protocol/protobuf/chat_message.pb.go index 6a34afcc7..4fd386673 100644 --- a/protocol/protobuf/chat_message.pb.go +++ b/protocol/protobuf/chat_message.pb.go @@ -54,6 +54,34 @@ func (ImageMessage_ImageType) EnumDescriptor() ([]byte, []int) { return fileDescriptor_263952f55fd35689, []int{1, 0} } +type AudioMessage_AudioType int32 + +const ( + AudioMessage_UNKNOWN_AUDIO_TYPE AudioMessage_AudioType = 0 + AudioMessage_AAC AudioMessage_AudioType = 1 + AudioMessage_AMR AudioMessage_AudioType = 2 +) + +var AudioMessage_AudioType_name = map[int32]string{ + 0: "UNKNOWN_AUDIO_TYPE", + 1: "AAC", + 2: "AMR", +} + +var AudioMessage_AudioType_value = map[string]int32{ + "UNKNOWN_AUDIO_TYPE": 0, + "AAC": 1, + "AMR": 2, +} + +func (x AudioMessage_AudioType) String() string { + return proto.EnumName(AudioMessage_AudioType_name, int32(x)) +} + +func (AudioMessage_AudioType) EnumDescriptor() ([]byte, []int) { + return fileDescriptor_263952f55fd35689, []int{2, 0} +} + type ChatMessage_MessageType int32 const ( @@ -86,7 +114,7 @@ func (x ChatMessage_MessageType) String() string { } func (ChatMessage_MessageType) EnumDescriptor() ([]byte, []int) { - return fileDescriptor_263952f55fd35689, []int{2, 0} + return fileDescriptor_263952f55fd35689, []int{3, 0} } type ChatMessage_ContentType int32 @@ -101,6 +129,7 @@ const ( // Only local ChatMessage_SYSTEM_MESSAGE_CONTENT_PRIVATE_GROUP ChatMessage_ContentType = 6 ChatMessage_IMAGE ChatMessage_ContentType = 7 + ChatMessage_AUDIO ChatMessage_ContentType = 8 ) var ChatMessage_ContentType_name = map[int32]string{ @@ -112,6 +141,7 @@ var ChatMessage_ContentType_name = map[int32]string{ 5: "TRANSACTION_COMMAND", 6: "SYSTEM_MESSAGE_CONTENT_PRIVATE_GROUP", 7: "IMAGE", + 8: "AUDIO", } var ChatMessage_ContentType_value = map[string]int32{ @@ -123,6 +153,7 @@ var ChatMessage_ContentType_value = map[string]int32{ "TRANSACTION_COMMAND": 5, "SYSTEM_MESSAGE_CONTENT_PRIVATE_GROUP": 6, "IMAGE": 7, + "AUDIO": 8, } func (x ChatMessage_ContentType) String() string { @@ -130,7 +161,7 @@ func (x ChatMessage_ContentType) String() string { } func (ChatMessage_ContentType) EnumDescriptor() ([]byte, []int) { - return fileDescriptor_263952f55fd35689, []int{2, 1} + return fileDescriptor_263952f55fd35689, []int{3, 1} } type StickerMessage struct { @@ -227,6 +258,61 @@ func (m *ImageMessage) GetType() ImageMessage_ImageType { return ImageMessage_UNKNOWN_IMAGE_TYPE } +type AudioMessage struct { + Payload []byte `protobuf:"bytes,1,opt,name=payload,proto3" json:"payload,omitempty"` + Type AudioMessage_AudioType `protobuf:"varint,2,opt,name=type,proto3,enum=protobuf.AudioMessage_AudioType" json:"type,omitempty"` + DurationMs uint64 `protobuf:"varint,3,opt,name=duration_ms,json=durationMs,proto3" json:"duration_ms,omitempty"` + XXX_NoUnkeyedLiteral struct{} `json:"-"` + XXX_unrecognized []byte `json:"-"` + XXX_sizecache int32 `json:"-"` +} + +func (m *AudioMessage) Reset() { *m = AudioMessage{} } +func (m *AudioMessage) String() string { return proto.CompactTextString(m) } +func (*AudioMessage) ProtoMessage() {} +func (*AudioMessage) Descriptor() ([]byte, []int) { + return fileDescriptor_263952f55fd35689, []int{2} +} + +func (m *AudioMessage) XXX_Unmarshal(b []byte) error { + return xxx_messageInfo_AudioMessage.Unmarshal(m, b) +} +func (m *AudioMessage) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + return xxx_messageInfo_AudioMessage.Marshal(b, m, deterministic) +} +func (m *AudioMessage) XXX_Merge(src proto.Message) { + xxx_messageInfo_AudioMessage.Merge(m, src) +} +func (m *AudioMessage) XXX_Size() int { + return xxx_messageInfo_AudioMessage.Size(m) +} +func (m *AudioMessage) XXX_DiscardUnknown() { + xxx_messageInfo_AudioMessage.DiscardUnknown(m) +} + +var xxx_messageInfo_AudioMessage proto.InternalMessageInfo + +func (m *AudioMessage) GetPayload() []byte { + if m != nil { + return m.Payload + } + return nil +} + +func (m *AudioMessage) GetType() AudioMessage_AudioType { + if m != nil { + return m.Type + } + return AudioMessage_UNKNOWN_AUDIO_TYPE +} + +func (m *AudioMessage) GetDurationMs() uint64 { + if m != nil { + return m.DurationMs + } + return 0 +} + type ChatMessage struct { // Lamport timestamp of the chat message Clock uint64 `protobuf:"varint,1,opt,name=clock,proto3" json:"clock,omitempty"` @@ -251,6 +337,7 @@ type ChatMessage struct { // Types that are valid to be assigned to Payload: // *ChatMessage_Sticker // *ChatMessage_Image + // *ChatMessage_Audio Payload isChatMessage_Payload `protobuf_oneof:"payload"` XXX_NoUnkeyedLiteral struct{} `json:"-"` XXX_unrecognized []byte `json:"-"` @@ -261,7 +348,7 @@ func (m *ChatMessage) Reset() { *m = ChatMessage{} } func (m *ChatMessage) String() string { return proto.CompactTextString(m) } func (*ChatMessage) ProtoMessage() {} func (*ChatMessage) Descriptor() ([]byte, []int) { - return fileDescriptor_263952f55fd35689, []int{2} + return fileDescriptor_263952f55fd35689, []int{3} } func (m *ChatMessage) XXX_Unmarshal(b []byte) error { @@ -350,10 +437,16 @@ type ChatMessage_Image struct { Image *ImageMessage `protobuf:"bytes,10,opt,name=image,proto3,oneof"` } +type ChatMessage_Audio struct { + Audio *AudioMessage `protobuf:"bytes,11,opt,name=audio,proto3,oneof"` +} + func (*ChatMessage_Sticker) isChatMessage_Payload() {} func (*ChatMessage_Image) isChatMessage_Payload() {} +func (*ChatMessage_Audio) isChatMessage_Payload() {} + func (m *ChatMessage) GetPayload() isChatMessage_Payload { if m != nil { return m.Payload @@ -375,61 +468,76 @@ func (m *ChatMessage) GetImage() *ImageMessage { return nil } +func (m *ChatMessage) GetAudio() *AudioMessage { + if x, ok := m.GetPayload().(*ChatMessage_Audio); ok { + return x.Audio + } + return nil +} + // XXX_OneofWrappers is for the internal use of the proto package. func (*ChatMessage) XXX_OneofWrappers() []interface{} { return []interface{}{ (*ChatMessage_Sticker)(nil), (*ChatMessage_Image)(nil), + (*ChatMessage_Audio)(nil), } } func init() { proto.RegisterEnum("protobuf.ImageMessage_ImageType", ImageMessage_ImageType_name, ImageMessage_ImageType_value) + proto.RegisterEnum("protobuf.AudioMessage_AudioType", AudioMessage_AudioType_name, AudioMessage_AudioType_value) proto.RegisterEnum("protobuf.ChatMessage_MessageType", ChatMessage_MessageType_name, ChatMessage_MessageType_value) proto.RegisterEnum("protobuf.ChatMessage_ContentType", ChatMessage_ContentType_name, ChatMessage_ContentType_value) proto.RegisterType((*StickerMessage)(nil), "protobuf.StickerMessage") proto.RegisterType((*ImageMessage)(nil), "protobuf.ImageMessage") + proto.RegisterType((*AudioMessage)(nil), "protobuf.AudioMessage") proto.RegisterType((*ChatMessage)(nil), "protobuf.ChatMessage") } func init() { proto.RegisterFile("chat_message.proto", fileDescriptor_263952f55fd35689) } var fileDescriptor_263952f55fd35689 = []byte{ - // 569 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x7c, 0x53, 0xcd, 0x4e, 0xdb, 0x40, - 0x10, 0xc6, 0x89, 0x1d, 0x27, 0xe3, 0x14, 0x6d, 0xa7, 0x08, 0x5c, 0x09, 0xa9, 0x69, 0xd4, 0x43, - 0x4e, 0x39, 0x50, 0x0e, 0xbd, 0x9a, 0xb0, 0x0d, 0x06, 0xfc, 0xa3, 0xf5, 0xa6, 0x94, 0x93, 0x65, - 0xcc, 0x96, 0x44, 0xe0, 0xd8, 0xc2, 0x5b, 0xa9, 0x5c, 0xfa, 0x3e, 0x7d, 0x9e, 0xbe, 0x50, 0xe5, - 0x35, 0x26, 0x4e, 0x55, 0xf5, 0xb4, 0xf3, 0xfb, 0xed, 0xb7, 0xdf, 0xcc, 0x02, 0xa6, 0xcb, 0x44, - 0xc6, 0x99, 0x28, 0xcb, 0xe4, 0x4e, 0x4c, 0x8b, 0xc7, 0x5c, 0xe6, 0xd8, 0x57, 0xc7, 0xcd, 0xf7, - 0x6f, 0xe3, 0x4f, 0xb0, 0x1b, 0xc9, 0x55, 0x7a, 0x2f, 0x1e, 0xbd, 0xba, 0x02, 0x11, 0xf4, 0x65, - 0x52, 0x2e, 0x6d, 0x6d, 0xa4, 0x4d, 0x06, 0x4c, 0xd9, 0x55, 0xac, 0x48, 0xd2, 0x7b, 0xbb, 0x33, - 0xd2, 0x26, 0x06, 0x53, 0xf6, 0xf8, 0x97, 0x06, 0x43, 0x37, 0x4b, 0xee, 0x44, 0xd3, 0x68, 0x83, - 0x59, 0x24, 0x4f, 0x0f, 0x79, 0x72, 0xab, 0x7a, 0x87, 0xac, 0x71, 0xf1, 0x18, 0x74, 0xf9, 0x54, - 0x08, 0xd5, 0xbe, 0x7b, 0x34, 0x9a, 0x36, 0xb7, 0x4f, 0xdb, 0xfd, 0xb5, 0xc3, 0x9f, 0x0a, 0xc1, - 0x54, 0xf5, 0xd8, 0x85, 0xc1, 0x4b, 0x08, 0xf7, 0x01, 0x17, 0xfe, 0x85, 0x1f, 0x5c, 0xf9, 0xb1, - 0xeb, 0x39, 0x73, 0x1a, 0xf3, 0xeb, 0x90, 0x92, 0x1d, 0x34, 0xa1, 0x1b, 0xfa, 0x73, 0xa2, 0x61, - 0x1f, 0xf4, 0xf3, 0x90, 0xce, 0x49, 0xa7, 0xb2, 0xae, 0xe8, 0x49, 0x48, 0xba, 0x55, 0x72, 0xee, - 0x7e, 0x26, 0xfa, 0xf8, 0xb7, 0x01, 0xd6, 0x6c, 0x99, 0xc8, 0x86, 0xea, 0x1e, 0x18, 0xe9, 0x43, - 0x9e, 0xde, 0x2b, 0xa2, 0x3a, 0xab, 0x1d, 0x3c, 0x84, 0x81, 0x5c, 0x65, 0xa2, 0x94, 0x49, 0x56, - 0x28, 0xae, 0x3a, 0xdb, 0x04, 0x2a, 0x0d, 0xa4, 0xf8, 0x21, 0xed, 0x6e, 0xad, 0x4b, 0x65, 0xe3, - 0x3b, 0xb0, 0x1e, 0x45, 0x59, 0xe4, 0xeb, 0x52, 0xc4, 0x32, 0xb7, 0x75, 0x95, 0x82, 0x26, 0xc4, - 0x73, 0x7c, 0x0b, 0x7d, 0xb1, 0x2e, 0xe3, 0x75, 0x92, 0x09, 0xdb, 0x50, 0x59, 0x53, 0xac, 0x4b, - 0x3f, 0xc9, 0x04, 0x1e, 0x80, 0xa9, 0x26, 0xb3, 0xba, 0xb5, 0x7b, 0x2a, 0xd3, 0xab, 0x5c, 0xf7, - 0x16, 0x4f, 0x61, 0xf8, 0x3c, 0xad, 0x58, 0xa9, 0x66, 0x2a, 0xd5, 0xde, 0x6f, 0x54, 0x6b, 0xbd, - 0x64, 0xfa, 0x7c, 0x2a, 0xd9, 0xac, 0x6c, 0xe3, 0x54, 0x28, 0x69, 0xbe, 0x96, 0x62, 0x2d, 0x6b, - 0x94, 0xfe, 0xff, 0x50, 0x66, 0x75, 0x65, 0x8d, 0x92, 0x6e, 0x1c, 0x3c, 0x06, 0xb3, 0xac, 0xd7, - 0xc3, 0x1e, 0x8c, 0xb4, 0x89, 0x75, 0x64, 0x6f, 0x00, 0xb6, 0xf7, 0xe6, 0x6c, 0x87, 0x35, 0xa5, - 0x38, 0x05, 0x63, 0x55, 0x4d, 0xce, 0x06, 0xd5, 0xb3, 0xff, 0xef, 0x81, 0x9f, 0xed, 0xb0, 0xba, - 0x6c, 0xfc, 0x13, 0xac, 0xd6, 0x3b, 0xd0, 0x86, 0xbd, 0x66, 0xd6, 0x1e, 0x8d, 0xa2, 0xd6, 0xb4, - 0x77, 0x01, 0x02, 0x9f, 0xc6, 0x3c, 0x88, 0x03, 0x9f, 0x12, 0x0d, 0x09, 0x0c, 0xc3, 0xc5, 0xc9, - 0xa5, 0x3b, 0x8b, 0xe7, 0x2c, 0x58, 0x84, 0xa4, 0x83, 0xaf, 0xe1, 0x55, 0xc8, 0xdc, 0x2f, 0x0e, - 0xa7, 0xcf, 0xa1, 0x2e, 0x8e, 0xe0, 0x30, 0xba, 0x8e, 0x38, 0xf5, 0x5e, 0xd0, 0xb6, 0x2b, 0xf4, - 0x6a, 0x95, 0xad, 0x96, 0x04, 0x6d, 0x02, 0xb3, 0xc0, 0xe7, 0xd4, 0xe7, 0x2d, 0x02, 0x9c, 0x7e, - 0xe5, 0x71, 0x78, 0xe9, 0xb8, 0x3e, 0xd1, 0xd0, 0x02, 0x33, 0xe2, 0xee, 0xec, 0x82, 0x32, 0xd2, - 0x41, 0x80, 0x5e, 0xc4, 0x1d, 0xbe, 0x88, 0x48, 0x17, 0x07, 0x60, 0x50, 0x2f, 0x38, 0x77, 0x89, - 0x8e, 0x07, 0xf0, 0x86, 0x33, 0xc7, 0x8f, 0x9c, 0x19, 0x77, 0x83, 0x0a, 0xd1, 0xf3, 0x1c, 0xff, - 0x94, 0x18, 0x38, 0x81, 0x0f, 0x7f, 0x11, 0x6b, 0x6e, 0xdb, 0x26, 0xd8, 0xab, 0xd0, 0xd4, 0xd6, - 0x13, 0xf3, 0x64, 0xf0, 0xf2, 0xcb, 0x6e, 0x7a, 0x4a, 0xd6, 0x8f, 0x7f, 0x02, 0x00, 0x00, 0xff, - 0xff, 0x1f, 0xf2, 0x87, 0xb6, 0xe2, 0x03, 0x00, 0x00, + // 652 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xa4, 0x53, 0x4d, 0x6f, 0xd3, 0x40, + 0x10, 0xad, 0x13, 0x27, 0x8e, 0xc7, 0xa1, 0x5a, 0x96, 0xaa, 0x35, 0x52, 0x25, 0x82, 0xc5, 0x21, + 0xa7, 0x1c, 0x4a, 0x91, 0xb8, 0xba, 0xae, 0x49, 0xdd, 0xd6, 0x1f, 0x5a, 0x6f, 0x28, 0x3d, 0x59, + 0xae, 0xb3, 0x34, 0x51, 0xeb, 0x0f, 0xc5, 0xae, 0x44, 0x2f, 0xfc, 0x04, 0xfe, 0x07, 0x77, 0xc4, + 0xef, 0x43, 0xbb, 0xae, 0x13, 0xa7, 0x42, 0x5c, 0x38, 0x79, 0x66, 0xf6, 0xcd, 0xf3, 0x9b, 0xd9, + 0xb7, 0x80, 0x93, 0x45, 0x5c, 0x45, 0x29, 0x2b, 0xcb, 0xf8, 0x96, 0x4d, 0x8a, 0x55, 0x5e, 0xe5, + 0x78, 0x20, 0x3e, 0x37, 0x0f, 0x5f, 0x8d, 0x8f, 0xb0, 0x1b, 0x56, 0xcb, 0xe4, 0x8e, 0xad, 0xdc, + 0x1a, 0x81, 0x31, 0xc8, 0x8b, 0xb8, 0x5c, 0xe8, 0xd2, 0x48, 0x1a, 0xab, 0x44, 0xc4, 0xbc, 0x56, + 0xc4, 0xc9, 0x9d, 0xde, 0x19, 0x49, 0xe3, 0x1e, 0x11, 0xb1, 0xf1, 0x53, 0x82, 0xa1, 0x93, 0xc6, + 0xb7, 0xac, 0x69, 0xd4, 0x41, 0x29, 0xe2, 0xc7, 0xfb, 0x3c, 0x9e, 0x8b, 0xde, 0x21, 0x69, 0x52, + 0x7c, 0x0c, 0x72, 0xf5, 0x58, 0x30, 0xd1, 0xbe, 0x7b, 0x34, 0x9a, 0x34, 0x7f, 0x9f, 0xb4, 0xfb, + 0xeb, 0x84, 0x3e, 0x16, 0x8c, 0x08, 0xb4, 0xe1, 0x80, 0xba, 0x2e, 0xe1, 0x7d, 0xc0, 0x33, 0xef, + 0xc2, 0xf3, 0xaf, 0xbc, 0xc8, 0x71, 0xcd, 0xa9, 0x1d, 0xd1, 0xeb, 0xc0, 0x46, 0x3b, 0x58, 0x81, + 0x6e, 0xe0, 0x4d, 0x91, 0x84, 0x07, 0x20, 0x9f, 0x07, 0xf6, 0x14, 0x75, 0x78, 0x74, 0x65, 0x9f, + 0x04, 0xa8, 0xcb, 0x0f, 0xa7, 0xce, 0x27, 0x24, 0x1b, 0xbf, 0x25, 0x18, 0x9a, 0x0f, 0xf3, 0x65, + 0xfe, 0x1f, 0x5a, 0xdb, 0xfd, 0x75, 0xb2, 0xd1, 0x8a, 0xdf, 0x80, 0x36, 0x7f, 0x58, 0xc5, 0xd5, + 0x32, 0xcf, 0xa2, 0xb4, 0xd4, 0xbb, 0x23, 0x69, 0x2c, 0x13, 0x68, 0x4a, 0x6e, 0x69, 0x7c, 0x00, + 0x75, 0xdd, 0xd3, 0x1e, 0xc6, 0x9c, 0x9d, 0x3a, 0x7e, 0x6b, 0x18, 0xd3, 0xb4, 0x90, 0x24, 0x02, + 0x97, 0xa0, 0x8e, 0xf1, 0xa3, 0x0f, 0x9a, 0xb5, 0x88, 0xab, 0x46, 0xf7, 0x1e, 0xf4, 0x92, 0xfb, + 0x3c, 0xb9, 0x13, 0xaa, 0x65, 0x52, 0x27, 0xf8, 0x10, 0xd4, 0x6a, 0x99, 0xb2, 0xb2, 0x8a, 0xd3, + 0x42, 0x08, 0x97, 0xc9, 0xa6, 0xc0, 0x2f, 0xaf, 0x62, 0xdf, 0x2a, 0x21, 0x4a, 0x25, 0x22, 0xe6, + 0x7a, 0x57, 0xac, 0x2c, 0xf2, 0xac, 0x64, 0x51, 0x95, 0xeb, 0xb2, 0x38, 0x82, 0xa6, 0x44, 0x73, + 0xfc, 0x1a, 0x06, 0x2c, 0x2b, 0xa3, 0x2c, 0x4e, 0x99, 0xde, 0x13, 0xa7, 0x0a, 0xcb, 0x4a, 0x2f, + 0x4e, 0x19, 0x3e, 0x00, 0x45, 0x58, 0x6a, 0x39, 0xd7, 0xfb, 0xe2, 0xa4, 0xcf, 0x53, 0x67, 0x8e, + 0x4f, 0x61, 0xf8, 0x64, 0xb3, 0x48, 0xac, 0x50, 0x11, 0x2b, 0x7c, 0xbb, 0x59, 0x61, 0x6b, 0x92, + 0xc9, 0xd3, 0x57, 0xec, 0x50, 0x4b, 0x37, 0x09, 0x67, 0x49, 0xf2, 0xac, 0x62, 0x59, 0x55, 0xb3, + 0x0c, 0xfe, 0xc5, 0x62, 0xd5, 0xc8, 0x9a, 0x25, 0xd9, 0x24, 0xf8, 0x18, 0x94, 0xb2, 0xf6, 0xb5, + 0xae, 0x8e, 0xa4, 0xb1, 0x76, 0xa4, 0x6f, 0x08, 0xb6, 0x0d, 0x7f, 0xb6, 0x43, 0x1a, 0x28, 0x9e, + 0x40, 0x6f, 0xc9, 0x2d, 0xa7, 0x83, 0xe8, 0xd9, 0xff, 0xbb, 0x53, 0xcf, 0x76, 0x48, 0x0d, 0xe3, + 0xf8, 0x98, 0xdf, 0xaa, 0xae, 0x3d, 0xc7, 0xb7, 0xdd, 0xc2, 0xf1, 0x02, 0x66, 0x7c, 0x07, 0xad, + 0x35, 0x37, 0xd6, 0x61, 0xaf, 0xf1, 0x81, 0x6b, 0x87, 0x61, 0xcb, 0xd6, 0xbb, 0x00, 0xbe, 0x67, + 0x47, 0xd4, 0x8f, 0x7c, 0xcf, 0x46, 0x12, 0x46, 0x30, 0x0c, 0x66, 0x27, 0x97, 0x8e, 0x15, 0x4d, + 0x89, 0x3f, 0x0b, 0x50, 0x07, 0xbf, 0x84, 0x17, 0x01, 0x71, 0x3e, 0x9b, 0xd4, 0x7e, 0x2a, 0x75, + 0xf1, 0x08, 0x0e, 0xc3, 0xeb, 0x90, 0xda, 0xee, 0x9a, 0x6d, 0x1b, 0x21, 0x1b, 0xbf, 0x24, 0xd0, + 0x5a, 0x2b, 0x6b, 0x0b, 0xb0, 0x7c, 0x8f, 0xda, 0x1e, 0x6d, 0x09, 0xa0, 0xf6, 0x17, 0x1a, 0x05, + 0x97, 0xa6, 0xe3, 0x21, 0x09, 0x6b, 0xa0, 0x84, 0xd4, 0xb1, 0x2e, 0x6c, 0x82, 0x3a, 0x18, 0xa0, + 0x1f, 0x52, 0x93, 0xce, 0x42, 0xd4, 0xc5, 0x2a, 0xf4, 0x6c, 0xd7, 0x3f, 0x77, 0x90, 0x8c, 0x0f, + 0xe0, 0x15, 0x25, 0xa6, 0x17, 0x9a, 0x16, 0x75, 0x7c, 0xce, 0xe8, 0xba, 0xa6, 0x77, 0x8a, 0x7a, + 0x78, 0x0c, 0xef, 0x9e, 0x09, 0x6b, 0xfe, 0xb6, 0x2d, 0xb0, 0xcf, 0xd9, 0xc4, 0xf3, 0x46, 0x0a, + 0x0f, 0xc5, 0xe3, 0x40, 0x83, 0x13, 0x75, 0xfd, 0x5a, 0x6f, 0xfa, 0x62, 0xc3, 0xef, 0xff, 0x04, + 0x00, 0x00, 0xff, 0xff, 0x5b, 0xc2, 0xb0, 0xfc, 0xd6, 0x04, 0x00, 0x00, } diff --git a/protocol/protobuf/chat_message.proto b/protocol/protobuf/chat_message.proto index 8bc45a1d0..cfc9eee8a 100644 --- a/protocol/protobuf/chat_message.proto +++ b/protocol/protobuf/chat_message.proto @@ -19,6 +19,17 @@ message ImageMessage { } } +message AudioMessage { + bytes payload = 1; + AudioType type = 2; + uint64 duration_ms = 3; + enum AudioType { + UNKNOWN_AUDIO_TYPE = 0; + AAC = 1; + AMR = 2; + } +} + message ChatMessage { // Lamport timestamp of the chat message uint64 clock = 1; @@ -45,6 +56,7 @@ message ChatMessage { oneof payload { StickerMessage sticker = 9; ImageMessage image = 10; + AudioMessage audio = 11; } enum MessageType { @@ -64,5 +76,6 @@ message ChatMessage { // Only local SYSTEM_MESSAGE_CONTENT_PRIVATE_GROUP = 6; IMAGE = 7; + AUDIO = 8; } } diff --git a/protocol/push_notification_test.go b/protocol/push_notification_test.go index 35e950016..aeda40dbc 100644 --- a/protocol/push_notification_test.go +++ b/protocol/push_notification_test.go @@ -88,6 +88,7 @@ func (s *MessengerPushNotificationSuite) newMessengerWithKey(shh types.Waku, pri WithMessagesPersistenceEnabled(), WithDatabaseConfig(tmpFile.Name(), ""), WithDatasync(), + WithPushNotifications(), } return s.newMessengerWithOptions(shh, privateKey, options) }