diff --git a/ts/models/conversation.ts b/ts/models/conversation.ts index 901066523..0c423c3b5 100644 --- a/ts/models/conversation.ts +++ b/ts/models/conversation.ts @@ -1830,8 +1830,9 @@ export class ConversationModel extends Backbone.Model { identifier: id, timestamp: sentAt, attachments, - expirationType: message.getExpirationType(), + expirationType: message.getExpirationType() ?? 'unknown', expireTimer: message.getExpireTimer(), + lastDisappearingMessageChangeTimestamp: this.getLastDisappearingMessageChangeTimestamp(), preview: preview ? [preview] : [], quote, lokiProfile: UserUtils.getOurProfile(), diff --git a/ts/session/disappearing_messages/index.ts b/ts/session/disappearing_messages/index.ts index 3136d9ff0..f88d7253d 100644 --- a/ts/session/disappearing_messages/index.ts +++ b/ts/session/disappearing_messages/index.ts @@ -291,12 +291,14 @@ async function checkForExpireUpdateInContentMessage( couldBeLegacyContentMessage, dataMessage as SignalService.DataMessage ); + const hasExpirationUpdateFlags = + dataMessage.flags === SignalService.DataMessage.Flags.EXPIRATION_TIMER_UPDATE; + const isLegacyConversationSettingMessage = isDisappearingMessagesV2Released ? (isLegacyDataMessage || (couldBeLegacyContentMessage && !content.lastDisappearingMessageChangeTimestamp)) && - dataMessage.flags === SignalService.DataMessage.Flags.EXPIRATION_TIMER_UPDATE - : couldBeLegacyContentMessage && - dataMessage.flags === SignalService.DataMessage.Flags.EXPIRATION_TIMER_UPDATE; + hasExpirationUpdateFlags + : couldBeLegacyContentMessage && hasExpirationUpdateFlags; const expirationTimer = isLegacyDataMessage ? Number(dataMessage.expireTimer) @@ -315,15 +317,17 @@ async function checkForExpireUpdateInContentMessage( // NOTE if we are checking an outgoing content message then the conversation's lastDisappearingMessageChangeTimestamp has just been set to match the content message so it can't be outdated if equal if ( - convoToUpdate.getLastDisappearingMessageChangeTimestamp() && - lastDisappearingMessageChangeTimestamp && - ((isOutgoing && + (lastDisappearingMessageChangeTimestamp && + convoToUpdate.getLastDisappearingMessageChangeTimestamp() && convoToUpdate.getLastDisappearingMessageChangeTimestamp() > lastDisappearingMessageChangeTimestamp) || - (!isOutgoing && - convoToUpdate.getLastDisappearingMessageChangeTimestamp() > - lastDisappearingMessageChangeTimestamp)) + (hasExpirationUpdateFlags && + convoToUpdate.getLastDisappearingMessageChangeTimestamp() === + lastDisappearingMessageChangeTimestamp) ) { + // Note: when we receive incoming messages, they will all have the same lastDisappearingMessageChangeTimestamp corresponding to when the latest change was made. + // Those incoming messages are *not* outdated, but a change asking for the same change would be outdated. + window.log.debug( `[checkForExpireUpdateInContentMessage] This is an outdated ${ isOutgoing ? 'outgoing' : 'incoming' diff --git a/ts/session/group/closed-group.ts b/ts/session/group/closed-group.ts index a13a82486..ecf810fbe 100644 --- a/ts/session/group/closed-group.ts +++ b/ts/session/group/closed-group.ts @@ -444,6 +444,9 @@ async function generateAndSendNewEncryptionKeyPair( groupId: toHex(groupId), timestamp: GetNetworkTime.getNowWithNetworkOffset(), encryptedKeyPairs: wrappers, + expirationType: null, + expireTimer: null, + lastDisappearingMessageChangeTimestamp: null, }); distributingClosedGroupEncryptionKeyPairs.set(toHex(groupId), newKeyPair); diff --git a/ts/session/messages/outgoing/ExpirableMessage.ts b/ts/session/messages/outgoing/ExpirableMessage.ts index 02377ba85..d8277d05c 100644 --- a/ts/session/messages/outgoing/ExpirableMessage.ts +++ b/ts/session/messages/outgoing/ExpirableMessage.ts @@ -5,14 +5,16 @@ import { ContentMessage } from './ContentMessage'; import { MessageParams } from './Message'; export interface ExpirableMessageParams extends MessageParams { - expirationType?: DisappearingMessageType; - expireTimer?: number; + expirationType: DisappearingMessageType | null; + expireTimer: number | null; + lastDisappearingMessageChangeTimestamp: number | null; } export class ExpirableMessage extends ContentMessage { - public readonly expirationType?: DisappearingMessageType; + public readonly expirationType: DisappearingMessageType | null; /** in seconds, 0 means no expiration */ - public readonly expireTimer?: number; + public readonly expireTimer: number | null; + public readonly lastDisappearingMessageChangeTimestamp: number | null; constructor(params: ExpirableMessageParams) { super({ @@ -21,6 +23,7 @@ export class ExpirableMessage extends ContentMessage { }); this.expirationType = params.expirationType; this.expireTimer = params.expireTimer; + this.lastDisappearingMessageChangeTimestamp = params.lastDisappearingMessageChangeTimestamp; } public contentProto(): SignalService.Content { @@ -35,6 +38,7 @@ export class ExpirableMessage extends ContentMessage { ? SignalService.Content.ExpirationType.UNKNOWN : undefined, expirationTimer: this.expireTimer && this.expireTimer > -1 ? this.expireTimer : undefined, + lastDisappearingMessageChangeTimestamp: this.lastDisappearingMessageChangeTimestamp, }); } @@ -51,7 +55,7 @@ export class ExpirableMessage extends ContentMessage { } public getDisappearingMessageType(): DisappearingMessageType | undefined { - return this.expirationType; + return this.expirationType || undefined; } public ttl(): number { diff --git a/ts/session/messages/outgoing/controlMessage/CallMessage.ts b/ts/session/messages/outgoing/controlMessage/CallMessage.ts index b0c2609d9..cfc54426f 100644 --- a/ts/session/messages/outgoing/controlMessage/CallMessage.ts +++ b/ts/session/messages/outgoing/controlMessage/CallMessage.ts @@ -1,8 +1,8 @@ -import { SignalService } from '../../../../protobuf'; -import { MessageParams } from '../Message'; import { ContentMessage } from '..'; +import { SignalService } from '../../../../protobuf'; import { signalservice } from '../../../../protobuf/compiled'; import { TTL_DEFAULT } from '../../../constants'; +import { MessageParams } from '../Message'; interface CallMessageParams extends MessageParams { type: SignalService.CallMessage.Type; @@ -20,7 +20,7 @@ export class CallMessage extends ContentMessage { public readonly uuid: string; constructor(params: CallMessageParams) { - super({ timestamp: params.timestamp, identifier: params.identifier }); + super(params); this.type = params.type; this.sdpMLineIndexes = params.sdpMLineIndexes; this.sdpMids = params.sdpMids; diff --git a/ts/session/messages/outgoing/controlMessage/ExpirationTimerUpdateMessage.ts b/ts/session/messages/outgoing/controlMessage/ExpirationTimerUpdateMessage.ts index 791e685ab..00aff1505 100644 --- a/ts/session/messages/outgoing/controlMessage/ExpirationTimerUpdateMessage.ts +++ b/ts/session/messages/outgoing/controlMessage/ExpirationTimerUpdateMessage.ts @@ -7,7 +7,6 @@ import { ExpirableMessageParams } from '../ExpirableMessage'; interface ExpirationTimerUpdateMessageParams extends ExpirableMessageParams { groupId?: string | PubKey; syncTarget?: string | PubKey; - lastDisappearingMessageChangeTimestamp?: number; } // NOTE legacy messages used a data message for the expireTimer. @@ -16,7 +15,6 @@ interface ExpirationTimerUpdateMessageParams extends ExpirableMessageParams { export class ExpirationTimerUpdateMessage extends DataMessage { public readonly groupId?: PubKey; public readonly syncTarget?: string; - public readonly lastDisappearingMessageChangeTimestamp?: number; constructor(params: ExpirationTimerUpdateMessageParams) { super({ @@ -24,10 +22,9 @@ export class ExpirationTimerUpdateMessage extends DataMessage { identifier: params.identifier, expirationType: params.expirationType, expireTimer: params.expireTimer, + lastDisappearingMessageChangeTimestamp: params.lastDisappearingMessageChangeTimestamp, }); - this.lastDisappearingMessageChangeTimestamp = params.lastDisappearingMessageChangeTimestamp; - const { groupId } = params; this.groupId = groupId ? PubKey.cast(groupId) : undefined; this.syncTarget = params.syncTarget ? PubKey.cast(params.syncTarget).key : undefined; diff --git a/ts/session/messages/outgoing/controlMessage/group/ClosedGroupAddedMembersMessage.ts b/ts/session/messages/outgoing/controlMessage/group/ClosedGroupAddedMembersMessage.ts index c8a43a777..c96937226 100644 --- a/ts/session/messages/outgoing/controlMessage/group/ClosedGroupAddedMembersMessage.ts +++ b/ts/session/messages/outgoing/controlMessage/group/ClosedGroupAddedMembersMessage.ts @@ -10,11 +10,7 @@ export class ClosedGroupAddedMembersMessage extends ClosedGroupMessage { private readonly addedMembers: Array; constructor(params: ClosedGroupAddedMembersMessageParams) { - super({ - timestamp: params.timestamp, - identifier: params.identifier, - groupId: params.groupId, - }); + super(params); this.addedMembers = params.addedMembers; if (!this.addedMembers?.length) { throw new Error('addedMembers cannot be empty'); diff --git a/ts/session/messages/outgoing/controlMessage/group/ClosedGroupEncryptionPairMessage.ts b/ts/session/messages/outgoing/controlMessage/group/ClosedGroupEncryptionPairMessage.ts index 9976015d5..326a66718 100644 --- a/ts/session/messages/outgoing/controlMessage/group/ClosedGroupEncryptionPairMessage.ts +++ b/ts/session/messages/outgoing/controlMessage/group/ClosedGroupEncryptionPairMessage.ts @@ -11,11 +11,7 @@ export class ClosedGroupEncryptionPairMessage extends ClosedGroupMessage { >; constructor(params: ClosedGroupEncryptionPairMessageParams) { - super({ - timestamp: params.timestamp, - identifier: params.identifier, - groupId: params.groupId, - }); + super(params); this.encryptedKeyPairs = params.encryptedKeyPairs; if (this.encryptedKeyPairs.length === 0) { throw new Error('EncryptedKeyPairs cannot be empty'); diff --git a/ts/session/messages/outgoing/controlMessage/group/ClosedGroupMessage.ts b/ts/session/messages/outgoing/controlMessage/group/ClosedGroupMessage.ts index a021b8063..72f1c89b4 100644 --- a/ts/session/messages/outgoing/controlMessage/group/ClosedGroupMessage.ts +++ b/ts/session/messages/outgoing/controlMessage/group/ClosedGroupMessage.ts @@ -15,6 +15,7 @@ export abstract class ClosedGroupMessage extends ExpirableMessage { identifier: params.identifier, expirationType: params.expirationType, expireTimer: params.expireTimer, + lastDisappearingMessageChangeTimestamp: params.lastDisappearingMessageChangeTimestamp, }); this.groupId = PubKey.cast(params.groupId); diff --git a/ts/session/messages/outgoing/controlMessage/group/ClosedGroupNameChangeMessage.ts b/ts/session/messages/outgoing/controlMessage/group/ClosedGroupNameChangeMessage.ts index 71a390c67..f145c4661 100644 --- a/ts/session/messages/outgoing/controlMessage/group/ClosedGroupNameChangeMessage.ts +++ b/ts/session/messages/outgoing/controlMessage/group/ClosedGroupNameChangeMessage.ts @@ -9,11 +9,7 @@ export class ClosedGroupNameChangeMessage extends ClosedGroupMessage { private readonly name: string; constructor(params: ClosedGroupNameChangeMessageParams) { - super({ - timestamp: params.timestamp, - identifier: params.identifier, - groupId: params.groupId, - }); + super(params); this.name = params.name; if (this.name.length === 0) { throw new Error('name cannot be empty'); diff --git a/ts/session/messages/outgoing/controlMessage/group/ClosedGroupNewMessage.ts b/ts/session/messages/outgoing/controlMessage/group/ClosedGroupNewMessage.ts index 0b133954e..500fca379 100644 --- a/ts/session/messages/outgoing/controlMessage/group/ClosedGroupNewMessage.ts +++ b/ts/session/messages/outgoing/controlMessage/group/ClosedGroupNewMessage.ts @@ -1,7 +1,7 @@ import { SignalService } from '../../../../../protobuf'; -import { ClosedGroupMessage, ClosedGroupMessageParams } from './ClosedGroupMessage'; -import { fromHexToArray } from '../../../../utils/String'; import { ECKeyPair } from '../../../../../receiver/keypairs'; +import { fromHexToArray } from '../../../../utils/String'; +import { ClosedGroupMessage, ClosedGroupMessageParams } from './ClosedGroupMessage'; export interface ClosedGroupNewMessageParams extends ClosedGroupMessageParams { name: string; @@ -22,6 +22,7 @@ export class ClosedGroupNewMessage extends ClosedGroupMessage { timestamp: params.timestamp, identifier: params.identifier, groupId: params.groupId, + lastDisappearingMessageChangeTimestamp: params.lastDisappearingMessageChangeTimestamp, expirationType: params.expirationType, expireTimer: params.expireTimer, }); diff --git a/ts/session/messages/outgoing/controlMessage/group/ClosedGroupRemovedMembersMessage.ts b/ts/session/messages/outgoing/controlMessage/group/ClosedGroupRemovedMembersMessage.ts index 019d832bc..d00b83ae5 100644 --- a/ts/session/messages/outgoing/controlMessage/group/ClosedGroupRemovedMembersMessage.ts +++ b/ts/session/messages/outgoing/controlMessage/group/ClosedGroupRemovedMembersMessage.ts @@ -14,6 +14,9 @@ export class ClosedGroupRemovedMembersMessage extends ClosedGroupMessage { timestamp: params.timestamp, identifier: params.identifier, groupId: params.groupId, + lastDisappearingMessageChangeTimestamp: params.lastDisappearingMessageChangeTimestamp, + expirationType: params.expirationType, + expireTimer: params.expireTimer, }); this.removedMembers = params.removedMembers; if (!this.removedMembers?.length) { diff --git a/ts/session/messages/outgoing/visibleMessage/ClosedGroupVisibleMessage.ts b/ts/session/messages/outgoing/visibleMessage/ClosedGroupVisibleMessage.ts index 92fbfd9f9..139829381 100644 --- a/ts/session/messages/outgoing/visibleMessage/ClosedGroupVisibleMessage.ts +++ b/ts/session/messages/outgoing/visibleMessage/ClosedGroupVisibleMessage.ts @@ -7,7 +7,11 @@ import { } from '../controlMessage/group/ClosedGroupMessage'; import { VisibleMessage } from './VisibleMessage'; -interface ClosedGroupVisibleMessageParams extends ClosedGroupMessageParams { +interface ClosedGroupVisibleMessageParams + extends Omit< + ClosedGroupMessageParams, + 'expireTimer' | 'expirationType' | 'lastDisappearingMessageChangeTimestamp' + > { groupId: PubKey; chatMessage: VisibleMessage; } @@ -20,8 +24,10 @@ export class ClosedGroupVisibleMessage extends ClosedGroupMessage { timestamp: params.chatMessage.timestamp, identifier: params.identifier ?? params.chatMessage.identifier, groupId: params.groupId, - expirationType: params.expirationType, - expireTimer: params.expireTimer, + expirationType: params.chatMessage.expirationType, + expireTimer: params.chatMessage.expireTimer, + lastDisappearingMessageChangeTimestamp: + params.chatMessage.lastDisappearingMessageChangeTimestamp ?? null, }); this.chatMessage = params.chatMessage; diff --git a/ts/session/messages/outgoing/visibleMessage/GroupInvitationMessage.ts b/ts/session/messages/outgoing/visibleMessage/GroupInvitationMessage.ts index de47d3cbf..9d3e74a5e 100644 --- a/ts/session/messages/outgoing/visibleMessage/GroupInvitationMessage.ts +++ b/ts/session/messages/outgoing/visibleMessage/GroupInvitationMessage.ts @@ -16,6 +16,7 @@ export class GroupInvitationMessage extends VisibleMessage { identifier: params.identifier, expirationType: params.expirationType, expireTimer: params.expireTimer, + lastDisappearingMessageChangeTimestamp: params.lastDisappearingMessageChangeTimestamp, }); this.url = params.url; this.name = params.name; diff --git a/ts/session/messages/outgoing/visibleMessage/OpenGroupVisibleMessage.ts b/ts/session/messages/outgoing/visibleMessage/OpenGroupVisibleMessage.ts index 692445a92..b548774ed 100644 --- a/ts/session/messages/outgoing/visibleMessage/OpenGroupVisibleMessage.ts +++ b/ts/session/messages/outgoing/visibleMessage/OpenGroupVisibleMessage.ts @@ -6,14 +6,19 @@ import { VisibleMessage, VisibleMessageParams } from './VisibleMessage'; // eslint-disable-next-line @typescript-eslint/ban-types export type OpenGroupVisibleMessageParams = Omit< VisibleMessageParams, - 'expirationType' | 'expireTimer' + 'expirationType' | 'expireTimer' | 'lastDisappearingMessageChangeTimestamp' >; export class OpenGroupVisibleMessage extends VisibleMessage { private readonly blocksCommunityMessageRequests: boolean; constructor(params: OpenGroupVisibleMessageParams) { - super(params); + super({ + ...params, + lastDisappearingMessageChangeTimestamp: null, + expirationType: null, + expireTimer: null, + }); // they are the opposite of each others this.blocksCommunityMessageRequests = !Storage.get(SettingsKey.hasBlindedMsgRequestsEnabled); } diff --git a/ts/session/messages/outgoing/visibleMessage/VisibleMessage.ts b/ts/session/messages/outgoing/visibleMessage/VisibleMessage.ts index 2e6c19aab..197e33d4d 100644 --- a/ts/session/messages/outgoing/visibleMessage/VisibleMessage.ts +++ b/ts/session/messages/outgoing/visibleMessage/VisibleMessage.ts @@ -91,6 +91,7 @@ export class VisibleMessage extends ExpirableMessage { identifier: params.identifier, expirationType: params.expirationType, expireTimer: params.expireTimer, + lastDisappearingMessageChangeTimestamp: params.lastDisappearingMessageChangeTimestamp, }); this.attachments = params.attachments; this.body = params.body; diff --git a/ts/session/utils/sync/syncUtils.ts b/ts/session/utils/sync/syncUtils.ts index e8176d1d1..8fa8f6237 100644 --- a/ts/session/utils/sync/syncUtils.ts +++ b/ts/session/utils/sync/syncUtils.ts @@ -332,7 +332,8 @@ const buildSyncVisibleMessage = ( preview, syncTarget, expireTimer: expireUpdate?.expirationTimer || dataMessageExpireTimer, - expirationType: expireUpdate?.expirationType, + expirationType: expireUpdate?.expirationType || null, + lastDisappearingMessageChangeTimestamp: null, }); }; @@ -353,7 +354,7 @@ const buildSyncExpireTimerMessage = ( timestamp, expirationType, expireTimer, - lastDisappearingMessageChangeTimestamp, + lastDisappearingMessageChangeTimestamp: lastDisappearingMessageChangeTimestamp ?? null, syncTarget, }); }; diff --git a/ts/test/session/unit/messages/ChatMessage_test.ts b/ts/test/session/unit/messages/ChatMessage_test.ts index 880f60031..d18d0c525 100644 --- a/ts/test/session/unit/messages/ChatMessage_test.ts +++ b/ts/test/session/unit/messages/ChatMessage_test.ts @@ -11,10 +11,17 @@ import { VisibleMessage, } from '../../../../session/messages/outgoing/visibleMessage/VisibleMessage'; +const sharedNoExpire = { + expirationType: null, + expireTimer: null, + lastDisappearingMessageChangeTimestamp: null, +}; + describe('VisibleMessage', () => { it('can create empty message with just a timestamp', () => { const message = new VisibleMessage({ timestamp: Date.now(), + ...sharedNoExpire, }); const plainText = message.plainTextBuffer(); const decoded = SignalService.Content.decode(plainText); @@ -26,6 +33,7 @@ describe('VisibleMessage', () => { const message = new VisibleMessage({ timestamp: Date.now(), body: 'body', + ...sharedNoExpire, }); const plainText = message.plainTextBuffer(); const decoded = SignalService.Content.decode(plainText); @@ -35,6 +43,7 @@ describe('VisibleMessage', () => { it('can create a disappear after read message', () => { const message = new VisibleMessage({ timestamp: Date.now(), + ...sharedNoExpire, expirationType: 'deleteAfterRead', expireTimer: 300, }); @@ -53,6 +62,7 @@ describe('VisibleMessage', () => { it('can create a disappear after send message', () => { const message = new VisibleMessage({ timestamp: Date.now(), + ...sharedNoExpire, expirationType: 'deleteAfterSend', expireTimer: 60, }); @@ -79,6 +89,7 @@ describe('VisibleMessage', () => { const message = new VisibleMessage({ timestamp: Date.now(), lokiProfile, + ...sharedNoExpire, }); const plainText = message.plainTextBuffer(); const decoded = SignalService.Content.decode(plainText); @@ -98,6 +109,7 @@ describe('VisibleMessage', () => { const message = new VisibleMessage({ timestamp: Date.now(), quote, + ...sharedNoExpire, }); const plainText = message.plainTextBuffer(); const decoded = SignalService.Content.decode(plainText); @@ -115,6 +127,7 @@ describe('VisibleMessage', () => { const message = new VisibleMessage({ timestamp: Date.now(), preview: previews, + ...sharedNoExpire, }); const plainText = message.plainTextBuffer(); const decoded = SignalService.Content.decode(plainText); @@ -139,6 +152,7 @@ describe('VisibleMessage', () => { const message = new VisibleMessage({ timestamp: Date.now(), attachments, + ...sharedNoExpire, }); const plainText = message.plainTextBuffer(); const decoded = SignalService.Content.decode(plainText); @@ -153,6 +167,7 @@ describe('VisibleMessage', () => { it('correct ttl', () => { const message = new VisibleMessage({ timestamp: Date.now(), + ...sharedNoExpire, }); expect(message.ttl()).to.equal(Constants.TTL_DEFAULT.CONTENT_MESSAGE); }); @@ -160,7 +175,9 @@ describe('VisibleMessage', () => { it('has an identifier', () => { const message = new VisibleMessage({ timestamp: Date.now(), + ...sharedNoExpire, }); + expect(message.identifier).to.not.equal(null, 'identifier cannot be null'); expect(message.identifier).to.not.equal(undefined, 'identifier cannot be undefined'); }); diff --git a/ts/test/session/unit/messages/GroupInvitationMessage_test.ts b/ts/test/session/unit/messages/GroupInvitationMessage_test.ts index 591c84398..f142f4913 100644 --- a/ts/test/session/unit/messages/GroupInvitationMessage_test.ts +++ b/ts/test/session/unit/messages/GroupInvitationMessage_test.ts @@ -16,6 +16,9 @@ describe('GroupInvitationMessage', () => { timestamp, url, name, + expirationType: null, + expireTimer: null, + lastDisappearingMessageChangeTimestamp: null, }); }); diff --git a/ts/test/session/unit/messages/closed_groups/ClosedGroupChatMessage_test.ts b/ts/test/session/unit/messages/closed_groups/ClosedGroupChatMessage_test.ts index 8e0cfa84c..4b1132dd6 100644 --- a/ts/test/session/unit/messages/closed_groups/ClosedGroupChatMessage_test.ts +++ b/ts/test/session/unit/messages/closed_groups/ClosedGroupChatMessage_test.ts @@ -18,11 +18,17 @@ describe('ClosedGroupVisibleMessage', () => { const chatMessage = new VisibleMessage({ timestamp, body: 'body', + expirationType: null, + expireTimer: null, + lastDisappearingMessageChangeTimestamp: null, }); const message = new ClosedGroupVisibleMessage({ groupId, timestamp, chatMessage, + expirationType: null, + expireTimer: null, + lastDisappearingMessageChangeTimestamp: null, }); const plainText = message.plainTextBuffer(); const decoded = SignalService.Content.decode(plainText); @@ -48,11 +54,17 @@ describe('ClosedGroupVisibleMessage', () => { const timestamp = Date.now(); const chatMessage = new VisibleMessage({ timestamp, + expirationType: null, + expireTimer: null, + lastDisappearingMessageChangeTimestamp: null, }); const message = new ClosedGroupVisibleMessage({ groupId, timestamp, chatMessage, + expirationType: null, + expireTimer: null, + lastDisappearingMessageChangeTimestamp: null, }); expect(message.ttl()).to.equal(Constants.TTL_DEFAULT.CONTENT_MESSAGE); }); @@ -61,11 +73,17 @@ describe('ClosedGroupVisibleMessage', () => { const timestamp = Date.now(); const chatMessage = new VisibleMessage({ timestamp, + expirationType: null, + expireTimer: null, + lastDisappearingMessageChangeTimestamp: null, }); const message = new ClosedGroupVisibleMessage({ groupId, timestamp, chatMessage, + expirationType: null, + expireTimer: null, + lastDisappearingMessageChangeTimestamp: null, }); expect(message.identifier).to.not.equal(null, 'identifier cannot be null'); expect(message.identifier).to.not.equal(undefined, 'identifier cannot be undefined'); @@ -77,12 +95,18 @@ describe('ClosedGroupVisibleMessage', () => { timestamp, body: 'body', identifier: 'chatMessage', + expirationType: null, + expireTimer: null, + lastDisappearingMessageChangeTimestamp: null, }); const message = new ClosedGroupVisibleMessage({ groupId, timestamp, chatMessage, identifier: 'closedGroupMessage', + expirationType: null, + expireTimer: null, + lastDisappearingMessageChangeTimestamp: null, }); expect(message.identifier).to.be.equal('closedGroupMessage'); }); @@ -93,11 +117,17 @@ describe('ClosedGroupVisibleMessage', () => { timestamp, body: 'body', identifier: 'chatMessage', + expirationType: null, + expireTimer: null, + lastDisappearingMessageChangeTimestamp: null, }); const message = new ClosedGroupVisibleMessage({ groupId, timestamp, chatMessage, + expirationType: null, + expireTimer: null, + lastDisappearingMessageChangeTimestamp: null, }); expect(message.identifier).to.be.equal('chatMessage'); }); diff --git a/ts/test/session/unit/utils/Messages_test.ts b/ts/test/session/unit/utils/Messages_test.ts index 8023a90d2..15c2a816d 100644 --- a/ts/test/session/unit/utils/Messages_test.ts +++ b/ts/test/session/unit/utils/Messages_test.ts @@ -29,6 +29,12 @@ chai.use(chaiAsPromised as any); const { expect } = chai; +const sharedNoExpire = { + expireTimer: null, + expirationType: null, + lastDisappearingMessageChangeTimestamp: null, +}; + describe('Message Utils', () => { afterEach(() => { Sinon.restore(); @@ -111,6 +117,7 @@ describe('Message Utils', () => { groupId, timestamp: Date.now(), chatMessage, + ...sharedNoExpire, }); const rawMessage = await MessageUtils.toRawMessage( @@ -144,6 +151,7 @@ describe('Message Utils', () => { admins: [member], groupId: TestUtils.generateFakePubKey().key, keypair: TestUtils.generateFakeECKeyPair(), + ...sharedNoExpire, expireTimer: 0, }); const rawMessage = await MessageUtils.toRawMessage(device, msg, SnodeNamespaces.UserMessages); @@ -157,6 +165,7 @@ describe('Message Utils', () => { timestamp: Date.now(), name: 'df', groupId: TestUtils.generateFakePubKey().key, + ...sharedNoExpire, }); const rawMessage = await MessageUtils.toRawMessage(device, msg, SnodeNamespaces.UserMessages); expect(rawMessage.encryption).to.equal(SignalService.Envelope.Type.CLOSED_GROUP_MESSAGE); @@ -169,6 +178,7 @@ describe('Message Utils', () => { timestamp: Date.now(), addedMembers: [TestUtils.generateFakePubKey().key], groupId: TestUtils.generateFakePubKey().key, + ...sharedNoExpire, }); const rawMessage = await MessageUtils.toRawMessage(device, msg, SnodeNamespaces.UserMessages); expect(rawMessage.encryption).to.equal(SignalService.Envelope.Type.CLOSED_GROUP_MESSAGE); @@ -181,6 +191,7 @@ describe('Message Utils', () => { timestamp: Date.now(), removedMembers: [TestUtils.generateFakePubKey().key], groupId: TestUtils.generateFakePubKey().key, + ...sharedNoExpire, }); const rawMessage = await MessageUtils.toRawMessage(device, msg, SnodeNamespaces.UserMessages); expect(rawMessage.encryption).to.equal(SignalService.Envelope.Type.CLOSED_GROUP_MESSAGE); @@ -202,6 +213,7 @@ describe('Message Utils', () => { timestamp: Date.now(), groupId: TestUtils.generateFakePubKey().key, encryptedKeyPairs: fakeWrappers, + ...sharedNoExpire, }); const rawMessage = await MessageUtils.toRawMessage(device, msg, SnodeNamespaces.UserMessages); expect(rawMessage.encryption).to.equal(SignalService.Envelope.Type.CLOSED_GROUP_MESSAGE); @@ -223,6 +235,7 @@ describe('Message Utils', () => { timestamp: Date.now(), groupId: TestUtils.generateFakePubKey().key, encryptedKeyPairs: fakeWrappers, + ...sharedNoExpire, }); const rawMessage = await MessageUtils.toRawMessage(device, msg, SnodeNamespaces.UserMessages); expect(rawMessage.encryption).to.equal(SignalService.Envelope.Type.SESSION_MESSAGE); diff --git a/ts/test/test-utils/utils/message.ts b/ts/test/test-utils/utils/message.ts index 5b1f2e14f..143201bd7 100644 --- a/ts/test/test-utils/utils/message.ts +++ b/ts/test/test-utils/utils/message.ts @@ -33,8 +33,9 @@ export function generateVisibleMessage({ timestamp: timestamp || Date.now(), attachments: undefined, quote: undefined, - expirationType: undefined, - expireTimer: undefined, + expirationType: null, + expireTimer: null, + lastDisappearingMessageChangeTimestamp: null, lokiProfile: undefined, preview: undefined, }); @@ -95,6 +96,9 @@ export function generateClosedGroupMessage( groupId: groupId ? PubKey.cast(groupId) : generateFakePubKey(), timestamp: timestamp || Date.now(), chatMessage: generateVisibleMessage(), + expirationType: null, + expireTimer: null, + lastDisappearingMessageChangeTimestamp: null, }); } @@ -153,10 +157,10 @@ export function generateDisappearingVisibleMessage({ return new ExpirationTimerUpdateMessage({ identifier: identifier ?? uuid(), timestamp: timestamp || Date.now(), - expirationType: expirationTimerUpdate.expirationType, + expirationType: expirationTimerUpdate.expirationType || null, expireTimer: expirationTimerUpdate.expireTimer, lastDisappearingMessageChangeTimestamp: - expirationTimerUpdate.lastDisappearingMessageChangeTimestamp, + expirationTimerUpdate.lastDisappearingMessageChangeTimestamp || null, }); } @@ -166,10 +170,11 @@ export function generateDisappearingVisibleMessage({ timestamp: timestamp || Date.now(), attachments: undefined, quote: undefined, - expirationType, - expireTimer, + expirationType: expirationType ?? null, + expireTimer: expireTimer ?? null, lokiProfile: undefined, preview: undefined, + lastDisappearingMessageChangeTimestamp: null, }); }