Added public chat ChatIdentity publish

This commit is contained in:
Samuel Hawksby-Robinson 2020-11-09 15:16:36 +00:00 committed by Andrea Maria Piana
parent 48a34072bb
commit a564066c4f
3 changed files with 112 additions and 35 deletions

View File

@ -88,7 +88,7 @@ func setupTestDB(t *testing.T) (Database, func()) {
func seedTestDB(t *testing.T, db Database) {
iis := []*IdentityImage{
{
Name: smallDimName,
Name: SmallDimName,
Payload: testJpegBytes,
Width: 80,
Height: 80,
@ -96,7 +96,7 @@ func seedTestDB(t *testing.T, db Database) {
ResizeTarget: 80,
},
{
Name: largeDimName,
Name: LargeDimName,
Payload: testPngBytes,
Width: 240,
Height: 300,
@ -133,11 +133,11 @@ func TestDatabase_GetIdentityImage(t *testing.T) {
Expected string
}{
{
smallDimName,
SmallDimName,
`{"name":"thumbnail","uri":"data:image/jpeg;base64,/9j/2wCEAFA3PEY8MlA=","width":80,"height":80,"file_size":256,"resize_target":80}`,
},
{
largeDimName,
LargeDimName,
`{"name":"large","uri":"data:image/png;base64,iVBORw0KGgoAAAANSUg=","width":240,"height":300,"file_size":1024,"resize_target":240}`,
},
}
@ -157,9 +157,9 @@ func TestDatabase_DeleteIdentityImage(t *testing.T) {
defer stop()
seedTestDB(t, db)
require.NoError(t, db.DeleteIdentityImage(smallDimName))
require.NoError(t, db.DeleteIdentityImage(SmallDimName))
oii, err := db.GetIdentityImage(smallDimName)
oii, err := db.GetIdentityImage(SmallDimName)
require.NoError(t, err)
require.Empty(t, oii)
}

View File

@ -17,8 +17,8 @@ const (
SmallDim = ResizeDimension(80)
LargeDim = ResizeDimension(240)
smallDimName = "thumbnail"
largeDimName = "large"
SmallDimName = "thumbnail"
LargeDimName = "large"
)
var (
@ -40,14 +40,14 @@ var (
// ResizeDimensionToName maps a ResizeDimension to its assigned string name
ResizeDimensionToName = map[ResizeDimension]string{
SmallDim: smallDimName,
LargeDim: largeDimName,
SmallDim: SmallDimName,
LargeDim: LargeDimName,
}
// NameToResizeDimension maps a string name to its assigned ResizeDimension
NameToResizeDimension = map[string]ResizeDimension{
smallDimName: SmallDim,
largeDimName: LargeDim,
SmallDimName: SmallDim,
LargeDimName: LargeDim,
}
)

View File

@ -484,21 +484,21 @@ func (m *Messenger) handleSendContactCode() error {
}
// contactCodeAdvertisement attaches a protobuf.ChatIdentity to the given protobuf.ContactCodeAdvertisement,
// if the last time the ChatIdentity was attached was more than 24 hours ago
// if the `shouldPublish` conditions are met
func (m *Messenger) handleContactCodeChatIdentity(cca *protobuf.ContactCodeAdvertisement) error {
pubKey := transport.PublicKeyToStr(&m.identity.PublicKey)
lp, err := m.persistence.GetWhenChatIdentityLastPublished(pubKey)
contactCodeTopic := transport.ContactCodeTopic(&m.identity.PublicKey)
shouldPublish, err := m.shouldPublishChatIdentity(contactCodeTopic)
if err != nil {
return err
}
if *lp == 0 || *lp - time.Now().Unix() > 24 * 60 * 60{
err = m.attachChatIdentity(cca)
if shouldPublish {
cca.ChatIdentity, err = m.createChatIdentity("private-chat")
if err != nil {
return err
}
err := m.persistence.SaveWhenChatIdentityLastPublished(pubKey)
err = m.persistence.SaveWhenChatIdentityLastPublished(contactCodeTopic)
if err != nil {
return err
}
@ -507,34 +507,106 @@ func (m *Messenger) handleContactCodeChatIdentity(cca *protobuf.ContactCodeAdver
return nil
}
// attachChatIdentity
func (m *Messenger) attachChatIdentity(cca *protobuf.ContactCodeAdvertisement) error {
// handleStandaloneChatIdentity sends a standalone ChatIdentity message to a public channel if the publish criteria is met
func (m *Messenger) handleStandaloneChatIdentity(chat *Chat) error {
if chat.ChatType != ChatTypePublic {
return nil
}
shouldPublishChatIdentity, err := m.shouldPublishChatIdentity(chat.ID)
if err != nil {
return err
}
if !shouldPublishChatIdentity {
return nil
}
idb := userimage.NewDatabase(m.database)
imgs, err := idb.GetIdentityImages()
ci, err := m.createChatIdentity("public-chat")
if err != nil {
return err
}
// Adapt images.IdentityImage to protobuf.IdentityImage
ciis := make(map[string]*protobuf.IdentityImage)
for _, img := range imgs {
ciis[img.Name] = &protobuf.IdentityImage{
Payload: img.Payload,
SourceType: protobuf.IdentityImage_RAW_PAYLOAD, // TODO add ENS avatar handling to dedicated PR
ImageType: images.ImageType(img.Payload),
}
payload, err := proto.Marshal(ci)
if err != nil {
return err
}
cca.ChatIdentity = &protobuf.ChatIdentity{
Clock: m.transport.GetCurrentTime(),
EnsName: "", // TODO add ENS name handling to dedicate PR
Images: ciis,
rawMessage := common.RawMessage{
LocalChatID: chat.ID,
MessageType: protobuf.ApplicationMetadataMessage_CHAT_IDENTITY,
Payload: payload,
}
ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
defer cancel()
_, err = m.processor.SendPublic(ctx, chat.ID, rawMessage)
if err != nil {
return err
}
err = m.persistence.SaveWhenChatIdentityLastPublished(chat.ID)
if err != nil {
return err
}
return nil
}
// shouldPublishChatIdentity returns true if the last time the ChatIdentity was attached was more than 24 hours ago
func (m *Messenger) shouldPublishChatIdentity(chatId string) (bool, error) {
lp, err := m.persistence.GetWhenChatIdentityLastPublished(chatId)
if err != nil {
return false, err
}
return *lp == 0 || time.Now().Unix() - *lp > 24 * 60 * 60, nil
}
// createChatIdentity creates a context based protobuf.ChatIdentity.
// context 'public-chat' will attach only the 'thumbnail' IdentityImage
// contect 'private-chat' will attach all IdentityImage
func (m *Messenger) createChatIdentity(context string) (*protobuf.ChatIdentity, error) {
ci := &protobuf.ChatIdentity{
Clock: m.transport.GetCurrentTime(),
EnsName: "", // TODO add ENS name handling to dedicate PR
}
ciis := make(map[string]*protobuf.IdentityImage)
switch context {
case "public-chat":
idb := userimage.NewDatabase(m.database)
img, err := idb.GetIdentityImage(userimage.SmallDimName)
if err != nil {
return nil, err
}
ciis[userimage.SmallDimName] = m.adaptIdentityImageToProtobuf(img)
ci.Images = ciis
case "private-chat":
idb := userimage.NewDatabase(m.database)
imgs, err := idb.GetIdentityImages()
if err != nil {
return nil, err
}
for _, img := range imgs {
ciis[img.Name] = m.adaptIdentityImageToProtobuf(img)
}
ci.Images = ciis
}
return ci, nil
}
// adaptIdentityImageToProtobuf Adapts a images.IdentityImage to protobuf.IdentityImage
func (m *Messenger) adaptIdentityImageToProtobuf(img *userimage.IdentityImage) *protobuf.IdentityImage {
return &protobuf.IdentityImage{
Payload: img.Payload,
SourceType: protobuf.IdentityImage_RAW_PAYLOAD, // TODO add ENS avatar handling to dedicated PR
ImageType: images.ImageType(img.Payload),
}
}
// handleSharedSecrets process the negotiated secrets received from the encryption layer
func (m *Messenger) handleSharedSecrets(secrets []*sharedsecret.Secret) error {
var result []*transport.Filter
@ -1984,7 +2056,12 @@ func (m *Messenger) sendChatMessage(ctx context.Context, message *common.Message
return nil, errors.New("Chat not found")
}
err := extendMessageFromChat(message, chat, &m.identity.PublicKey, m.getTimesource())
err := m.handleStandaloneChatIdentity(chat)
if err != nil {
return nil, err
}
err = extendMessageFromChat(message, chat, &m.identity.PublicKey, m.getTimesource())
if err != nil {
return nil, err
}