Add audio messages
Why make this change? We are adding support of audio recorded files, similarly to how we did with images What has changed? - Added protobuf definition, only AAC supported - Added migrations to store files - Fixed an issue with nil pointer when transaction would fail to be created, causing the application to crash
This commit is contained in:
parent
717ed3e1cf
commit
e58ba1e9c8
Binary file not shown.
|
@ -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
|
||||
}
|
||||
}
|
|
@ -22,6 +22,8 @@ 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"`
|
||||
}
|
||||
|
||||
type CommandState int
|
||||
|
@ -102,6 +104,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 +140,7 @@ func (m *Message) MarshalJSON() ([]byte, error) {
|
|||
ResponseTo string `json:"responseTo"`
|
||||
EnsName string `json:"ensName"`
|
||||
Image string `json:"image,omitempty"`
|
||||
Audio string `json:"audio,omitempty"`
|
||||
Sticker *StickerAlias `json:"sticker"`
|
||||
CommandParameters *CommandParameters `json:"commandParameters"`
|
||||
Timestamp uint64 `json:"timestamp"`
|
||||
|
@ -159,6 +166,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,
|
||||
|
@ -239,6 +247,37 @@ func (m *Message) parseImage() error {
|
|||
return nil
|
||||
}
|
||||
|
||||
// parseAudio check the message contains an audio, and if so
|
||||
// it creates the 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 +289,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 +308,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")
|
||||
}
|
||||
|
|
|
@ -36,6 +36,9 @@ func (db sqlitePersistence) tableUserMessagesAllFields() string {
|
|||
image_payload,
|
||||
image_type,
|
||||
image_base64,
|
||||
audio_payload,
|
||||
audio_type,
|
||||
audio_base64,
|
||||
command_id,
|
||||
command_value,
|
||||
command_from,
|
||||
|
@ -68,6 +71,7 @@ func (db sqlitePersistence) tableUserMessagesAllFieldsJoin() string {
|
|||
m1.sticker_pack,
|
||||
m1.sticker_hash,
|
||||
m1.image_base64,
|
||||
m1.audio_base64,
|
||||
m1.command_id,
|
||||
m1.command_value,
|
||||
m1.command_from,
|
||||
|
@ -83,6 +87,7 @@ func (db sqlitePersistence) tableUserMessagesAllFieldsJoin() string {
|
|||
m2.source,
|
||||
m2.text,
|
||||
m2.image_base64,
|
||||
m2.audio_base64,
|
||||
c.alias,
|
||||
c.identicon`
|
||||
}
|
||||
|
@ -99,6 +104,7 @@ func (db sqlitePersistence) tableUserMessagesScanAllFields(row scanner, message
|
|||
var quotedText sql.NullString
|
||||
var quotedFrom sql.NullString
|
||||
var quotedImage sql.NullString
|
||||
var quotedAudio sql.NullString
|
||||
var alias sql.NullString
|
||||
var identicon sql.NullString
|
||||
|
||||
|
@ -123,6 +129,7 @@ func (db sqlitePersistence) tableUserMessagesScanAllFields(row scanner, message
|
|||
&sticker.Pack,
|
||||
&sticker.Hash,
|
||||
&message.Base64Image,
|
||||
&message.Base64Audio,
|
||||
&command.ID,
|
||||
&command.Value,
|
||||
&command.From,
|
||||
|
@ -138,6 +145,7 @@ func (db sqlitePersistence) tableUserMessagesScanAllFields(row scanner, message
|
|||
"edFrom,
|
||||
"edText,
|
||||
"edImage,
|
||||
"edAudio,
|
||||
&alias,
|
||||
&identicon,
|
||||
}
|
||||
|
@ -151,6 +159,7 @@ func (db sqlitePersistence) tableUserMessagesScanAllFields(row scanner, message
|
|||
From: quotedFrom.String,
|
||||
Text: quotedText.String,
|
||||
Base64Image: quotedImage.String,
|
||||
Base64Audio: quotedAudio.String,
|
||||
}
|
||||
}
|
||||
message.Alias = alias.String
|
||||
|
@ -177,6 +186,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 +215,9 @@ func (db sqlitePersistence) tableUserMessagesAllValues(message *Message) ([]inte
|
|||
image.Payload,
|
||||
image.Type,
|
||||
message.Base64Image,
|
||||
audio.Payload,
|
||||
audio.Type,
|
||||
message.Base64Audio,
|
||||
command.ID,
|
||||
command.Value,
|
||||
command.From,
|
||||
|
|
|
@ -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)
|
||||
}
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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,26 @@ 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
|
||||
|
||||
}
|
||||
audio := protobuf.AudioMessage{
|
||||
Payload: payload,
|
||||
Type: audio.Type(payload),
|
||||
}
|
||||
message.Payload = &protobuf.ChatMessage_Audio{Audio: &audio}
|
||||
}
|
||||
|
||||
logger := m.logger.With(zap.String("site", "Send"), zap.String("chatID", message.ChatId))
|
||||
var response MessengerResponse
|
||||
|
||||
|
|
|
@ -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 (186B)
|
||||
// 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\x0a\xc2\x40\x0c\x05\xd0\x7d\x4f\xf1\xe9\x19\xc4\x4d\x57\x33\x4e\x04\x21\x66\x40\x32\xe0\xae\x44\x1a\x44\x50\x5a\x8c\x5d\xf4\xf6\x9e\xa1\x07\x78\x89\x95\x6e\xd0\x94\x99\xb0\x86\x7f\xc7\x8f\x47\xd8\xd3\x03\xa9\x14\x9c\x2a\xb7\xab\xc0\xd6\xe9\x35\x8f\x8b\x6d\xef\xd9\x26\x64\xae\x79\xe8\x76\xc0\xdf\xb6\x38\x2e\xa2\xbb\xd0\xc3\xc2\x8f\x07\x28\xdd\x15\x52\x15\xd2\x98\x51\xe8\x9c\x1a\x2b\xfa\x7e\xe8\xfe\x01\x00\x00\xff\xff\x87\xd0\x8b\xbb\xba\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: 186, mode: os.FileMode(0644), modTime: time.Unix(1595862768, 0)}
|
||||
a := &asset{bytes: bytes, info: info, digest: [32]uint8{0x49, 0xf0, 0xf7, 0x5d, 0x8e, 0xc4, 0xd5, 0xb1, 0xb0, 0xa, 0x7c, 0xbd, 0x26, 0x22, 0xfe, 0xc0, 0xf0, 0xb0, 0x4e, 0x97, 0x2f, 0xcf, 0x8c, 0x24, 0x88, 0xdc, 0x6e, 0xab, 0x41, 0x99, 0xce, 0x36}}
|
||||
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,6 +606,8 @@ 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{}},
|
||||
"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{}},
|
||||
}}
|
||||
|
||||
|
|
|
@ -0,0 +1,3 @@
|
|||
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_base64 TEXT NOT NULL DEFAULT "";
|
|
@ -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()
|
||||
|
|
|
@ -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,53 @@ 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"`
|
||||
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
|
||||
}
|
||||
|
||||
type ChatMessage struct {
|
||||
// Lamport timestamp of the chat message
|
||||
Clock uint64 `protobuf:"varint,1,opt,name=clock,proto3" json:"clock,omitempty"`
|
||||
|
@ -251,6 +329,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 +340,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 +429,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 +460,75 @@ 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,
|
||||
// 631 bytes of a gzipped FileDescriptorProto
|
||||
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xa4, 0x53, 0xcb, 0x4e, 0xdb, 0x40,
|
||||
0x14, 0xc5, 0x89, 0x13, 0xc7, 0xd7, 0x29, 0x9a, 0x4e, 0x11, 0xb8, 0x12, 0x52, 0x53, 0xab, 0x8b,
|
||||
0xac, 0xb2, 0xa0, 0x54, 0xea, 0xd6, 0x98, 0x69, 0x30, 0xe0, 0x87, 0xc6, 0x93, 0x52, 0x56, 0x96,
|
||||
0x71, 0xa6, 0x24, 0x02, 0xc7, 0x16, 0x36, 0x52, 0xd9, 0xf4, 0x13, 0xba, 0xeb, 0x47, 0x74, 0xdf,
|
||||
0x0f, 0xac, 0x66, 0x8c, 0x13, 0x83, 0xaa, 0x6e, 0xba, 0xf2, 0x7d, 0x9c, 0x7b, 0x7c, 0xe6, 0xce,
|
||||
0x19, 0xc0, 0xe9, 0x22, 0xa9, 0xe2, 0x8c, 0x97, 0x65, 0x72, 0xcd, 0x27, 0xc5, 0x5d, 0x5e, 0xe5,
|
||||
0x78, 0x20, 0x3f, 0x57, 0xf7, 0x5f, 0xad, 0x8f, 0xb0, 0x1d, 0x55, 0xcb, 0xf4, 0x86, 0xdf, 0x79,
|
||||
0x35, 0x02, 0x63, 0x50, 0x17, 0x49, 0xb9, 0x30, 0x95, 0x91, 0x32, 0xd6, 0xa9, 0x8c, 0x45, 0xad,
|
||||
0x48, 0xd2, 0x1b, 0xb3, 0x33, 0x52, 0xc6, 0x3d, 0x2a, 0x63, 0xeb, 0x97, 0x02, 0x43, 0x37, 0x4b,
|
||||
0xae, 0x79, 0x33, 0x68, 0x82, 0x56, 0x24, 0x0f, 0xb7, 0x79, 0x32, 0x97, 0xb3, 0x43, 0xda, 0xa4,
|
||||
0xf8, 0x10, 0xd4, 0xea, 0xa1, 0xe0, 0x72, 0x7c, 0xfb, 0x60, 0x34, 0x69, 0xfe, 0x3e, 0x69, 0xcf,
|
||||
0xd7, 0x09, 0x7b, 0x28, 0x38, 0x95, 0x68, 0xcb, 0x05, 0x7d, 0x5d, 0xc2, 0xbb, 0x80, 0x67, 0xfe,
|
||||
0x99, 0x1f, 0x5c, 0xf8, 0xb1, 0xeb, 0xd9, 0x53, 0x12, 0xb3, 0xcb, 0x90, 0xa0, 0x2d, 0xac, 0x41,
|
||||
0x37, 0xf4, 0xa7, 0x48, 0xc1, 0x03, 0x50, 0x4f, 0x43, 0x32, 0x45, 0x1d, 0x11, 0x5d, 0x90, 0xa3,
|
||||
0x10, 0x75, 0x45, 0x73, 0xea, 0x7e, 0x42, 0xaa, 0xf5, 0x53, 0x81, 0xa1, 0x7d, 0x3f, 0x5f, 0xe6,
|
||||
0xff, 0xa1, 0xb5, 0x3d, 0x5f, 0x27, 0x2d, 0xad, 0x1f, 0x40, 0x5f, 0x97, 0xda, 0x5a, 0xed, 0xd9,
|
||||
0xb1, 0x1b, 0xb4, 0xb4, 0xda, 0xb6, 0x83, 0x14, 0x19, 0x78, 0x14, 0x75, 0xac, 0x1f, 0x7d, 0x30,
|
||||
0x9c, 0x45, 0x52, 0x35, 0xb2, 0x76, 0xa0, 0x97, 0xde, 0xe6, 0xe9, 0x8d, 0x14, 0xa5, 0xd2, 0x3a,
|
||||
0xc1, 0xfb, 0xa0, 0x57, 0xcb, 0x8c, 0x97, 0x55, 0x92, 0x15, 0x52, 0x97, 0x4a, 0x37, 0x05, 0x71,
|
||||
0x37, 0x15, 0xff, 0x56, 0x99, 0xdd, 0xfa, 0xbe, 0x44, 0x8c, 0xdf, 0x80, 0x71, 0xc7, 0xcb, 0x22,
|
||||
0x5f, 0x95, 0x3c, 0xae, 0x72, 0x53, 0x95, 0x2d, 0x68, 0x4a, 0x2c, 0xc7, 0xaf, 0x61, 0xc0, 0x57,
|
||||
0x65, 0xbc, 0x4a, 0x32, 0x6e, 0xf6, 0x64, 0x57, 0xe3, 0xab, 0xd2, 0x4f, 0x32, 0x8e, 0xf7, 0x40,
|
||||
0x93, 0x8e, 0x59, 0xce, 0xcd, 0xbe, 0xec, 0xf4, 0x45, 0xea, 0xce, 0xf1, 0x31, 0x0c, 0x1f, 0x5d,
|
||||
0x14, 0xcb, 0x0d, 0x69, 0x72, 0x43, 0x6f, 0x37, 0x1b, 0x6a, 0x9d, 0x64, 0xf2, 0xf8, 0x95, 0x2b,
|
||||
0x32, 0xb2, 0x4d, 0x22, 0x58, 0xd2, 0x7c, 0x55, 0xf1, 0x55, 0x55, 0xb3, 0x0c, 0xfe, 0xc5, 0xe2,
|
||||
0xd4, 0xc8, 0x9a, 0x25, 0xdd, 0x24, 0xf8, 0x10, 0xb4, 0xb2, 0xb6, 0xad, 0xa9, 0x8f, 0x94, 0xb1,
|
||||
0x71, 0x60, 0x6e, 0x08, 0x9e, 0xfa, 0xf9, 0x64, 0x8b, 0x36, 0x50, 0x3c, 0x81, 0xde, 0x52, 0x38,
|
||||
0xca, 0x04, 0x39, 0xb3, 0xfb, 0x77, 0x23, 0x9e, 0x6c, 0xd1, 0x1a, 0x26, 0xf0, 0x89, 0xb8, 0x55,
|
||||
0xd3, 0x78, 0x8e, 0x6f, 0x9b, 0x41, 0xe0, 0x25, 0xcc, 0xfa, 0x0e, 0x46, 0xeb, 0xdc, 0xd8, 0x84,
|
||||
0x9d, 0xc6, 0x07, 0x1e, 0x89, 0xa2, 0x96, 0x6b, 0xb7, 0x01, 0x02, 0x9f, 0xc4, 0x2c, 0x88, 0x03,
|
||||
0x9f, 0x20, 0x05, 0x23, 0x18, 0x86, 0xb3, 0xa3, 0x73, 0xd7, 0x89, 0xa7, 0x34, 0x98, 0x85, 0xa8,
|
||||
0x83, 0x5f, 0xc2, 0x8b, 0x90, 0xba, 0x9f, 0x6d, 0x46, 0x1e, 0x4b, 0x5d, 0x3c, 0x82, 0xfd, 0xe8,
|
||||
0x32, 0x62, 0xc4, 0x5b, 0xb3, 0x3d, 0x45, 0xa8, 0xd6, 0x6f, 0x05, 0x8c, 0xd6, 0xca, 0xda, 0x02,
|
||||
0x9c, 0xc0, 0x67, 0xc4, 0x67, 0x2d, 0x01, 0x8c, 0x7c, 0x61, 0x71, 0x78, 0x6e, 0xbb, 0x3e, 0x52,
|
||||
0xb0, 0x01, 0x5a, 0xc4, 0x5c, 0xe7, 0x8c, 0x50, 0xd4, 0xc1, 0x00, 0xfd, 0x88, 0xd9, 0x6c, 0x16,
|
||||
0xa1, 0x2e, 0xd6, 0xa1, 0x47, 0xbc, 0xe0, 0xd4, 0x45, 0x2a, 0xde, 0x83, 0x57, 0x8c, 0xda, 0x7e,
|
||||
0x64, 0x3b, 0xcc, 0x0d, 0x04, 0xa3, 0xe7, 0xd9, 0xfe, 0x31, 0xea, 0xe1, 0x31, 0xbc, 0x7b, 0x26,
|
||||
0xac, 0xf9, 0xdb, 0x53, 0x81, 0x7d, 0xc1, 0x26, 0x5f, 0x2f, 0xd2, 0x44, 0x28, 0x1f, 0x07, 0x1a,
|
||||
0x1c, 0xe9, 0xeb, 0xc7, 0x78, 0xd5, 0x97, 0x1b, 0x7e, 0xff, 0x27, 0x00, 0x00, 0xff, 0xff, 0x68,
|
||||
0xd3, 0x79, 0xbb, 0xb5, 0x04, 0x00, 0x00,
|
||||
}
|
||||
|
|
|
@ -19,6 +19,16 @@ message ImageMessage {
|
|||
}
|
||||
}
|
||||
|
||||
message AudioMessage {
|
||||
bytes payload = 1;
|
||||
AudioType type = 2;
|
||||
enum AudioType {
|
||||
UNKNOWN_AUDIO_TYPE = 0;
|
||||
AAC = 1;
|
||||
AMR = 2;
|
||||
}
|
||||
}
|
||||
|
||||
message ChatMessage {
|
||||
// Lamport timestamp of the chat message
|
||||
uint64 clock = 1;
|
||||
|
@ -45,6 +55,7 @@ message ChatMessage {
|
|||
oneof payload {
|
||||
StickerMessage sticker = 9;
|
||||
ImageMessage image = 10;
|
||||
AudioMessage audio = 11;
|
||||
}
|
||||
|
||||
enum MessageType {
|
||||
|
@ -64,5 +75,6 @@ message ChatMessage {
|
|||
// Only local
|
||||
SYSTEM_MESSAGE_CONTENT_PRIVATE_GROUP = 6;
|
||||
IMAGE = 7;
|
||||
AUDIO = 8;
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue