Only set force RCS flag if chat has had e2ee tombstone

This commit is contained in:
Tulir Asokan 2024-06-13 20:46:18 +03:00
parent 56bfc105ed
commit 2c373db8fc
10 changed files with 217 additions and 109 deletions

View file

@ -37,18 +37,18 @@ func newPortal(qh *dbutil.QueryHelper[*Portal]) *Portal {
} }
const ( const (
getAllPortalsQuery = "SELECT id, receiver, self_user, other_user, type, mxid, name, name_set, encrypted, in_space FROM portal" getAllPortalsQuery = "SELECT id, receiver, self_user, other_user, type, send_mode, force_rcs, mxid, name, name_set, encrypted, in_space FROM portal"
getAllPortalsForUserQuery = getAllPortalsQuery + " WHERE receiver=$1" getAllPortalsForUserQuery = getAllPortalsQuery + " WHERE receiver=$1"
getPortalByKeyQuery = getAllPortalsQuery + " WHERE id=$1 AND receiver=$2" getPortalByKeyQuery = getAllPortalsQuery + " WHERE id=$1 AND receiver=$2"
getPortalByOtherUserQuery = getAllPortalsQuery + " WHERE other_user=$1 AND receiver=$2" getPortalByOtherUserQuery = getAllPortalsQuery + " WHERE other_user=$1 AND receiver=$2"
getPortalByMXIDQuery = getAllPortalsQuery + " WHERE mxid=$1" getPortalByMXIDQuery = getAllPortalsQuery + " WHERE mxid=$1"
insertPortalQuery = ` insertPortalQuery = `
INSERT INTO portal (id, receiver, self_user, other_user, type, mxid, name, name_set, encrypted, in_space) INSERT INTO portal (id, receiver, self_user, other_user, type, send_mode, force_rcs, mxid, name, name_set, encrypted, in_space)
VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10) VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12)
` `
updatePortalQuery = ` updatePortalQuery = `
UPDATE portal UPDATE portal
SET self_user=$3, other_user=$4, type=$5, mxid=$6, name=$7, name_set=$8, encrypted=$9, in_space=$10 SET self_user=$3, other_user=$4, type=$5, send_mode=$6, force_rcs=$7, mxid=$8, name=$9, name_set=$10, encrypted=$11, in_space=$12
WHERE id=$1 AND receiver=$2 WHERE id=$1 AND receiver=$2
` `
deletePortalQuery = "DELETE FROM portal WHERE id=$1 AND receiver=$2" deletePortalQuery = "DELETE FROM portal WHERE id=$1 AND receiver=$2"
@ -96,6 +96,8 @@ type Portal struct {
MXID id.RoomID MXID id.RoomID
Type gmproto.ConversationType Type gmproto.ConversationType
SendMode gmproto.ConversationSendMode
ForceRCS bool
Name string Name string
NameSet bool NameSet bool
Encrypted bool Encrypted bool
@ -104,15 +106,16 @@ type Portal struct {
func (portal *Portal) Scan(row dbutil.Scannable) (*Portal, error) { func (portal *Portal) Scan(row dbutil.Scannable) (*Portal, error) {
var mxid, selfUserID, otherUserID sql.NullString var mxid, selfUserID, otherUserID sql.NullString
var convType int var convType, sendMode int
err := row.Scan( err := row.Scan(
&portal.ID, &portal.Receiver, &selfUserID, &otherUserID, &convType, &mxid, &portal.ID, &portal.Receiver, &selfUserID, &otherUserID, &convType, &sendMode, &portal.ForceRCS, &mxid,
&portal.Name, &portal.NameSet, &portal.Encrypted, &portal.InSpace, &portal.Name, &portal.NameSet, &portal.Encrypted, &portal.InSpace,
) )
if err != nil { if err != nil {
return nil, err return nil, err
} }
portal.Type = gmproto.ConversationType(convType) portal.Type = gmproto.ConversationType(convType)
portal.SendMode = gmproto.ConversationSendMode(sendMode)
portal.MXID = id.RoomID(mxid.String) portal.MXID = id.RoomID(mxid.String)
portal.OutgoingID = selfUserID.String portal.OutgoingID = selfUserID.String
portal.OtherUserID = otherUserID.String portal.OtherUserID = otherUserID.String
@ -122,7 +125,7 @@ func (portal *Portal) Scan(row dbutil.Scannable) (*Portal, error) {
func (portal *Portal) sqlVariables() []any { func (portal *Portal) sqlVariables() []any {
return []any{ return []any{
portal.ID, portal.Receiver, dbutil.StrPtr(portal.OutgoingID), dbutil.StrPtr(portal.OtherUserID), portal.ID, portal.Receiver, dbutil.StrPtr(portal.OutgoingID), dbutil.StrPtr(portal.OtherUserID),
int(portal.Type), dbutil.StrPtr(portal.MXID), int(portal.Type), int(portal.SendMode), portal.ForceRCS, dbutil.StrPtr(portal.MXID),
portal.Name, portal.NameSet, portal.Encrypted, portal.InSpace, portal.Name, portal.NameSet, portal.Encrypted, portal.InSpace,
} }
} }

View file

@ -1,4 +1,4 @@
-- v0 -> v9: Latest revision -- v0 -> v10 (compatible with v9+): Latest revision
CREATE TABLE "user" ( CREATE TABLE "user" (
-- only: postgres -- only: postgres
@ -44,6 +44,8 @@ CREATE TABLE portal (
self_user TEXT, self_user TEXT,
other_user TEXT, other_user TEXT,
type INTEGER NOT NULL, type INTEGER NOT NULL,
send_mode INTEGER NOT NULL,
force_rcs BOOLEAN NOT NULL DEFAULT false,
mxid TEXT UNIQUE, mxid TEXT UNIQUE,
name TEXT NOT NULL, name TEXT NOT NULL,
name_set BOOLEAN NOT NULL DEFAULT false, name_set BOOLEAN NOT NULL DEFAULT false,

View file

@ -0,0 +1,3 @@
-- v10 (compatible with v9+): Store send mode for portals
ALTER TABLE portal ADD COLUMN send_mode INTEGER NOT NULL DEFAULT 0;
ALTER TABLE portal ADD COLUMN force_rcs BOOLEAN NOT NULL DEFAULT false;

View file

@ -2383,7 +2383,7 @@ type SendMessageRequest struct {
MessagePayload *MessagePayload `protobuf:"bytes,3,opt,name=messagePayload,proto3" json:"messagePayload,omitempty"` MessagePayload *MessagePayload `protobuf:"bytes,3,opt,name=messagePayload,proto3" json:"messagePayload,omitempty"`
SIMPayload *SIMPayload `protobuf:"bytes,4,opt,name=SIMPayload,proto3" json:"SIMPayload,omitempty"` SIMPayload *SIMPayload `protobuf:"bytes,4,opt,name=SIMPayload,proto3" json:"SIMPayload,omitempty"`
TmpID string `protobuf:"bytes,5,opt,name=tmpID,proto3" json:"tmpID,omitempty"` TmpID string `protobuf:"bytes,5,opt,name=tmpID,proto3" json:"tmpID,omitempty"`
IsRCS bool `protobuf:"varint,6,opt,name=isRCS,proto3" json:"isRCS,omitempty"` // not sure ForceRCS bool `protobuf:"varint,6,opt,name=forceRCS,proto3" json:"forceRCS,omitempty"`
Reply *ReplyPayload `protobuf:"bytes,8,opt,name=reply,proto3" json:"reply,omitempty"` Reply *ReplyPayload `protobuf:"bytes,8,opt,name=reply,proto3" json:"reply,omitempty"`
} }
@ -2447,9 +2447,9 @@ func (x *SendMessageRequest) GetTmpID() string {
return "" return ""
} }
func (x *SendMessageRequest) GetIsRCS() bool { func (x *SendMessageRequest) GetForceRCS() bool {
if x != nil { if x != nil {
return x.IsRCS return x.ForceRCS
} }
return false return false
} }

Binary file not shown.

View file

@ -255,7 +255,7 @@ message SendMessageRequest {
MessagePayload messagePayload = 3; MessagePayload messagePayload = 3;
settings.SIMPayload SIMPayload = 4; settings.SIMPayload SIMPayload = 4;
string tmpID = 5; string tmpID = 5;
bool isRCS = 6; // not sure bool forceRCS = 6;
ReplyPayload reply = 8; ReplyPayload reply = 8;
} }

View file

@ -153,6 +153,55 @@ func (IdentifierType) EnumDescriptor() ([]byte, []int) {
return file_conversations_proto_rawDescGZIP(), []int{1} return file_conversations_proto_rawDescGZIP(), []int{1}
} }
type ConversationSendMode int32
const (
ConversationSendMode_SEND_MODE_AUTO ConversationSendMode = 0
ConversationSendMode_SEND_MODE_XMS ConversationSendMode = 1
ConversationSendMode_SEND_MODE_XMS_LATCH ConversationSendMode = 2
)
// Enum value maps for ConversationSendMode.
var (
ConversationSendMode_name = map[int32]string{
0: "SEND_MODE_AUTO",
1: "SEND_MODE_XMS",
2: "SEND_MODE_XMS_LATCH",
}
ConversationSendMode_value = map[string]int32{
"SEND_MODE_AUTO": 0,
"SEND_MODE_XMS": 1,
"SEND_MODE_XMS_LATCH": 2,
}
)
func (x ConversationSendMode) Enum() *ConversationSendMode {
p := new(ConversationSendMode)
*p = x
return p
}
func (x ConversationSendMode) String() string {
return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x))
}
func (ConversationSendMode) Descriptor() protoreflect.EnumDescriptor {
return file_conversations_proto_enumTypes[2].Descriptor()
}
func (ConversationSendMode) Type() protoreflect.EnumType {
return &file_conversations_proto_enumTypes[2]
}
func (x ConversationSendMode) Number() protoreflect.EnumNumber {
return protoreflect.EnumNumber(x)
}
// Deprecated: Use ConversationSendMode.Descriptor instead.
func (ConversationSendMode) EnumDescriptor() ([]byte, []int) {
return file_conversations_proto_rawDescGZIP(), []int{2}
}
type ConversationType int32 type ConversationType int32
const ( const (
@ -186,11 +235,11 @@ func (x ConversationType) String() string {
} }
func (ConversationType) Descriptor() protoreflect.EnumDescriptor { func (ConversationType) Descriptor() protoreflect.EnumDescriptor {
return file_conversations_proto_enumTypes[2].Descriptor() return file_conversations_proto_enumTypes[3].Descriptor()
} }
func (ConversationType) Type() protoreflect.EnumType { func (ConversationType) Type() protoreflect.EnumType {
return &file_conversations_proto_enumTypes[2] return &file_conversations_proto_enumTypes[3]
} }
func (x ConversationType) Number() protoreflect.EnumNumber { func (x ConversationType) Number() protoreflect.EnumNumber {
@ -199,7 +248,7 @@ func (x ConversationType) Number() protoreflect.EnumNumber {
// Deprecated: Use ConversationType.Descriptor instead. // Deprecated: Use ConversationType.Descriptor instead.
func (ConversationType) EnumDescriptor() ([]byte, []int) { func (ConversationType) EnumDescriptor() ([]byte, []int) {
return file_conversations_proto_rawDescGZIP(), []int{2} return file_conversations_proto_rawDescGZIP(), []int{3}
} }
type MessageStatusType int32 type MessageStatusType int32
@ -463,11 +512,11 @@ func (x MessageStatusType) String() string {
} }
func (MessageStatusType) Descriptor() protoreflect.EnumDescriptor { func (MessageStatusType) Descriptor() protoreflect.EnumDescriptor {
return file_conversations_proto_enumTypes[3].Descriptor() return file_conversations_proto_enumTypes[4].Descriptor()
} }
func (MessageStatusType) Type() protoreflect.EnumType { func (MessageStatusType) Type() protoreflect.EnumType {
return &file_conversations_proto_enumTypes[3] return &file_conversations_proto_enumTypes[4]
} }
func (x MessageStatusType) Number() protoreflect.EnumNumber { func (x MessageStatusType) Number() protoreflect.EnumNumber {
@ -476,7 +525,7 @@ func (x MessageStatusType) Number() protoreflect.EnumNumber {
// Deprecated: Use MessageStatusType.Descriptor instead. // Deprecated: Use MessageStatusType.Descriptor instead.
func (MessageStatusType) EnumDescriptor() ([]byte, []int) { func (MessageStatusType) EnumDescriptor() ([]byte, []int) {
return file_conversations_proto_rawDescGZIP(), []int{3} return file_conversations_proto_rawDescGZIP(), []int{4}
} }
type ConversationStatus int32 type ConversationStatus int32
@ -524,11 +573,11 @@ func (x ConversationStatus) String() string {
} }
func (ConversationStatus) Descriptor() protoreflect.EnumDescriptor { func (ConversationStatus) Descriptor() protoreflect.EnumDescriptor {
return file_conversations_proto_enumTypes[4].Descriptor() return file_conversations_proto_enumTypes[5].Descriptor()
} }
func (ConversationStatus) Type() protoreflect.EnumType { func (ConversationStatus) Type() protoreflect.EnumType {
return &file_conversations_proto_enumTypes[4] return &file_conversations_proto_enumTypes[5]
} }
func (x ConversationStatus) Number() protoreflect.EnumNumber { func (x ConversationStatus) Number() protoreflect.EnumNumber {
@ -537,7 +586,7 @@ func (x ConversationStatus) Number() protoreflect.EnumNumber {
// Deprecated: Use ConversationStatus.Descriptor instead. // Deprecated: Use ConversationStatus.Descriptor instead.
func (ConversationStatus) EnumDescriptor() ([]byte, []int) { func (ConversationStatus) EnumDescriptor() ([]byte, []int) {
return file_conversations_proto_rawDescGZIP(), []int{4} return file_conversations_proto_rawDescGZIP(), []int{5}
} }
type MediaFormats int32 type MediaFormats int32
@ -696,11 +745,11 @@ func (x MediaFormats) String() string {
} }
func (MediaFormats) Descriptor() protoreflect.EnumDescriptor { func (MediaFormats) Descriptor() protoreflect.EnumDescriptor {
return file_conversations_proto_enumTypes[5].Descriptor() return file_conversations_proto_enumTypes[6].Descriptor()
} }
func (MediaFormats) Type() protoreflect.EnumType { func (MediaFormats) Type() protoreflect.EnumType {
return &file_conversations_proto_enumTypes[5] return &file_conversations_proto_enumTypes[6]
} }
func (x MediaFormats) Number() protoreflect.EnumNumber { func (x MediaFormats) Number() protoreflect.EnumNumber {
@ -709,7 +758,7 @@ func (x MediaFormats) Number() protoreflect.EnumNumber {
// Deprecated: Use MediaFormats.Descriptor instead. // Deprecated: Use MediaFormats.Descriptor instead.
func (MediaFormats) EnumDescriptor() ([]byte, []int) { func (MediaFormats) EnumDescriptor() ([]byte, []int) {
return file_conversations_proto_rawDescGZIP(), []int{5} return file_conversations_proto_rawDescGZIP(), []int{6}
} }
type Contact struct { type Contact struct {
@ -1839,24 +1888,25 @@ type Conversation struct {
sizeCache protoimpl.SizeCache sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields unknownFields protoimpl.UnknownFields
ConversationID string `protobuf:"bytes,1,opt,name=conversationID,proto3" json:"conversationID,omitempty"` ConversationID string `protobuf:"bytes,1,opt,name=conversationID,proto3" json:"conversationID,omitempty"`
Name string `protobuf:"bytes,2,opt,name=name,proto3" json:"name,omitempty"` Name string `protobuf:"bytes,2,opt,name=name,proto3" json:"name,omitempty"`
LatestMessage *LatestMessage `protobuf:"bytes,4,opt,name=latestMessage,proto3" json:"latestMessage,omitempty"` LatestMessage *LatestMessage `protobuf:"bytes,4,opt,name=latestMessage,proto3" json:"latestMessage,omitempty"`
LastMessageTimestamp int64 `protobuf:"varint,5,opt,name=lastMessageTimestamp,proto3" json:"lastMessageTimestamp,omitempty"` LastMessageTimestamp int64 `protobuf:"varint,5,opt,name=lastMessageTimestamp,proto3" json:"lastMessageTimestamp,omitempty"`
Unread bool `protobuf:"varint,6,opt,name=unread,proto3" json:"unread,omitempty"` Unread bool `protobuf:"varint,6,opt,name=unread,proto3" json:"unread,omitempty"`
IsGroupChat bool `protobuf:"varint,10,opt,name=isGroupChat,proto3" json:"isGroupChat,omitempty"` // not certain IsGroupChat bool `protobuf:"varint,10,opt,name=isGroupChat,proto3" json:"isGroupChat,omitempty"` // not certain
DefaultOutgoingID string `protobuf:"bytes,11,opt,name=defaultOutgoingID,proto3" json:"defaultOutgoingID,omitempty"` DefaultOutgoingID string `protobuf:"bytes,11,opt,name=defaultOutgoingID,proto3" json:"defaultOutgoingID,omitempty"`
Status ConversationStatus `protobuf:"varint,12,opt,name=status,proto3,enum=conversations.ConversationStatus" json:"status,omitempty"` Status ConversationStatus `protobuf:"varint,12,opt,name=status,proto3,enum=conversations.ConversationStatus" json:"status,omitempty"`
ReadOnly bool `protobuf:"varint,13,opt,name=readOnly,proto3" json:"readOnly,omitempty"` ReadOnly bool `protobuf:"varint,13,opt,name=readOnly,proto3" json:"readOnly,omitempty"`
AvatarHexColor string `protobuf:"bytes,15,opt,name=avatarHexColor,proto3" json:"avatarHexColor,omitempty"` AvatarHexColor string `protobuf:"bytes,15,opt,name=avatarHexColor,proto3" json:"avatarHexColor,omitempty"`
LatestMessageID string `protobuf:"bytes,17,opt,name=latestMessageID,proto3" json:"latestMessageID,omitempty"` LatestMessageID string `protobuf:"bytes,17,opt,name=latestMessageID,proto3" json:"latestMessageID,omitempty"`
Participants []*Participant `protobuf:"bytes,20,rep,name=participants,proto3" json:"participants,omitempty"` SendMode ConversationSendMode `protobuf:"varint,18,opt,name=sendMode,proto3,enum=conversations.ConversationSendMode" json:"sendMode,omitempty"`
OtherParticipants []string `protobuf:"bytes,21,rep,name=otherParticipants,proto3" json:"otherParticipants,omitempty"` // participant ids excluding me Participants []*Participant `protobuf:"bytes,20,rep,name=participants,proto3" json:"participants,omitempty"`
Type ConversationType `protobuf:"varint,22,opt,name=type,proto3,enum=conversations.ConversationType" json:"type,omitempty"` OtherParticipants []string `protobuf:"bytes,21,rep,name=otherParticipants,proto3" json:"otherParticipants,omitempty"` // participant ids excluding me
SubType bool `protobuf:"varint,24,opt,name=subType,proto3" json:"subType,omitempty"` Type ConversationType `protobuf:"varint,22,opt,name=type,proto3,enum=conversations.ConversationType" json:"type,omitempty"`
Pinned bool `protobuf:"varint,26,opt,name=pinned,proto3" json:"pinned,omitempty"` SubType bool `protobuf:"varint,24,opt,name=subType,proto3" json:"subType,omitempty"`
UnknownTimestamp int64 `protobuf:"varint,28,opt,name=unknownTimestamp,proto3" json:"unknownTimestamp,omitempty"` // set to lastMessageTimestamp + 1000 when marking as unread? Pinned bool `protobuf:"varint,26,opt,name=pinned,proto3" json:"pinned,omitempty"`
ThirdType bool `protobuf:"varint,29,opt,name=thirdType,proto3" json:"thirdType,omitempty"` UnknownTimestamp int64 `protobuf:"varint,28,opt,name=unknownTimestamp,proto3" json:"unknownTimestamp,omitempty"` // set to lastMessageTimestamp + 1000 when marking as unread?
ThirdType bool `protobuf:"varint,29,opt,name=thirdType,proto3" json:"thirdType,omitempty"`
} }
func (x *Conversation) Reset() { func (x *Conversation) Reset() {
@ -1968,6 +2018,13 @@ func (x *Conversation) GetLatestMessageID() string {
return "" return ""
} }
func (x *Conversation) GetSendMode() ConversationSendMode {
if x != nil {
return x.SendMode
}
return ConversationSendMode_SEND_MODE_AUTO
}
func (x *Conversation) GetParticipants() []*Participant { func (x *Conversation) GetParticipants() []*Participant {
if x != nil { if x != nil {
return x.Participants return x.Participants
@ -2673,77 +2730,79 @@ func file_conversations_proto_rawDescGZIP() []byte {
return file_conversations_proto_rawDescData return file_conversations_proto_rawDescData
} }
var file_conversations_proto_enumTypes = make([]protoimpl.EnumInfo, 6) var file_conversations_proto_enumTypes = make([]protoimpl.EnumInfo, 7)
var file_conversations_proto_msgTypes = make([]protoimpl.MessageInfo, 26) var file_conversations_proto_msgTypes = make([]protoimpl.MessageInfo, 26)
var file_conversations_proto_goTypes = []interface{}{ var file_conversations_proto_goTypes = []interface{}{
(EmojiType)(0), // 0: conversations.EmojiType (EmojiType)(0), // 0: conversations.EmojiType
(IdentifierType)(0), // 1: conversations.IdentifierType (IdentifierType)(0), // 1: conversations.IdentifierType
(ConversationType)(0), // 2: conversations.ConversationType (ConversationSendMode)(0), // 2: conversations.ConversationSendMode
(MessageStatusType)(0), // 3: conversations.MessageStatusType (ConversationType)(0), // 3: conversations.ConversationType
(ConversationStatus)(0), // 4: conversations.ConversationStatus (MessageStatusType)(0), // 4: conversations.MessageStatusType
(MediaFormats)(0), // 5: conversations.MediaFormats (ConversationStatus)(0), // 5: conversations.ConversationStatus
(*Contact)(nil), // 6: conversations.Contact (MediaFormats)(0), // 6: conversations.MediaFormats
(*ContactNumber)(nil), // 7: conversations.ContactNumber (*Contact)(nil), // 7: conversations.Contact
(*Message)(nil), // 8: conversations.Message (*ContactNumber)(nil), // 8: conversations.ContactNumber
(*ReactionEntry)(nil), // 9: conversations.ReactionEntry (*Message)(nil), // 9: conversations.Message
(*CustomEmojiData)(nil), // 10: conversations.CustomEmojiData (*ReactionEntry)(nil), // 10: conversations.ReactionEntry
(*ReactionData)(nil), // 11: conversations.ReactionData (*CustomEmojiData)(nil), // 11: conversations.CustomEmojiData
(*EmojiMeta)(nil), // 12: conversations.EmojiMeta (*ReactionData)(nil), // 12: conversations.ReactionData
(*EmojiMetaData)(nil), // 13: conversations.EmojiMetaData (*EmojiMeta)(nil), // 13: conversations.EmojiMeta
(*ReplyMessage)(nil), // 14: conversations.ReplyMessage (*EmojiMetaData)(nil), // 14: conversations.EmojiMetaData
(*ReplyMessageData)(nil), // 15: conversations.ReplyMessageData (*ReplyMessage)(nil), // 15: conversations.ReplyMessage
(*MessageInfo)(nil), // 16: conversations.MessageInfo (*ReplyMessageData)(nil), // 16: conversations.ReplyMessageData
(*MediaContent)(nil), // 17: conversations.MediaContent (*MessageInfo)(nil), // 17: conversations.MessageInfo
(*Dimensions)(nil), // 18: conversations.Dimensions (*MediaContent)(nil), // 18: conversations.MediaContent
(*MessageContent)(nil), // 19: conversations.MessageContent (*Dimensions)(nil), // 19: conversations.Dimensions
(*MsgType)(nil), // 20: conversations.MsgType (*MessageContent)(nil), // 20: conversations.MessageContent
(*MessageStatus)(nil), // 21: conversations.MessageStatus (*MsgType)(nil), // 21: conversations.MsgType
(*Conversation)(nil), // 22: conversations.Conversation (*MessageStatus)(nil), // 22: conversations.MessageStatus
(*Participant)(nil), // 23: conversations.Participant (*Conversation)(nil), // 23: conversations.Conversation
(*SmallInfo)(nil), // 24: conversations.SmallInfo (*Participant)(nil), // 24: conversations.Participant
(*LatestMessage)(nil), // 25: conversations.LatestMessage (*SmallInfo)(nil), // 25: conversations.SmallInfo
(*LatestMessageStatus)(nil), // 26: conversations.LatestMessageStatus (*LatestMessage)(nil), // 26: conversations.LatestMessage
(*Muted)(nil), // 27: conversations.Muted (*LatestMessageStatus)(nil), // 27: conversations.LatestMessageStatus
(*CustomEmojiData_Inner)(nil), // 28: conversations.CustomEmojiData.Inner (*Muted)(nil), // 28: conversations.Muted
(*CustomEmojiData_Inner_ImageData)(nil), // 29: conversations.CustomEmojiData.Inner.ImageData (*CustomEmojiData_Inner)(nil), // 29: conversations.CustomEmojiData.Inner
(*CustomEmojiData_Inner_WrappedImageData)(nil), // 30: conversations.CustomEmojiData.Inner.WrappedImageData (*CustomEmojiData_Inner_ImageData)(nil), // 30: conversations.CustomEmojiData.Inner.ImageData
(*CustomEmojiData_Inner_WrappedImageData_ImageData)(nil), // 31: conversations.CustomEmojiData.Inner.WrappedImageData.ImageData (*CustomEmojiData_Inner_WrappedImageData)(nil), // 31: conversations.CustomEmojiData.Inner.WrappedImageData
(*CustomEmojiData_Inner_WrappedImageData_ImageData)(nil), // 32: conversations.CustomEmojiData.Inner.WrappedImageData.ImageData
} }
var file_conversations_proto_depIdxs = []int32{ var file_conversations_proto_depIdxs = []int32{
7, // 0: conversations.Contact.number:type_name -> conversations.ContactNumber 8, // 0: conversations.Contact.number:type_name -> conversations.ContactNumber
20, // 1: conversations.Message.msgType:type_name -> conversations.MsgType 21, // 1: conversations.Message.msgType:type_name -> conversations.MsgType
21, // 2: conversations.Message.messageStatus:type_name -> conversations.MessageStatus 22, // 2: conversations.Message.messageStatus:type_name -> conversations.MessageStatus
16, // 3: conversations.Message.messageInfo:type_name -> conversations.MessageInfo 17, // 3: conversations.Message.messageInfo:type_name -> conversations.MessageInfo
9, // 4: conversations.Message.reactions:type_name -> conversations.ReactionEntry 10, // 4: conversations.Message.reactions:type_name -> conversations.ReactionEntry
14, // 5: conversations.Message.replyMessage:type_name -> conversations.ReplyMessage 15, // 5: conversations.Message.replyMessage:type_name -> conversations.ReplyMessage
11, // 6: conversations.ReactionEntry.data:type_name -> conversations.ReactionData 12, // 6: conversations.ReactionEntry.data:type_name -> conversations.ReactionData
28, // 7: conversations.CustomEmojiData.innerData:type_name -> conversations.CustomEmojiData.Inner 29, // 7: conversations.CustomEmojiData.innerData:type_name -> conversations.CustomEmojiData.Inner
0, // 8: conversations.ReactionData.type:type_name -> conversations.EmojiType 0, // 8: conversations.ReactionData.type:type_name -> conversations.EmojiType
10, // 9: conversations.ReactionData.customEmoji:type_name -> conversations.CustomEmojiData 11, // 9: conversations.ReactionData.customEmoji:type_name -> conversations.CustomEmojiData
13, // 10: conversations.EmojiMeta.emojiMetaData:type_name -> conversations.EmojiMetaData 14, // 10: conversations.EmojiMeta.emojiMetaData:type_name -> conversations.EmojiMetaData
15, // 11: conversations.ReplyMessage.replyMessageData:type_name -> conversations.ReplyMessageData 16, // 11: conversations.ReplyMessage.replyMessageData:type_name -> conversations.ReplyMessageData
19, // 12: conversations.MessageInfo.messageContent:type_name -> conversations.MessageContent 20, // 12: conversations.MessageInfo.messageContent:type_name -> conversations.MessageContent
17, // 13: conversations.MessageInfo.mediaContent:type_name -> conversations.MediaContent 18, // 13: conversations.MessageInfo.mediaContent:type_name -> conversations.MediaContent
5, // 14: conversations.MediaContent.format:type_name -> conversations.MediaFormats 6, // 14: conversations.MediaContent.format:type_name -> conversations.MediaFormats
18, // 15: conversations.MediaContent.dimensions:type_name -> conversations.Dimensions 19, // 15: conversations.MediaContent.dimensions:type_name -> conversations.Dimensions
3, // 16: conversations.MessageStatus.status:type_name -> conversations.MessageStatusType 4, // 16: conversations.MessageStatus.status:type_name -> conversations.MessageStatusType
25, // 17: conversations.Conversation.latestMessage:type_name -> conversations.LatestMessage 26, // 17: conversations.Conversation.latestMessage:type_name -> conversations.LatestMessage
4, // 18: conversations.Conversation.status:type_name -> conversations.ConversationStatus 5, // 18: conversations.Conversation.status:type_name -> conversations.ConversationStatus
23, // 19: conversations.Conversation.participants:type_name -> conversations.Participant 2, // 19: conversations.Conversation.sendMode:type_name -> conversations.ConversationSendMode
2, // 20: conversations.Conversation.type:type_name -> conversations.ConversationType 24, // 20: conversations.Conversation.participants:type_name -> conversations.Participant
24, // 21: conversations.Participant.ID:type_name -> conversations.SmallInfo 3, // 21: conversations.Conversation.type:type_name -> conversations.ConversationType
27, // 22: conversations.Participant.muted:type_name -> conversations.Muted 25, // 22: conversations.Participant.ID:type_name -> conversations.SmallInfo
1, // 23: conversations.SmallInfo.type:type_name -> conversations.IdentifierType 28, // 23: conversations.Participant.muted:type_name -> conversations.Muted
26, // 24: conversations.LatestMessage.latestMessageStatus:type_name -> conversations.LatestMessageStatus 1, // 24: conversations.SmallInfo.type:type_name -> conversations.IdentifierType
3, // 25: conversations.LatestMessageStatus.status:type_name -> conversations.MessageStatusType 27, // 25: conversations.LatestMessage.latestMessageStatus:type_name -> conversations.LatestMessageStatus
29, // 26: conversations.CustomEmojiData.Inner.first:type_name -> conversations.CustomEmojiData.Inner.ImageData 4, // 26: conversations.LatestMessageStatus.status:type_name -> conversations.MessageStatusType
30, // 27: conversations.CustomEmojiData.Inner.second:type_name -> conversations.CustomEmojiData.Inner.WrappedImageData 30, // 27: conversations.CustomEmojiData.Inner.first:type_name -> conversations.CustomEmojiData.Inner.ImageData
31, // 28: conversations.CustomEmojiData.Inner.WrappedImageData.data:type_name -> conversations.CustomEmojiData.Inner.WrappedImageData.ImageData 31, // 28: conversations.CustomEmojiData.Inner.second:type_name -> conversations.CustomEmojiData.Inner.WrappedImageData
29, // [29:29] is the sub-list for method output_type 32, // 29: conversations.CustomEmojiData.Inner.WrappedImageData.data:type_name -> conversations.CustomEmojiData.Inner.WrappedImageData.ImageData
29, // [29:29] is the sub-list for method input_type 30, // [30:30] is the sub-list for method output_type
29, // [29:29] is the sub-list for extension type_name 30, // [30:30] is the sub-list for method input_type
29, // [29:29] is the sub-list for extension extendee 30, // [30:30] is the sub-list for extension type_name
0, // [0:29] is the sub-list for field type_name 30, // [30:30] is the sub-list for extension extendee
0, // [0:30] is the sub-list for field type_name
} }
func init() { file_conversations_proto_init() } func init() { file_conversations_proto_init() }
@ -3080,7 +3139,7 @@ func file_conversations_proto_init() {
File: protoimpl.DescBuilder{ File: protoimpl.DescBuilder{
GoPackagePath: reflect.TypeOf(x{}).PkgPath(), GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
RawDescriptor: file_conversations_proto_rawDesc, RawDescriptor: file_conversations_proto_rawDesc,
NumEnums: 6, NumEnums: 7,
NumMessages: 26, NumMessages: 26,
NumExtensions: 0, NumExtensions: 0,
NumServices: 0, NumServices: 0,

Binary file not shown.

View file

@ -168,6 +168,7 @@ message Conversation {
bool readOnly = 13; bool readOnly = 13;
string avatarHexColor = 15; string avatarHexColor = 15;
string latestMessageID = 17; string latestMessageID = 17;
ConversationSendMode sendMode = 18;
repeated Participant participants = 20; repeated Participant participants = 20;
repeated string otherParticipants = 21; // participant ids excluding me repeated string otherParticipants = 21; // participant ids excluding me
ConversationType type = 22; ConversationType type = 22;
@ -221,6 +222,12 @@ message Muted {
int64 isMuted = 1; int64 isMuted = 1;
} }
enum ConversationSendMode {
SEND_MODE_AUTO = 0;
SEND_MODE_XMS = 1;
SEND_MODE_XMS_LATCH = 2;
}
enum ConversationType { enum ConversationType {
UNKNOWN_CONVERSATION_TYPE = 0; UNKNOWN_CONVERSATION_TYPE = 0;
SMS = 1; SMS = 1;

View file

@ -774,6 +774,26 @@ func (portal *Portal) handleMessage(source *User, evt *gmproto.Message, raw []by
case gmproto.MessageStatusType_INCOMING_AUTO_DOWNLOADING, gmproto.MessageStatusType_INCOMING_RETRYING_AUTO_DOWNLOAD: case gmproto.MessageStatusType_INCOMING_AUTO_DOWNLOADING, gmproto.MessageStatusType_INCOMING_RETRYING_AUTO_DOWNLOAD:
log.Debug().Msg("Not handling incoming auto-downloading MMS") log.Debug().Msg("Not handling incoming auto-downloading MMS")
return return
case gmproto.MessageStatusType_MESSAGE_STATUS_TOMBSTONE_PROTOCOL_SWITCH_RCS_TO_E2EE, gmproto.MessageStatusType_MESSAGE_STATUS_TOMBSTONE_PROTOCOL_SWITCH_TEXT_TO_E2EE:
if !portal.ForceRCS {
portal.ForceRCS = true
err := portal.Update(ctx)
if err != nil {
log.Warn().Err(err).Msg("Failed to update portal to force RCS")
} else {
log.Debug().Msg("Setting force RCS flag for portal due to E2EE tombstone")
}
}
case gmproto.MessageStatusType_MESSAGE_STATUS_TOMBSTONE_PROTOCOL_SWITCH_E2EE_TO_RCS, gmproto.MessageStatusType_MESSAGE_STATUS_TOMBSTONE_PROTOCOL_SWITCH_E2EE_TO_TEXT:
if portal.ForceRCS {
portal.ForceRCS = false
err := portal.Update(ctx)
if err != nil {
log.Warn().Err(err).Msg("Failed to update portal to unforce RCS")
} else {
log.Debug().Msg("Removing force RCS flag for portal due to non-E2EE tombstone")
}
}
} }
if time.Since(eventTS) > 24*time.Hour { if time.Since(eventTS) > 24*time.Hour {
lastMessage, err := portal.bridge.DB.Message.GetLastInChat(ctx, portal.Key) lastMessage, err := portal.bridge.DB.Message.GetLastInChat(ctx, portal.Key)
@ -1486,6 +1506,14 @@ func (portal *Portal) UpdateMetadata(ctx context.Context, user *User, info *gmpr
portal.Type = info.Type portal.Type = info.Type
update = true update = true
} }
if portal.SendMode != info.SendMode {
portal.zlog.Debug().
Str("old_send_mode", portal.SendMode.String()).
Str("new_send_mode", info.SendMode.String()).
Msg("Conversation send mode changed")
portal.SendMode = info.SendMode
update = true
}
if portal.OutgoingID != info.DefaultOutgoingID { if portal.OutgoingID != info.DefaultOutgoingID {
portal.zlog.Debug(). portal.zlog.Debug().
Str("old_id", portal.OutgoingID). Str("old_id", portal.OutgoingID).
@ -1932,6 +1960,7 @@ func (portal *Portal) uploadMedia(ctx context.Context, intent *appservice.Intent
func (portal *Portal) convertMatrixMessage(ctx context.Context, sender *User, content *event.MessageEventContent, raw map[string]any, txnID string) (*gmproto.SendMessageRequest, error) { func (portal *Portal) convertMatrixMessage(ctx context.Context, sender *User, content *event.MessageEventContent, raw map[string]any, txnID string) (*gmproto.SendMessageRequest, error) {
log := zerolog.Ctx(ctx) log := zerolog.Ctx(ctx)
sim := sender.GetSIM(portal.OutgoingID)
req := &gmproto.SendMessageRequest{ req := &gmproto.SendMessageRequest{
ConversationID: portal.ID, ConversationID: portal.ID,
TmpID: txnID, TmpID: txnID,
@ -1941,7 +1970,7 @@ func (portal *Portal) convertMatrixMessage(ctx context.Context, sender *User, co
TmpID2: txnID, TmpID2: txnID,
ParticipantID: portal.OutgoingID, ParticipantID: portal.OutgoingID,
}, },
SIMPayload: sender.GetSIM(portal.OutgoingID).GetSIMData().GetSIMPayload(), SIMPayload: sim.GetSIMData().GetSIMPayload(),
} }
replyToMXID := content.RelatesTo.GetReplyTo() replyToMXID := content.RelatesTo.GetReplyTo()
@ -1955,7 +1984,12 @@ func (portal *Portal) convertMatrixMessage(ctx context.Context, sender *User, co
req.Reply = &gmproto.ReplyPayload{MessageID: replyToMsg.ID} req.Reply = &gmproto.ReplyPayload{MessageID: replyToMsg.ID}
} }
} }
req.IsRCS = portal.Type == gmproto.ConversationType_RCS req.ForceRCS = portal.Type == gmproto.ConversationType_RCS &&
portal.SendMode == gmproto.ConversationSendMode_SEND_MODE_AUTO &&
portal.ForceRCS
if req.ForceRCS && !sim.GetRCSChats().GetEnabled() {
log.Warn().Msg("Forcing RCS but RCS is disabled on sim")
}
switch content.MsgType { switch content.MsgType {
case event.MsgText, event.MsgEmote, event.MsgNotice: case event.MsgText, event.MsgEmote, event.MsgNotice: