Only set force RCS flag if chat has had e2ee tombstone
This commit is contained in:
parent
56bfc105ed
commit
2c373db8fc
10 changed files with 217 additions and 109 deletions
|
@ -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,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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,
|
||||||
|
|
3
database/upgrades/10-send-mode.sql
Normal file
3
database/upgrades/10-send-mode.sql
Normal 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;
|
|
@ -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.
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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.
|
@ -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;
|
||||||
|
|
38
portal.go
38
portal.go
|
@ -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:
|
||||||
|
|
Loading…
Reference in a new issue