From 81841f4a822881cace1a8e527d23843a9292faaf Mon Sep 17 00:00:00 2001 From: Tulir Asokan Date: Tue, 3 Sep 2024 20:22:42 +0300 Subject: [PATCH] dbmeta: add support for expiration timer versions --- pkg/msgconv/from-matrix.go | 4 +++ pkg/msgconv/from-signal.go | 18 ++++++++-- pkg/signalid/dbmeta.go | 3 +- pkg/signalmeow/protobuf/SignalService.pb.go | 36 +++++++++++++------ pkg/signalmeow/protobuf/SignalService.pb.raw | Bin 19040 -> 19136 bytes pkg/signalmeow/protobuf/SignalService.proto | 24 +++++++------ pkg/signalmeow/protobuf/update-protos.sh | 4 +-- pkg/signalmeow/provisioning.go | 3 +- 8 files changed, 65 insertions(+), 27 deletions(-) diff --git a/pkg/msgconv/from-matrix.go b/pkg/msgconv/from-matrix.go index 2a282fc1..cb938e7a 100644 --- a/pkg/msgconv/from-matrix.go +++ b/pkg/msgconv/from-matrix.go @@ -78,6 +78,10 @@ func (mc *MessageConverter) ToSignal( } if portal.Disappear.Timer > 0 { dm.ExpireTimer = proto.Uint32(uint32(portal.Disappear.Timer.Seconds())) + timerVersion := portal.Metadata.(*signalid.PortalMetadata).ExpirationTimerVersion + if timerVersion > 0 { + dm.ExpireTimerVersion = &timerVersion + } } if content.MsgType == event.MsgEmote && !relaybotFormatted { content.Body = "/me " + content.Body diff --git a/pkg/msgconv/from-signal.go b/pkg/msgconv/from-signal.go index 4b09e80b..20dd39b9 100644 --- a/pkg/msgconv/from-signal.go +++ b/pkg/msgconv/from-signal.go @@ -85,7 +85,7 @@ func (mc *MessageConverter) ToMatrix( Parts: make([]*bridgev2.ConvertedMessagePart, 0, calculateLength(dm)), } if dm.GetFlags()&uint32(signalpb.DataMessage_EXPIRATION_TIMER_UPDATE) != 0 { - cm.Parts = append(cm.Parts, mc.ConvertDisappearingTimerChangeToMatrix(ctx, dm.GetExpireTimer(), true)) + cm.Parts = append(cm.Parts, mc.ConvertDisappearingTimerChangeToMatrix(ctx, dm.GetExpireTimer(), dm.ExpireTimerVersion, true)) // Don't allow any other parts in a disappearing timer change message return cm } @@ -151,7 +151,7 @@ func (mc *MessageConverter) ToMatrix( return cm } -func (mc *MessageConverter) ConvertDisappearingTimerChangeToMatrix(ctx context.Context, timer uint32, updatePortal bool) *bridgev2.ConvertedMessagePart { +func (mc *MessageConverter) ConvertDisappearingTimerChangeToMatrix(ctx context.Context, timer uint32, timerVersion *uint32, updatePortal bool) *bridgev2.ConvertedMessagePart { part := &bridgev2.ConvertedMessagePart{ Type: event.EventMessage, Content: &event.MessageEventContent{ @@ -164,12 +164,26 @@ func (mc *MessageConverter) ConvertDisappearingTimerChangeToMatrix(ctx context.C } if updatePortal { portal := getPortal(ctx) + portalMeta := portal.Metadata.(*signalid.PortalMetadata) + if timerVersion != nil && portalMeta.ExpirationTimerVersion > *timerVersion { + zerolog.Ctx(ctx).Warn(). + Uint32("current_version", portalMeta.ExpirationTimerVersion). + Uint32("new_version", *timerVersion). + Msg("Ignoring outdated disappearing timer change") + part.Content.Body += " (change ignored)" + return part + } portal.Disappear.Timer = time.Duration(timer) * time.Second if timer == 0 { portal.Disappear.Type = "" } else { portal.Disappear.Type = database.DisappearingTypeAfterRead } + if timerVersion != nil { + portalMeta.ExpirationTimerVersion = *timerVersion + } else { + portalMeta.ExpirationTimerVersion = 1 + } err := portal.Save(ctx) if err != nil { zerolog.Ctx(ctx).Err(err).Msg("Failed to update portal disappearing timer in database") diff --git a/pkg/signalid/dbmeta.go b/pkg/signalid/dbmeta.go index 5a96b07d..f3811af0 100644 --- a/pkg/signalid/dbmeta.go +++ b/pkg/signalid/dbmeta.go @@ -21,7 +21,8 @@ import ( ) type PortalMetadata struct { - Revision uint32 `json:"revision,omitempty"` + Revision uint32 `json:"revision,omitempty"` + ExpirationTimerVersion uint32 `json:"expiration_timer_version,omitempty"` } type MessageMetadata struct { diff --git a/pkg/signalmeow/protobuf/SignalService.pb.go b/pkg/signalmeow/protobuf/SignalService.pb.go index f382b8bc..f524c90c 100644 --- a/pkg/signalmeow/protobuf/SignalService.pb.go +++ b/pkg/signalmeow/protobuf/SignalService.pb.go @@ -2163,6 +2163,7 @@ type DataMessage struct { GroupV2 *GroupContextV2 `protobuf:"bytes,15,opt,name=groupV2" json:"groupV2,omitempty"` Flags *uint32 `protobuf:"varint,4,opt,name=flags" json:"flags,omitempty"` ExpireTimer *uint32 `protobuf:"varint,5,opt,name=expireTimer" json:"expireTimer,omitempty"` + ExpireTimerVersion *uint32 `protobuf:"varint,23,opt,name=expireTimerVersion" json:"expireTimerVersion,omitempty"` ProfileKey []byte `protobuf:"bytes,6,opt,name=profileKey" json:"profileKey,omitempty"` Timestamp *uint64 `protobuf:"varint,7,opt,name=timestamp" json:"timestamp,omitempty"` Quote *DataMessage_Quote `protobuf:"bytes,8,opt,name=quote" json:"quote,omitempty"` @@ -2247,6 +2248,13 @@ func (x *DataMessage) GetExpireTimer() uint32 { return 0 } +func (x *DataMessage) GetExpireTimerVersion() uint32 { + if x != nil && x.ExpireTimerVersion != nil { + return *x.ExpireTimerVersion + } + return 0 +} + func (x *DataMessage) GetProfileKey() []byte { if x != nil { return x.ProfileKey @@ -3464,16 +3472,17 @@ type ContactDetails struct { sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields - Number *string `protobuf:"bytes,1,opt,name=number" json:"number,omitempty"` - Aci *string `protobuf:"bytes,9,opt,name=aci" json:"aci,omitempty"` - Name *string `protobuf:"bytes,2,opt,name=name" json:"name,omitempty"` - Avatar *ContactDetails_Avatar `protobuf:"bytes,3,opt,name=avatar" json:"avatar,omitempty"` - Color *string `protobuf:"bytes,4,opt,name=color" json:"color,omitempty"` - Verified *Verified `protobuf:"bytes,5,opt,name=verified" json:"verified,omitempty"` - ProfileKey []byte `protobuf:"bytes,6,opt,name=profileKey" json:"profileKey,omitempty"` - ExpireTimer *uint32 `protobuf:"varint,8,opt,name=expireTimer" json:"expireTimer,omitempty"` - InboxPosition *uint32 `protobuf:"varint,10,opt,name=inboxPosition" json:"inboxPosition,omitempty"` - Archived *bool `protobuf:"varint,11,opt,name=archived" json:"archived,omitempty"` + Number *string `protobuf:"bytes,1,opt,name=number" json:"number,omitempty"` + Aci *string `protobuf:"bytes,9,opt,name=aci" json:"aci,omitempty"` + Name *string `protobuf:"bytes,2,opt,name=name" json:"name,omitempty"` + Avatar *ContactDetails_Avatar `protobuf:"bytes,3,opt,name=avatar" json:"avatar,omitempty"` + Color *string `protobuf:"bytes,4,opt,name=color" json:"color,omitempty"` + Verified *Verified `protobuf:"bytes,5,opt,name=verified" json:"verified,omitempty"` + ProfileKey []byte `protobuf:"bytes,6,opt,name=profileKey" json:"profileKey,omitempty"` + ExpireTimer *uint32 `protobuf:"varint,8,opt,name=expireTimer" json:"expireTimer,omitempty"` + ExpireTimerVersion *uint32 `protobuf:"varint,12,opt,name=expireTimerVersion" json:"expireTimerVersion,omitempty"` + InboxPosition *uint32 `protobuf:"varint,10,opt,name=inboxPosition" json:"inboxPosition,omitempty"` + Archived *bool `protobuf:"varint,11,opt,name=archived" json:"archived,omitempty"` } func (x *ContactDetails) Reset() { @@ -3564,6 +3573,13 @@ func (x *ContactDetails) GetExpireTimer() uint32 { return 0 } +func (x *ContactDetails) GetExpireTimerVersion() uint32 { + if x != nil && x.ExpireTimerVersion != nil { + return *x.ExpireTimerVersion + } + return 0 +} + func (x *ContactDetails) GetInboxPosition() uint32 { if x != nil && x.InboxPosition != nil { return *x.InboxPosition diff --git a/pkg/signalmeow/protobuf/SignalService.pb.raw b/pkg/signalmeow/protobuf/SignalService.pb.raw index 2ca3d164ba21b6b1ed160d649962a9e9d2aaeb9c..bc9a4d57969c32e0c0d280ef3808c2a3c4c70bbb 100644 GIT binary patch delta 128 zcmaDbh4H{t#tp}~7++03&UHgyk4q@Eq9C&b37uWoK~k!Hl9mj|cbIj%=o02{F{IsgCw delta 32 qcmV+*0N?+>l>y+C0kFmj0lJgN3fQyH3*tBdrL(d`8v(QZMZ*ODbPo{# diff --git a/pkg/signalmeow/protobuf/SignalService.proto b/pkg/signalmeow/protobuf/SignalService.proto index 1e2332ba..c516a1ba 100644 --- a/pkg/signalmeow/protobuf/SignalService.proto +++ b/pkg/signalmeow/protobuf/SignalService.proto @@ -332,6 +332,7 @@ message DataMessage { optional GroupContextV2 groupV2 = 15; optional uint32 flags = 4; optional uint32 expireTimer = 5; + optional uint32 expireTimerVersion = 23; optional bytes profileKey = 6; optional uint64 timestamp = 7; optional Quote quote = 8; @@ -793,17 +794,18 @@ message ContactDetails { optional uint32 length = 2; } - optional string number = 1; - optional string aci = 9; - optional string name = 2; - optional Avatar avatar = 3; - optional string color = 4; - optional Verified verified = 5; - optional bytes profileKey = 6; - reserved /*blocked*/ 7; - optional uint32 expireTimer = 8; - optional uint32 inboxPosition = 10; - optional bool archived = 11; + optional string number = 1; + optional string aci = 9; + optional string name = 2; + optional Avatar avatar = 3; + optional string color = 4; + optional Verified verified = 5; + optional bytes profileKey = 6; + reserved /*blocked*/ 7; + optional uint32 expireTimer = 8; + optional uint32 expireTimerVersion = 12; + optional uint32 inboxPosition = 10; + optional bool archived = 11; } message GroupDetails { diff --git a/pkg/signalmeow/protobuf/update-protos.sh b/pkg/signalmeow/protobuf/update-protos.sh index 9735ecf5..43790f4c 100755 --- a/pkg/signalmeow/protobuf/update-protos.sh +++ b/pkg/signalmeow/protobuf/update-protos.sh @@ -1,8 +1,8 @@ #!/bin/bash set -euo pipefail -ANDROID_GIT_REVISION=${1:-68c7ce582378b5f752e5971007b2c203e81cecbd} -DESKTOP_GIT_REVISION=${1:-faea93e5cea24893a8976dc6329faa751f59df5c} +ANDROID_GIT_REVISION=${1:-ab7bdc3c03ecda2d746fd56cfd747f56feab7b17} +DESKTOP_GIT_REVISION=${1:-1898e964adcfc8a9096b4aaebff895813fb4f35c} update_proto() { case "$1" in diff --git a/pkg/signalmeow/provisioning.go b/pkg/signalmeow/provisioning.go index 160bdec5..5c09457d 100644 --- a/pkg/signalmeow/provisioning.go +++ b/pkg/signalmeow/provisioning.go @@ -331,7 +331,8 @@ func continueProvisioning(ctx context.Context, ws *websocket.Conn, provisioningC } var signalCapabilities = map[string]any{ - "deleteSync": true, + "deleteSync": true, + "versionedExpirationTimer": true, } var signalCapabilitiesBody = exerrors.Must(json.Marshal(signalCapabilities))