feat: added expirationType and expireTimer to content message and updated message pipeline

this includes sync messages and updating the protobuf, haven't tested closed groups
pull/2660/head
William Grant 2 years ago
parent 0700ac4813
commit ee6607b96a

@ -17,10 +17,12 @@ message Envelope {
}
message TypingMessage {
enum Action {
STARTED = 0;
STOPPED = 1;
}
// @required
required uint64 timestamp = 1;
// @required
@ -42,7 +44,32 @@ message MessageRequestResponse {
optional DataMessage.LokiProfile profile = 3;
}
// TODO Syncing disappearing messages
// message SyncedExpiries {
// message SyncedConversationExpiries {
// message SyncedExpiry {
// // @required
// required string serverHash = 1; // messageHash for desktop and serverHash for iOS
// // @required
// required uint64 expirationTimestamp = 2; // this is only used for deleteAfterRead
// }
// // @required
// required string syncTarget = 1; // the conversationID those expiries are related to
// repeated SyncedExpiry expiries = 2;
// }
// repeated SyncedConversationExpiries conversationExpiries = 1;
// }
message Content {
enum ExpirationType {
DELETE_AFTER_SEND = 1;
DELETE_AFTER_READ = 2;
}
optional DataMessage dataMessage = 1;
optional CallMessage callMessage = 3;
optional ReceiptMessage receiptMessage = 5;
@ -51,6 +78,10 @@ message Content {
optional DataExtractionNotification dataExtractionNotification = 8;
optional Unsend unsendMessage = 9;
optional MessageRequestResponse messageRequestResponse = 10;
optional ExpirationType expirationType = 11;
optional uint32 expirationTimer = 12;
optional uint64 lastDisappearingMessageChangeTimestamp = 13;
// optional SyncedExpiries syncedExpiries = 14;
}
message KeyPair {
@ -130,7 +161,7 @@ message DataMessage {
message ClosedGroupControlMessage {
enum Type {
NEW = 1; // publicKey, name, encryptionKeyPair, members, admins, expireTimer
NEW = 1; // publicKey, name, encryptionKeyPair, members, admins, expirationTimer
ENCRYPTION_KEY_PAIR = 3; // publicKey, wrappers
NAME_CHANGE = 4; // name
MEMBERS_ADDED = 5; // members
@ -156,7 +187,8 @@ message DataMessage {
repeated bytes members = 5;
repeated bytes admins = 6;
repeated KeyPairWrapper wrappers = 7;
optional uint32 expireTimer = 8;
// TODO Make sure rename doesn't break anything
optional uint32 expirationTimer = 8;
}
@ -164,6 +196,7 @@ message DataMessage {
repeated AttachmentPointer attachments = 2;
optional GroupContext group = 3;
optional uint32 flags = 4;
// TODO this will be removed 2 weeks after the release
optional uint32 expireTimer = 5;
optional bytes profileKey = 6;
optional uint64 timestamp = 7;

@ -41,6 +41,7 @@ import { getSodiumRenderer } from '../session/crypto';
import { encryptProfile } from '../util/crypto/profileEncrypter';
import { uploadFileToFsWithOnionV4 } from '../session/apis/file_server_api/FileServerApi';
import { DisappearingMessageConversationType } from '../util/expiringMessages';
import { getNowWithNetworkOffset } from '../session/apis/snode_api/SNodeAPI';
export const getCompleteUrlForV2ConvoId = async (convoId: string) => {
if (convoId.match(openGroupV2ConversationIdRegex)) {
@ -356,10 +357,19 @@ export async function setDisappearingMessagesByConvoId(
return;
}
const providedChangeTimestamp = getNowWithNetworkOffset();
if (!expirationType || expirationType === 'off' || !seconds || seconds <= 0) {
await conversation.updateExpireTimer('off');
await conversation.updateExpireTimer({
providedExpirationType: 'off',
providedChangeTimestamp,
});
} else {
await conversation.updateExpireTimer(expirationType, seconds);
await conversation.updateExpireTimer({
providedExpirationType: expirationType,
providedExpireTimer: seconds,
providedChangeTimestamp,
});
}
}

@ -78,7 +78,6 @@ import {
ConversationAttributes,
ConversationNotificationSetting,
ConversationTypeEnum,
DisappearingMessageConversationType,
fillConvoAttributesWithDefaults,
} from './conversationAttributes';
import { SogsBlinding } from '../session/apis/open_group_api/sogsv3/sogsBlinding';
@ -97,6 +96,7 @@ import {
import { sogsV3FetchPreviewAndSaveIt } from '../session/apis/open_group_api/sogsv3/sogsV3FetchFile';
import { Reaction } from '../types/Reaction';
import { Reactions } from '../util/reactions';
import { DisappearingMessageConversationType } from '../util/expiringMessages';
export class ConversationModel extends Backbone.Model<ConversationAttributes> {
public updateLastMessage: () => any;
@ -1016,31 +1016,34 @@ export class ConversationModel extends Backbone.Model<ConversationAttributes> {
}
}
public async updateExpireTimer(
providedExpirationType: DisappearingMessageConversationType,
providedExpireTimer?: number,
providedSource?: string,
receivedAt?: number, // is set if it comes from outside
options: {
fromSync?: boolean;
} = {},
shouldCommit = true
): Promise<void> {
public async updateExpireTimer({
providedExpirationType,
providedExpireTimer,
providedChangeTimestamp,
providedSource,
receivedAt, // is set if it comes from outside
fromSync,
shouldCommit = true,
}: {
providedExpirationType: DisappearingMessageConversationType;
providedExpireTimer?: number;
providedChangeTimestamp?: number;
providedSource?: string;
receivedAt?: number; // is set if it comes from outside
fromSync?: boolean;
shouldCommit?: boolean;
}): Promise<void> {
let expirationType = providedExpirationType;
let expireTimer = providedExpireTimer;
let source = providedSource;
defaults(options, { fromSync: false });
defaults({ fromSync }, { fromSync: false });
if (!expirationType) {
if (!expirationType || !expireTimer) {
expirationType = 'off';
expireTimer = 0;
}
if (!expireTimer) {
expireTimer = 0;
}
if (this.get('expireTimer') === expireTimer || (!expireTimer && !this.get('expireTimer'))) {
return;
}
@ -1057,21 +1060,29 @@ export class ConversationModel extends Backbone.Model<ConversationAttributes> {
source = source || UserUtils.getOurPubKeyStrFromCache();
// When we add a disappearing messages notification to the conversation, we want it
// to be above the message that initiated that change, hence the subtraction.
// TODO Will we use this for lastDisappearingMessageChangeTimestamp
// to be above the message that initiated that change, hence the subtraction.
const timestamp = (receivedAt || Date.now()) - 1;
this.set({ expirationType, expireTimer });
this.set({
expirationType,
expireTimer,
lastDisappearingMessageChangeTimestamp: providedChangeTimestamp || undefined,
});
const lastDisappearingMessageChangeTimestamp = providedChangeTimestamp || 0;
// TODO Update for the new types of Disappearing Messages
const commonAttributes = {
flags: SignalService.DataMessage.Flags.EXPIRATION_TIMER_UPDATE,
expirationTimerUpdate: {
expirationType,
expireTimer,
lastDisappearingMessageChangeTimestamp,
source,
fromSync: options.fromSync,
fromSync,
},
expireTimer: 0,
// TODO do we need this?
// expirationType,
// expireTimer,
};
let message: MessageModel | undefined;
@ -1082,6 +1093,7 @@ export class ConversationModel extends Backbone.Model<ConversationAttributes> {
sent_at: timestamp,
});
} else {
// TODO do we still want to handle expiration in incoming messages?
message = await this.addSingleIncomingMessage({
...commonAttributes,
// Even though this isn't reflected to the user, we want to place the last seen
@ -1106,23 +1118,28 @@ export class ConversationModel extends Backbone.Model<ConversationAttributes> {
return;
}
// TODO Update for the new types of Disappearing Messages
const expireUpdate = {
identifier: message.id,
timestamp,
expireTimer: expireTimer ? expireTimer : (null as number | null),
expirationType,
expireTimer,
lastDisappearingMessageChangeTimestamp,
};
if (this.isMe()) {
// TODO Check that the args are correct
const expirationTimerMessage = new ExpirationTimerUpdateMessage(expireUpdate);
return message.sendSyncMessageOnly(expirationTimerMessage);
}
if (this.isPrivate()) {
// TODO Check that the args are correct
const expirationTimerMessage = new ExpirationTimerUpdateMessage(expireUpdate);
const pubkey = new PubKey(this.get('id'));
await getMessageQueue().sendToPubKey(pubkey, expirationTimerMessage);
} else {
// TODO Check that the args are correct
// Cannot be an open group
window?.log?.warn('TODO: Expiration update for closed groups are to be updated');
const expireUpdateForGroup = {
...expireUpdate,

@ -1028,20 +1028,25 @@ export class MessageModel extends Backbone.Model<MessageAttributes> {
this.set({
sent_to: [UserUtils.getOurPubKeyStrFromCache()],
sent: true,
// NOTE if disappearing message is deleteAfterRead then we don't use this
expirationStartTimestamp: now,
});
await this.commit();
const data = dataMessage instanceof DataMessage ? dataMessage.dataProto() : dataMessage;
await this.sendSyncMessage(data, now);
await this.sendSyncMessage(dataMessage, now);
}
public async sendSyncMessage(dataMessage: SignalService.DataMessage, sentTimestamp: number) {
public async sendSyncMessage(
data: DataMessage | SignalService.DataMessage,
sentTimestamp: number
) {
if (this.get('synced') || this.get('sentSync')) {
return;
}
const dataMessage = data instanceof DataMessage ? data.dataProto() : data;
// if this message needs to be synced
if (
dataMessage.body?.length ||
@ -1052,10 +1057,12 @@ export class MessageModel extends Backbone.Model<MessageAttributes> {
if (!conversation) {
throw new Error('Cannot trigger syncMessage with unknown convo.');
}
const syncMessage = buildSyncMessage(this.id, dataMessage, conversation.id, sentTimestamp);
const syncMessage = buildSyncMessage(this.id, data, conversation.id, sentTimestamp);
await getMessageQueue().sendSyncMessage(syncMessage);
}
this.set({ sentSync: true });
this.set({
sentSync: true,
});
await this.commit();
}

@ -35,6 +35,7 @@ export function createSwarmMessageSentFromUs(args: {
const messageData: MessageAttributesOptionals = {
...getSharedAttributesForSwarmMessage(args),
...getSharedAttributesForOutgoingMessage(),
// TODO need to update this for delete after read
expirationStartTimestamp: Math.min(args.sentAt, Date.now()),
};

@ -21,11 +21,12 @@ export interface MessageAttributes {
reacts?: ReactionList;
reactsIndex?: number;
body?: string;
// NOTE this is used for the logic
expirationType?: DisappearingMessageType;
expireTimer: number;
expirationStartTimestamp: number;
expires_at?: number;
// TODO are having both variables redundant?
// NOTE this is used for conversation setting
expirationTimerUpdate?: {
expirationType: DisappearingMessageType;
expireTimer: number;

@ -32,6 +32,7 @@ import { MessageModel } from '../models/message';
import { updateConfirmModal } from '../state/ducks/modalDialog';
import { perfEnd, perfStart } from '../session/utils/Performance';
import { ConversationTypeEnum } from '../models/conversationAttributes';
import { getNowWithNetworkOffset } from '../session/apis/snode_api/SNodeAPI';
export const distributingClosedGroupEncryptionKeyPairs = new Map<string, ECKeyPair>();
@ -240,7 +241,8 @@ export async function handleNewClosedGroup(
return;
}
const groupConvo = getConversationController().get(groupId);
const expireTimer = groupUpdate.expireTimer;
// TODO Rename to expirationTimer
const expireTimer = groupUpdate.expirationTimer;
if (groupConvo) {
// if we did not left this group, just add the keypair we got if not already there
@ -256,12 +258,13 @@ export async function handleNewClosedGroup(
);
// TODO This is only applicable for old closed groups - will be removed in future
await groupConvo.updateExpireTimer(
expireTimer === 0 ? 'off' : 'deleteAfterSend',
expireTimer,
sender,
Date.now()
);
await groupConvo.updateExpireTimer({
providedExpirationType: expireTimer === 0 ? 'off' : 'deleteAfterSend',
providedExpireTimer: expireTimer,
providedChangeTimestamp: getNowWithNetworkOffset(),
providedSource: sender,
receivedAt: Date.now(),
});
if (isKeyPairAlreadyHere) {
window.log.info('Dropping already saved keypair for group', groupId);
@ -322,12 +325,13 @@ export async function handleNewClosedGroup(
// envelope.timestamp and Date.now(). And we need to listen to those (some might even remove us)
convo.set('lastJoinedTimestamp', envelopeTimestamp);
// TODO This is only applicable for old closed groups - will be removed in future
await convo.updateExpireTimer(
expireTimer === 0 ? 'off' : 'deleteAfterSend',
expireTimer,
sender,
envelopeTimestamp
);
await convo.updateExpireTimer({
providedExpirationType: expireTimer === 0 ? 'off' : 'deleteAfterSend',
providedExpireTimer: expireTimer,
providedChangeTimestamp: getNowWithNetworkOffset(),
providedSource: sender,
receivedAt: envelopeTimestamp,
});
convo.updateLastMessage();
await convo.commit();

@ -398,13 +398,25 @@ export async function innerHandleSwarmContentMessage(
if (content.dataMessage.profileKey && content.dataMessage.profileKey.length === 0) {
content.dataMessage.profileKey = null;
}
perfStart(`handleSwarmDataMessage-${envelope.id}`);
let expireUpdate = null;
if (content.expirationType && content.expirationTimer) {
expireUpdate = {
expirationType: content.expirationType,
expirationTimer: content.expirationTimer,
};
}
await handleSwarmDataMessage(
envelope,
sentAtTimestamp,
content.dataMessage as SignalService.DataMessage,
messageHash,
senderConversationModel
senderConversationModel,
expireUpdate
);
perfEnd(`handleSwarmDataMessage-${envelope.id}`, 'handleSwarmDataMessage');
return;

@ -152,7 +152,8 @@ export async function handleSwarmDataMessage(
sentAtTimestamp: number,
rawDataMessage: SignalService.DataMessage,
messageHash: string,
senderConversationModel: ConversationModel
senderConversationModel: ConversationModel,
expireUpdate: any
): Promise<void> {
window.log.info('handleSwarmDataMessage');
@ -246,7 +247,8 @@ export async function handleSwarmDataMessage(
sentAtTimestamp,
cleanDataMessage,
convoToAddMessageTo,
() => removeFromCache(envelope)
() => removeFromCache(envelope),
expireUpdate
);
}
@ -293,7 +295,8 @@ async function handleSwarmMessage(
sentAt: number,
rawDataMessage: SignalService.DataMessage,
convoToAddMessageTo: ConversationModel,
confirm: () => void
confirm: () => void,
expireUpdate?: any
): Promise<void> {
if (!rawDataMessage || !msgModel) {
window?.log?.warn('Invalid data passed to handleSwarmMessage.');
@ -310,6 +313,7 @@ async function handleSwarmMessage(
sender: msgModel.get('source'),
you: isUsFromCache(msgModel.get('source')),
});
if (
convoToAddMessageTo.isPrivate() &&
msgModel.get('unread') &&
@ -322,6 +326,7 @@ async function handleSwarmMessage(
confirm();
return;
}
const isDuplicate = await isSwarmMessageDuplicate({
source: msgModel.get('source'),
sentAt,
@ -339,7 +344,8 @@ async function handleSwarmMessage(
toRegularMessage(rawDataMessage),
confirm,
msgModel.get('source'),
messageHash
messageHash,
expireUpdate
);
});
}

@ -1,7 +1,7 @@
import { queueAttachmentDownloads } from './attachments';
import { Quote } from './types';
import _ from 'lodash';
import _, { isEmpty } from 'lodash';
import { getConversationController } from '../session/conversations';
import { ConversationModel } from '../models/conversation';
import { MessageModel, sliceQuoteText } from '../models/message';
@ -14,11 +14,10 @@ import { MessageDirection } from '../models/messageType';
import { LinkPreviews } from '../util/linkPreviews';
import { GoogleChrome } from '../util';
import { appendFetchAvatarAndProfileJob } from './userProfileImageUpdates';
import {
ConversationTypeEnum,
DisappearingMessageConversationType,
} from '../models/conversationAttributes';
import { ConversationTypeEnum } from '../models/conversationAttributes';
import { getUsBlindedInThatServer } from '../session/apis/open_group_api/sogsv3/knownBlindedkeys';
import { DisappearingMessageConversationType } from '../util/expiringMessages';
import { getNowWithNetworkOffset } from '../session/apis/snode_api/SNodeAPI';
function contentTypeSupported(type: string): boolean {
const Chrome = GoogleChrome;
@ -185,7 +184,7 @@ export type RegularMessageType = Pick<
| 'reaction'
| 'profile'
| 'profileKey'
// TODO Add expirationType and other new props
// TODO Will be removed 2 weeks after release
| 'expireTimer'
> & { isRegularMessage: true };
@ -317,23 +316,26 @@ async function handleExpirationTimerUpdateNoCommit(
expirationType: DisappearingMessageConversationType,
expireTimer: number
) {
const providedChangeTimestamp = getNowWithNetworkOffset();
message.set({
expirationTimerUpdate: {
source,
expirationType: expirationType !== 'off' ? expirationType : null,
expireTimer,
lastDisappearingMessageChangeTimestamp: providedChangeTimestamp,
},
unread: 0, // mark the message as read.
});
conversation.set({ expirationType, expireTimer });
await conversation.updateExpireTimer(
expirationType,
expireTimer,
source,
message.get('received_at'),
{},
false
);
await conversation.updateExpireTimer({
providedExpirationType: expirationType,
providedExpireTimer: expireTimer,
providedChangeTimestamp,
providedSource: source,
receivedAt: message.get('received_at'),
shouldCommit: false,
});
}
export async function handleMessageJob(
@ -342,7 +344,8 @@ export async function handleMessageJob(
regularDataMessage: RegularMessageType,
confirm: () => void,
source: string,
messageHash: string
messageHash: string,
expireUpdate?: any
) {
window?.log?.info(
`Starting handleMessageJob for message ${messageModel.idForLogging()}, ${messageModel.get(
@ -356,11 +359,13 @@ export async function handleMessageJob(
);
try {
messageModel.set({ flags: regularDataMessage.flags });
// TODO update to handle the new disappearing message props
if (messageModel.isExpirationTimerUpdate()) {
// TODO Account for expirationType and lastDisappearingMessageChangeTimestamp
const { expireTimer } = regularDataMessage;
// TODO remove 2 weeks after release
if (messageModel.isExpirationTimerUpdate() || !isEmpty(expireUpdate)) {
const { expireTimer: oldExpireTimer } = regularDataMessage;
const expirationType = expireUpdate.expirationType;
const expireTimer = expireUpdate.expireTimer || oldExpireTimer;
// TODO compare types and change timestamps
// const oldTypeValue = conversation.get('expirationType');
const oldTimerValue = conversation.get('expireTimer');
if (expireTimer === oldTimerValue) {
@ -370,11 +375,12 @@ export async function handleMessageJob(
);
return;
}
await handleExpirationTimerUpdateNoCommit(
conversation,
messageModel,
source,
'deleteAfterSend',
expirationType,
expireTimer
);
} else {

@ -28,11 +28,8 @@ import { ClosedGroupNewMessage } from '../messages/outgoing/controlMessage/group
import { ClosedGroupRemovedMembersMessage } from '../messages/outgoing/controlMessage/group/ClosedGroupRemovedMembersMessage';
import { getSwarmPollingInstance } from '../apis/snode_api';
import { getNowWithNetworkOffset } from '../apis/snode_api/SNodeAPI';
import {
ConversationAttributes,
ConversationTypeEnum,
DisappearingMessageConversationType,
} from '../../models/conversationAttributes';
import { ConversationAttributes, ConversationTypeEnum } from '../../models/conversationAttributes';
import { DisappearingMessageConversationType } from '../../util/expiringMessages';
export type GroupInfo = {
id: string;
@ -270,16 +267,16 @@ export async function updateOrCreateClosedGroup(details: GroupInfo) {
if (expireTimer === undefined || typeof expireTimer !== 'number') {
return;
}
// Todo Update here
await conversation.updateExpireTimer(
expirationType || 'deleteAfterSend',
expireTimer,
UserUtils.getOurPubKeyStrFromCache(),
Date.now(),
{
fromSync: true,
}
);
await conversation.updateExpireTimer({
// TODO clean up 2 weeks after release
providedExpirationType: expirationType || 'deleteAfterSend',
providedExpireTimer: expireTimer,
providedChangeTimestamp: getNowWithNetworkOffset(),
providedSource: UserUtils.getOurPubKeyStrFromCache(),
receivedAt: Date.now(),
fromSync: true,
});
}
export async function leaveClosedGroup(groupId: string) {

@ -1,5 +1,6 @@
import { DataMessage } from '..';
import { SignalService } from '../../../../protobuf';
import { DisappearingMessageType } from '../../../../util/expiringMessages';
import { PubKey } from '../../../types';
import { StringUtils } from '../../../utils';
import { MessageParams } from '../Message';
@ -7,23 +8,44 @@ import { MessageParams } from '../Message';
interface ExpirationTimerUpdateMessageParams extends MessageParams {
groupId?: string | PubKey;
syncTarget?: string | PubKey;
expirationType: DisappearingMessageType | null;
expireTimer: number | null;
lastDisappearingMessageChangeTimestamp: number | null;
}
// Note the old disappearing messages used a data message for the expiration time.
// The new ones use properties on the Content Message
// We will remove support for the old one 2 weeks after the release
export class ExpirationTimerUpdateMessage extends DataMessage {
public readonly groupId?: PubKey;
public readonly syncTarget?: string;
public readonly expirationType: DisappearingMessageType | null;
public readonly expireTimer: number | null;
public readonly lastDisappearingMessageChangeTimestamp: number | null;
constructor(params: ExpirationTimerUpdateMessageParams) {
super({ timestamp: params.timestamp, identifier: params.identifier });
this.expirationType = params.expirationType;
this.expireTimer = params.expireTimer;
this.lastDisappearingMessageChangeTimestamp = params.lastDisappearingMessageChangeTimestamp;
const { groupId, syncTarget } = params;
this.groupId = groupId ? PubKey.cast(groupId) : undefined;
this.syncTarget = syncTarget ? PubKey.cast(syncTarget).key : undefined;
}
public contentProto(): SignalService.Content {
return new SignalService.Content({
dataMessage: this.dataProto(),
expirationType:
this.expirationType === 'deleteAfterSend'
? SignalService.Content.ExpirationType.DELETE_AFTER_SEND
: SignalService.Content.ExpirationType.DELETE_AFTER_READ,
expirationTimer: this.expireTimer,
lastDisappearingMessageChangeTimestamp: this.lastDisappearingMessageChangeTimestamp,
});
}
public dataProto(): SignalService.DataMessage {
const data = new SignalService.DataMessage();
@ -46,6 +68,7 @@ export class ExpirationTimerUpdateMessage extends DataMessage {
data.syncTarget = this.syncTarget;
}
// TODO remove 2 weeks after the release
if (this.expireTimer) {
data.expireTimer = this.expireTimer;
}

@ -63,7 +63,7 @@ export class ClosedGroupNewMessage extends ClosedGroupMessage {
dataMessage.closedGroupControlMessage.admins = this.admins.map(fromHexToArray);
dataMessage.closedGroupControlMessage.members = this.members.map(fromHexToArray);
dataMessage.closedGroupControlMessage.expireTimer = this.expireTimer;
dataMessage.closedGroupControlMessage.expirationTimer = this.expireTimer;
try {
dataMessage.closedGroupControlMessage.encryptionKeyPair = new SignalService.KeyPair();
dataMessage.closedGroupControlMessage.encryptionKeyPair.privateKey = new Uint8Array(

@ -26,6 +26,8 @@ import { DURATION } from '../constants';
import { UnsendMessage } from '../messages/outgoing/controlMessage/UnsendMessage';
import { MessageRequestResponse } from '../messages/outgoing/controlMessage/MessageRequestResponse';
import { PubKey } from '../types';
import { DataMessage } from '../messages/outgoing';
import { DisappearingMessageType } from '../../util/expiringMessages';
const ITEM_ID_LAST_SYNC_TIMESTAMP = 'lastSyncedTimestamp';
@ -294,16 +296,18 @@ const buildSyncVisibleMessage = (
const buildSyncExpireTimerMessage = (
identifier: string,
dataMessage: SignalService.DataMessage,
expirationType: DisappearingMessageType,
expireTimer: number,
lastDisappearingMessageChangeTimestamp: number | null,
timestamp: number,
syncTarget: string
) => {
const expireTimer = dataMessage.expireTimer;
return new ExpirationTimerUpdateMessage({
identifier,
timestamp,
expirationType: expirationType || null,
expireTimer,
lastDisappearingMessageChangeTimestamp: lastDisappearingMessageChangeTimestamp || null,
syncTarget,
});
};
@ -317,24 +321,48 @@ export type SyncMessageType =
export const buildSyncMessage = (
identifier: string,
dataMessage: SignalService.DataMessage,
data: DataMessage | SignalService.DataMessage,
syncTarget: string,
sentTimestamp: number
): VisibleMessage | ExpirationTimerUpdateMessage => {
if (
(dataMessage as any).constructor.name !== 'DataMessage' &&
!(dataMessage instanceof SignalService.DataMessage)
(data as any).constructor.name !== 'DataMessage' &&
!(data instanceof SignalService.DataMessage)
) {
window?.log?.warn('buildSyncMessage with something else than a DataMessage');
}
// TODO Remove DataMessage expireTimer 2 weeks after the release
const dataMessage = data instanceof DataMessage ? data.dataProto() : data;
const contentMessage = data instanceof DataMessage ? data.contentProto() : null;
const expirationType =
contentMessage?.expirationType === SignalService.Content.ExpirationType.DELETE_AFTER_SEND
? 'deleteAfterSend'
: contentMessage?.expirationType === SignalService.Content.ExpirationType.DELETE_AFTER_READ
? 'deleteAfterRead'
: null;
const expireTimer = contentMessage?.expirationTimer || dataMessage.expireTimer;
const lastDisappearingMessageChangeTimestamp = contentMessage?.lastDisappearingMessageChangeTimestamp
? Number(contentMessage?.lastDisappearingMessageChangeTimestamp)
: null;
if (!sentTimestamp || !_.isNumber(sentTimestamp)) {
throw new Error('Tried to build a sync message without a sentTimestamp');
}
// don't include our profileKey on syncing message. This is to be done by a ConfigurationMessage now
const timestamp = _.toNumber(sentTimestamp);
if (dataMessage.flags === SignalService.DataMessage.Flags.EXPIRATION_TIMER_UPDATE) {
return buildSyncExpireTimerMessage(identifier, dataMessage, timestamp, syncTarget);
if (
contentMessage?.expirationType &&
dataMessage.flags === SignalService.DataMessage.Flags.EXPIRATION_TIMER_UPDATE
) {
return buildSyncExpireTimerMessage(
identifier,
expirationType,
expireTimer,
lastDisappearingMessageChangeTimestamp,
timestamp,
syncTarget
);
}
return buildSyncVisibleMessage(identifier, dataMessage, timestamp, syncTarget);
};

Loading…
Cancel
Save