From 615ae1ccf79cf30f873c68d0f97fb3152493db51 Mon Sep 17 00:00:00 2001 From: Scott Nonnenberg Date: Fri, 2 Jul 2021 11:34:17 -0700 Subject: [PATCH] Refactor SendMessage.ts to named parameters --- ts/background.ts | 6 +- ts/groups.ts | 48 ++- ts/models/conversations.ts | 132 +++--- ts/models/messages.ts | 90 +++-- ts/services/calling.ts | 10 +- ts/textsecure/OutgoingMessage.ts | 4 +- ts/textsecure/SendMessage.ts | 670 +++++++++++++++++-------------- ts/util/sendReadReceiptsFor.ts | 12 +- ts/util/sendToGroup.ts | 38 +- 9 files changed, 540 insertions(+), 470 deletions(-) diff --git a/ts/background.ts b/ts/background.ts index 6306d048a42d..6c86bfb0aa6c 100644 --- a/ts/background.ts +++ b/ts/background.ts @@ -181,12 +181,12 @@ export async function startApp(): Promise { } = await window.ConversationController.prepareForSend(c.get('id')); // eslint-disable-next-line no-await-in-loop await wrap( - window.textsecure.messaging.sendDeliveryReceipt( + window.textsecure.messaging.sendDeliveryReceipt({ e164, uuid, timestamps, - sendOptions - ) + options: sendOptions, + }) ); } catch (error) { window.log.error( diff --git a/ts/groups.ts b/ts/groups.ts index 8408bd6279e8..ace72e65d144 100644 --- a/ts/groups.ts +++ b/ts/groups.ts @@ -1298,8 +1298,8 @@ export async function modifyGroupV2({ const { ContentHint } = Proto.UnidentifiedSenderMessage.Message; const promise = handleMessageSend( - window.Signal.Util.sendToGroup( - { + window.Signal.Util.sendToGroup({ + groupSendOptions: { groupV2: conversation.getGroupV2Info({ groupChange: typedArrayToArrayBuffer(groupChangeBuffer), includePendingMembers: true, @@ -1309,9 +1309,9 @@ export async function modifyGroupV2({ profileKey, }, conversation, - ContentHint.DEFAULT, - sendOptions - ) + contentHint: ContentHint.DEFAULT, + sendOptions, + }) ); // We don't save this message; we just use it to ensure that a sync message is @@ -1676,16 +1676,16 @@ export async function createGroupV2({ conversation, logId: `sendToGroup/${logId}`, send: async () => - window.Signal.Util.sendToGroup( - { + window.Signal.Util.sendToGroup({ + groupSendOptions: { groupV2: groupV2Info, timestamp, profileKey, }, conversation, - ContentHint.DEFAULT, - sendOptions - ), + contentHint: ContentHint.DEFAULT, + sendOptions, + }), timestamp, }); @@ -2207,8 +2207,8 @@ export async function initiateMigrationToGroupV2( logId: `sendToGroup/${logId}`, send: async () => // Minimal message to notify group members about migration - window.Signal.Util.sendToGroup( - { + window.Signal.Util.sendToGroup({ + groupSendOptions: { groupV2: conversation.getGroupV2Info({ includePendingMembers: true, }), @@ -2216,9 +2216,9 @@ export async function initiateMigrationToGroupV2( profileKey: ourProfileKey, }, conversation, - ContentHint.DEFAULT, - sendOptions - ), + contentHint: ContentHint.DEFAULT, + sendOptions, + }), timestamp, }); } @@ -2278,17 +2278,15 @@ export async function wrapWithSyncMessageSend({ ); } - await sender.sendSyncMessage( - dataMessage, + await sender.sendSyncMessage({ + encodedDataMessage: dataMessage, timestamp, - ourConversation.get('e164'), - ourConversation.get('uuid'), - null, // expirationStartTimestamp - [], // sentTo - [], // unidentifiedDeliveries - undefined, // isUpdate - undefined // options - ); + destination: ourConversation.get('e164'), + destinationUuid: ourConversation.get('uuid'), + expirationStartTimestamp: null, + sentTo: [], + unidentifiedDeliveries: [], + }); } export async function waitThenRespondToGroupV2Migration( diff --git a/ts/models/conversations.ts b/ts/models/conversations.ts index de64d04972c5..972ee0f789ac 100644 --- a/ts/models/conversations.ts +++ b/ts/models/conversations.ts @@ -1186,20 +1186,21 @@ export class ConversationModel extends window.Backbone const { ContentHint, } = window.textsecure.protobuf.UnidentifiedSenderMessage.Message; + const sendOptions = await getSendOptions(this.attributes); if (isDirectConversation(this.attributes)) { handleMessageSend( - window.textsecure.messaging.sendMessageProtoAndWait( + window.textsecure.messaging.sendMessageProtoAndWait({ timestamp, - groupMembers, - contentMessage, - ContentHint.IMPLICIT, - undefined, - { + recipients: groupMembers, + proto: contentMessage, + contentHint: ContentHint.IMPLICIT, + groupId: undefined, + options: { ...sendOptions, online: true, - } - ) + }, + }) ); } else { handleMessageSend( @@ -3204,7 +3205,7 @@ export class ConversationModel extends window.Backbone throw new Error('Cannot send DOE while offline!'); } - const options = await getSendOptions(this.attributes); + const sendOptions = await getSendOptions(this.attributes); const promise = (async () => { let profileKey: ArrayBuffer | undefined; @@ -3217,36 +3218,36 @@ export class ConversationModel extends window.Backbone } = window.textsecure.protobuf.UnidentifiedSenderMessage.Message; if (isDirectConversation(this.attributes)) { - return window.textsecure.messaging.sendMessageToIdentifier( - destination, - undefined, // body - [], // attachments - undefined, // quote - [], // preview - undefined, // sticker - undefined, // reaction - targetTimestamp, + return window.textsecure.messaging.sendMessageToIdentifier({ + identifier: destination, + messageText: undefined, + attachments: [], + quote: undefined, + preview: [], + sticker: undefined, + reaction: undefined, + deletedForEveryoneTimestamp: targetTimestamp, timestamp, - undefined, // expireTimer - ContentHint.DEFAULT, - undefined, // groupId + expireTimer: undefined, + contentHint: ContentHint.DEFAULT, + groupId: undefined, profileKey, - options - ); + options: sendOptions, + }); } - return window.Signal.Util.sendToGroup( - { + return window.Signal.Util.sendToGroup({ + groupSendOptions: { groupV1: this.getGroupV1Info(), groupV2: this.getGroupV2Info(), deletedForEveryoneTimestamp: targetTimestamp, timestamp, profileKey, }, - this, - ContentHint.DEFAULT, - options - ); + conversation: this, + contentHint: ContentHint.DEFAULT, + sendOptions, + }); })(); // This is to ensure that the functions in send() and sendSyncMessage() don't save @@ -3341,7 +3342,6 @@ export class ConversationModel extends window.Backbone if (this.get('profileSharing')) { profileKey = await ourProfileKeyService.get(); } - // Special-case the self-send case - we send only a sync message if (isMe(this.attributes)) { const dataMessage = await window.textsecure.messaging.getDataMessage({ @@ -3369,26 +3369,26 @@ export class ConversationModel extends window.Backbone const promise = (() => { if (isDirectConversation(this.attributes)) { - return window.textsecure.messaging.sendMessageToIdentifier( - destination, - undefined, // body - [], // attachments - undefined, // quote - [], // preview - undefined, // sticker - outgoingReaction, - undefined, // deletedForEveryoneTimestamp + return window.textsecure.messaging.sendMessageToIdentifier({ + identifier: destination, + messageText: undefined, + attachments: [], + quote: undefined, + preview: [], + sticker: undefined, + reaction: outgoingReaction, + deletedForEveryoneTimestamp: undefined, timestamp, expireTimer, - ContentHint.DEFAULT, - undefined, // groupId + contentHint: ContentHint.DEFAULT, + groupId: undefined, profileKey, - options - ); + options, + }); } - return window.Signal.Util.sendToGroup( - { + return window.Signal.Util.sendToGroup({ + groupSendOptions: { // eslint-disable-next-line @typescript-eslint/no-non-null-assertion groupV1: this.getGroupV1Info()!, // eslint-disable-next-line @typescript-eslint/no-non-null-assertion @@ -3398,10 +3398,10 @@ export class ConversationModel extends window.Backbone expireTimer, profileKey, }, - this, - ContentHint.DEFAULT, - options - ); + conversation: this, + contentHint: ContentHint.DEFAULT, + sendOptions: options, + }); })(); const result = await message.send(handleMessageSend(promise)); @@ -3627,8 +3627,8 @@ export class ConversationModel extends window.Backbone let promise; if (conversationType === Message.GROUP) { - promise = window.Signal.Util.sendToGroup( - { + promise = window.Signal.Util.sendToGroup({ + groupSendOptions: { attachments: finalAttachments, expireTimer, groupV1: this.getGroupV1Info(), @@ -3641,27 +3641,27 @@ export class ConversationModel extends window.Backbone timestamp: now, mentions, }, - this, - ContentHint.RESENDABLE, - options - ); + conversation: this, + contentHint: ContentHint.RESENDABLE, + sendOptions: options, + }); } else { - promise = window.textsecure.messaging.sendMessageToIdentifier( - destination, - messageBody, - finalAttachments, + promise = window.textsecure.messaging.sendMessageToIdentifier({ + identifier: destination, + messageText: messageBody, + attachments: finalAttachments, quote, preview, sticker, - null, // reaction - undefined, // deletedForEveryoneTimestamp - now, + reaction: null, + deletedForEveryoneTimestamp: undefined, + timestamp: now, expireTimer, - ContentHint.RESENDABLE, - undefined, // groupId + contentHint: ContentHint.RESENDABLE, + groupId: undefined, profileKey, - options - ); + options, + }); } return message.send(handleMessageSend(promise)); diff --git a/ts/models/messages.ts b/ts/models/messages.ts index 9285779d396f..e853a4d297a4 100644 --- a/ts/models/messages.ts +++ b/ts/models/messages.ts @@ -1278,6 +1278,7 @@ export class MessageModel extends window.Backbone.Model { sticker: stickerWithData, timestamp: this.get('sent_at'), }); + return this.sendSyncMessageOnly(dataMessage); } @@ -1290,22 +1291,23 @@ export class MessageModel extends window.Backbone.Model { if (isDirectConversation(conversation.attributes)) { const [identifier] = recipients; - promise = window.textsecure.messaging.sendMessageToIdentifier( + + promise = window.textsecure.messaging.sendMessageToIdentifier({ identifier, - body, + messageText: body, attachments, - quoteWithData, - previewWithData, - stickerWithData, - null, - this.get('deletedForEveryoneTimestamp'), - this.get('sent_at'), - this.get('expireTimer'), - ContentHint.RESENDABLE, - undefined, // groupId + quote: quoteWithData, + preview: previewWithData, + sticker: stickerWithData, + reaction: null, + deletedForEveryoneTimestamp: this.get('deletedForEveryoneTimestamp'), + timestamp: this.get('sent_at'), + expireTimer: this.get('expireTimer'), + contentHint: ContentHint.RESENDABLE, + groupId: undefined, profileKey, - options - ); + options, + }); } else { const initialGroupV2 = conversation.getGroupV2Info(); const groupId = conversation.get('groupId'); @@ -1326,12 +1328,8 @@ export class MessageModel extends window.Backbone.Model { members: recipients, }; - // Important to ensure that we don't consider this receipient list to be the entire - // member list. - const partialSend = true; - - promise = window.Signal.Util.sendToGroup( - { + promise = window.Signal.Util.sendToGroup({ + groupSendOptions: { messageText: body, timestamp: this.get('sent_at'), attachments, @@ -1345,10 +1343,12 @@ export class MessageModel extends window.Backbone.Model { groupV1, }, conversation, - ContentHint.RESENDABLE, - options, - partialSend - ); + contentHint: ContentHint.RESENDABLE, + // Important to ensure that we don't consider this recipient list to be the + // entire member list. + isPartialSend: true, + sendOptions: options, + }); } return this.send(handleMessageSend(promise)); @@ -1423,6 +1423,7 @@ export class MessageModel extends window.Backbone.Model { sticker: stickerWithData, timestamp: this.get('sent_at'), }); + return this.sendSyncMessageOnly(dataMessage); } @@ -1465,7 +1466,7 @@ export class MessageModel extends window.Backbone.Model { senderKeyInfo.distributionId ); - window.dcodeIO.ByteBuffer.wrap( + contentMessage.senderKeyDistributionMessage = window.dcodeIO.ByteBuffer.wrap( window.Signal.Crypto.typedArrayToArrayBuffer( senderKeyDistributionMessage.serialize() ) @@ -1473,16 +1474,17 @@ export class MessageModel extends window.Backbone.Model { } } - const promise = window.textsecure.messaging.sendMessageProtoAndWait( + const promise = window.textsecure.messaging.sendMessageProtoAndWait({ timestamp, - [identifier], - contentMessage, - ContentHint.RESENDABLE, - groupId && isGroupV2(parentConversation?.attributes) - ? groupId - : undefined, - sendOptions - ); + recipients: [identifier], + proto: contentMessage, + contentHint: ContentHint.RESENDABLE, + groupId: + groupId && isGroupV2(parentConversation?.attributes) + ? groupId + : undefined, + options: sendOptions, + }); return this.send(wrap(promise)); } @@ -1780,18 +1782,18 @@ export class MessageModel extends window.Backbone.Model { const conv = this.getConversation()!; return wrap( - window.textsecure.messaging.sendSyncMessage( - dataMessage, - this.get('sent_at'), - conv.get('e164'), - conv.get('uuid'), - this.get('expirationStartTimestamp') || null, - this.get('sent_to'), - // eslint-disable-next-line @typescript-eslint/no-non-null-assertion - this.get('unidentifiedDeliveries')!, + window.textsecure.messaging.sendSyncMessage({ + encodedDataMessage: dataMessage, + timestamp: this.get('sent_at'), + destination: conv.get('e164'), + destinationUuid: conv.get('uuid'), + expirationStartTimestamp: + this.get('expirationStartTimestamp') || null, + sentTo: this.get('sent_to') || [], + unidentifiedDeliveries: this.get('unidentifiedDeliveries') || [], isUpdate, - sendOptions - ) + options: sendOptions, + }) ).then(async (result: unknown) => { this.set({ synced: true, diff --git a/ts/services/calling.ts b/ts/services/calling.ts index fda49d145b8f..aa3191d48bc8 100644 --- a/ts/services/calling.ts +++ b/ts/services/calling.ts @@ -807,12 +807,12 @@ export class CallingClass { conversation, logId: `sendToGroup/groupCallUpdate/${conversationId}-${eraId}`, send: () => - window.Signal.Util.sendToGroup( - { groupCallUpdate: { eraId }, groupV2, timestamp }, + window.Signal.Util.sendToGroup({ + groupSendOptions: { groupCallUpdate: { eraId }, groupV2, timestamp }, conversation, - ContentHint.DEFAULT, - sendOptions - ), + contentHint: ContentHint.DEFAULT, + sendOptions, + }), timestamp, }).catch(err => { window.log.error( diff --git a/ts/textsecure/OutgoingMessage.ts b/ts/textsecure/OutgoingMessage.ts index a60a97e7035c..033201e98a6f 100644 --- a/ts/textsecure/OutgoingMessage.ts +++ b/ts/textsecure/OutgoingMessage.ts @@ -438,11 +438,13 @@ export default class OutgoingMessage { ciphertextMessage.type() ); + const content = ciphertextMessage.serialize().toString('base64'); + return { type, destinationDeviceId, destinationRegistrationId, - content: ciphertextMessage.serialize().toString('base64'), + content, }; } ); diff --git a/ts/textsecure/SendMessage.ts b/ts/textsecure/SendMessage.ts index 618a43471506..acf89a3d186e 100644 --- a/ts/textsecure/SendMessage.ts +++ b/ts/textsecure/SendMessage.ts @@ -791,13 +791,18 @@ export default class MessageSender { // Low-level sends - async sendMessage( - attrs: MessageOptionsType, - contentHint: number, - groupId: string | undefined, - options?: SendOptionsType - ): Promise { - const message = new Message(attrs); + async sendMessage({ + messageOptions, + contentHint, + groupId, + options, + }: { + messageOptions: MessageOptionsType; + contentHint: number; + groupId: string | undefined; + options?: SendOptionsType; + }): Promise { + const message = new Message(messageOptions); return Promise.all([ this.uploadAttachments(message), @@ -807,13 +812,8 @@ export default class MessageSender { ]).then( async (): Promise => new Promise((resolve, reject) => { - this.sendMessageProto( - message.timestamp, - message.recipients || [], - message.toProto(), - contentHint, - groupId, - (res: CallbackResultType) => { + this.sendMessageProto({ + callback: (res: CallbackResultType) => { res.dataMessage = message.toArrayBuffer(); if (res.errors && res.errors.length > 0) { reject(res); @@ -821,21 +821,34 @@ export default class MessageSender { resolve(res); } }, - options - ); + contentHint, + groupId, + options, + proto: message.toProto(), + recipients: message.recipients || [], + timestamp: message.timestamp, + }); }) ); } - sendMessageProto( - timestamp: number, - recipients: Array, - messageProto: ContentClass | DataMessageClass | PlaintextContent, - contentHint: number, - groupId: string | undefined, - callback: (result: CallbackResultType) => void, - options?: SendOptionsType - ): void { + sendMessageProto({ + timestamp, + recipients, + proto, + contentHint, + groupId, + callback, + options, + }: { + timestamp: number; + recipients: Array; + proto: ContentClass | DataMessageClass | PlaintextContent; + contentHint: number; + groupId: string | undefined; + callback: (result: CallbackResultType) => void; + options?: SendOptionsType; + }): void { const rejections = window.textsecure.storage.get( 'signedKeyRotationRejected', 0 @@ -848,7 +861,7 @@ export default class MessageSender { this.server, timestamp, recipients, - messageProto, + proto, contentHint, groupId, callback, @@ -862,14 +875,21 @@ export default class MessageSender { }); } - async sendMessageProtoAndWait( - timestamp: number, - identifiers: Array, - messageProto: ContentClass | DataMessageClass | PlaintextContent, - contentHint: number, - groupId: string | undefined, - options?: SendOptionsType - ): Promise { + async sendMessageProtoAndWait({ + timestamp, + recipients, + proto, + contentHint, + groupId, + options, + }: { + timestamp: number; + recipients: Array; + proto: ContentClass | DataMessageClass | PlaintextContent; + contentHint: number; + groupId: string | undefined; + options?: SendOptionsType; + }): Promise { return new Promise((resolve, reject) => { const callback = (result: CallbackResultType) => { if (result && result.errors && result.errors.length > 0) { @@ -880,25 +900,31 @@ export default class MessageSender { resolve(result); }; - this.sendMessageProto( - timestamp, - identifiers, - messageProto, + this.sendMessageProto({ + callback, contentHint, groupId, - callback, - options - ); + options, + proto, + recipients, + timestamp, + }); }); } - async sendIndividualProto( - identifier: string | undefined, - proto: DataMessageClass | ContentClass | PlaintextContent, - timestamp: number, - contentHint: number, - options?: SendOptionsType - ): Promise { + async sendIndividualProto({ + identifier, + proto, + timestamp, + contentHint, + options, + }: { + identifier: string | undefined; + proto: DataMessageClass | ContentClass | PlaintextContent; + timestamp: number; + contentHint: number; + options?: SendOptionsType; + }): Promise { assert(identifier, "Identifier can't be undefined"); return new Promise((resolve, reject) => { const callback = (res: CallbackResultType) => { @@ -908,38 +934,53 @@ export default class MessageSender { resolve(res); } }; - this.sendMessageProto( - timestamp, - [identifier], - proto, - contentHint, - undefined, // groupId + this.sendMessageProto({ callback, - options - ); + contentHint, + groupId: undefined, + options, + proto, + recipients: [identifier], + timestamp, + }); }); } // You might wonder why this takes a groupId. models/messages.resend() can send a group // message to just one person. - async sendMessageToIdentifier( - identifier: string, - messageText: string | undefined, - attachments: Array | undefined, - quote: unknown, - preview: Array | undefined, - sticker: unknown, - reaction: unknown, - deletedForEveryoneTimestamp: number | undefined, - timestamp: number, - expireTimer: number | undefined, - contentHint: number, - groupId: string | undefined, - profileKey?: ArrayBuffer, - options?: SendOptionsType - ): Promise { - return this.sendMessage( - { + async sendMessageToIdentifier({ + identifier, + messageText, + attachments, + quote, + preview, + sticker, + reaction, + deletedForEveryoneTimestamp, + timestamp, + expireTimer, + contentHint, + groupId, + profileKey, + options, + }: { + identifier: string; + messageText: string | undefined; + attachments: Array | undefined; + quote: unknown; + preview: Array | undefined; + sticker: unknown; + reaction: unknown; + deletedForEveryoneTimestamp: number | undefined; + timestamp: number; + expireTimer: number | undefined; + contentHint: number; + groupId: string | undefined; + profileKey?: ArrayBuffer; + options?: SendOptionsType; + }): Promise { + return this.sendMessage({ + messageOptions: { recipients: [identifier], body: messageText, timestamp, @@ -954,23 +995,33 @@ export default class MessageSender { }, contentHint, groupId, - options - ); + options, + }); } // Support for sync messages - async sendSyncMessage( - encodedDataMessage: ArrayBuffer, - timestamp: number, - destination: string | undefined, - destinationUuid: string | null | undefined, - expirationStartTimestamp: number | null, - sentTo: Array = [], - unidentifiedDeliveries: Array = [], - isUpdate = false, - options?: SendOptionsType - ): Promise { + async sendSyncMessage({ + encodedDataMessage, + timestamp, + destination, + destinationUuid, + expirationStartTimestamp, + sentTo, + unidentifiedDeliveries, + isUpdate, + options, + }: { + encodedDataMessage: ArrayBuffer; + timestamp: number; + destination: string | undefined; + destinationUuid: string | null | undefined; + expirationStartTimestamp: number | null; + sentTo?: Array; + unidentifiedDeliveries?: Array; + isUpdate?: boolean; + options?: SendOptionsType; + }): Promise { const myNumber = window.textsecure.storage.user.getNumber(); const myUuid = window.textsecure.storage.user.getUuid(); const myDevice = window.textsecure.storage.user.getDeviceId(); @@ -995,7 +1046,7 @@ export default class MessageSender { sentMessage.expirationStartTimestamp = expirationStartTimestamp; } - const unidentifiedLookup = unidentifiedDeliveries.reduce( + const unidentifiedLookup = (unidentifiedDeliveries || []).reduce( (accumulator, item) => { // eslint-disable-next-line no-param-reassign accumulator[item] = true; @@ -1034,13 +1085,13 @@ export default class MessageSender { ContentHint, } = window.textsecure.protobuf.UnidentifiedSenderMessage.Message; - return this.sendIndividualProto( - myUuid || myNumber, - contentMessage, + return this.sendIndividualProto({ + identifier: myUuid || myNumber, + proto: contentMessage, timestamp, - ContentHint.IMPLICIT, - options - ); + contentHint: ContentHint.IMPLICIT, + options, + }); } async sendRequestBlockSyncMessage( @@ -1062,13 +1113,13 @@ export default class MessageSender { ContentHint, } = window.textsecure.protobuf.UnidentifiedSenderMessage.Message; - return this.sendIndividualProto( - myUuid || myNumber, - contentMessage, - Date.now(), - ContentHint.IMPLICIT, - options - ); + return this.sendIndividualProto({ + identifier: myUuid || myNumber, + proto: contentMessage, + timestamp: Date.now(), + contentHint: ContentHint.IMPLICIT, + options, + }); } return Promise.resolve(); @@ -1093,13 +1144,13 @@ export default class MessageSender { ContentHint, } = window.textsecure.protobuf.UnidentifiedSenderMessage.Message; - return this.sendIndividualProto( - myUuid || myNumber, - contentMessage, - Date.now(), - ContentHint.IMPLICIT, - options - ); + return this.sendIndividualProto({ + identifier: myUuid || myNumber, + proto: contentMessage, + timestamp: Date.now(), + contentHint: ContentHint.IMPLICIT, + options, + }); } return Promise.resolve(); @@ -1123,13 +1174,13 @@ export default class MessageSender { ContentHint, } = window.textsecure.protobuf.UnidentifiedSenderMessage.Message; - return this.sendIndividualProto( - myUuid || myNumber, - contentMessage, - Date.now(), - ContentHint.IMPLICIT, - options - ); + return this.sendIndividualProto({ + identifier: myUuid || myNumber, + proto: contentMessage, + timestamp: Date.now(), + contentHint: ContentHint.IMPLICIT, + options, + }); } return Promise.resolve(); @@ -1155,13 +1206,13 @@ export default class MessageSender { ContentHint, } = window.textsecure.protobuf.UnidentifiedSenderMessage.Message; - return this.sendIndividualProto( - myUuid || myNumber, - contentMessage, - Date.now(), - ContentHint.IMPLICIT, - options - ); + return this.sendIndividualProto({ + identifier: myUuid || myNumber, + proto: contentMessage, + timestamp: Date.now(), + contentHint: ContentHint.IMPLICIT, + options, + }); } return Promise.resolve(); @@ -1191,13 +1242,13 @@ export default class MessageSender { ContentHint, } = window.textsecure.protobuf.UnidentifiedSenderMessage.Message; - await this.sendIndividualProto( - myUuid || myNumber, - contentMessage, - Date.now(), - ContentHint.IMPLICIT, - options - ); + await this.sendIndividualProto({ + identifier: myUuid || myNumber, + proto: contentMessage, + timestamp: Date.now(), + contentHint: ContentHint.IMPLICIT, + options, + }); } async sendRequestKeySyncMessage( @@ -1223,13 +1274,13 @@ export default class MessageSender { ContentHint, } = window.textsecure.protobuf.UnidentifiedSenderMessage.Message; - await this.sendIndividualProto( - myUuid || myNumber, - contentMessage, - Date.now(), - ContentHint.IMPLICIT, - options - ); + await this.sendIndividualProto({ + identifier: myUuid || myNumber, + proto: contentMessage, + timestamp: Date.now(), + contentHint: ContentHint.IMPLICIT, + options, + }); } async syncReadMessages( @@ -1243,34 +1294,34 @@ export default class MessageSender { const myNumber = window.textsecure.storage.user.getNumber(); const myUuid = window.textsecure.storage.user.getUuid(); const myDevice = window.textsecure.storage.user.getDeviceId(); - if (myDevice !== 1) { - const syncMessage = this.createSyncMessage(); - syncMessage.read = []; - for (let i = 0; i < reads.length; i += 1) { - const read = new window.textsecure.protobuf.SyncMessage.Read(); - read.timestamp = reads[i].timestamp; - read.sender = reads[i].senderE164 || null; - read.senderUuid = reads[i].senderUuid || null; - - syncMessage.read.push(read); - } - const contentMessage = new window.textsecure.protobuf.Content(); - contentMessage.syncMessage = syncMessage; - - const { - ContentHint, - } = window.textsecure.protobuf.UnidentifiedSenderMessage.Message; - - return this.sendIndividualProto( - myUuid || myNumber, - contentMessage, - Date.now(), - ContentHint.DEFAULT, - options - ); + if (myDevice === 1) { + return Promise.resolve(); } - return Promise.resolve(); + const syncMessage = this.createSyncMessage(); + syncMessage.read = []; + for (let i = 0; i < reads.length; i += 1) { + const read = new window.textsecure.protobuf.SyncMessage.Read(); + read.timestamp = reads[i].timestamp; + read.sender = reads[i].senderE164 || null; + read.senderUuid = reads[i].senderUuid || null; + + syncMessage.read.push(read); + } + const contentMessage = new window.textsecure.protobuf.Content(); + contentMessage.syncMessage = syncMessage; + + const { + ContentHint, + } = window.textsecure.protobuf.UnidentifiedSenderMessage.Message; + + return this.sendIndividualProto({ + identifier: myUuid || myNumber, + proto: contentMessage, + timestamp: Date.now(), + contentHint: ContentHint.IMPLICIT, + options, + }); } async syncViewOnceOpen( @@ -1301,13 +1352,13 @@ export default class MessageSender { ContentHint, } = window.textsecure.protobuf.UnidentifiedSenderMessage.Message; - return this.sendIndividualProto( - myUuid || myNumber, - contentMessage, - Date.now(), - ContentHint.IMPLICIT, - options - ); + return this.sendIndividualProto({ + identifier: myUuid || myNumber, + proto: contentMessage, + timestamp: Date.now(), + contentHint: ContentHint.IMPLICIT, + options, + }); } async syncMessageRequestResponse( @@ -1317,7 +1368,7 @@ export default class MessageSender { groupId?: ArrayBuffer; type: number; }, - sendOptions?: SendOptionsType + options?: SendOptionsType ): Promise { const myNumber = window.textsecure.storage.user.getNumber(); const myUuid = window.textsecure.storage.user.getUuid(); @@ -1342,13 +1393,13 @@ export default class MessageSender { ContentHint, } = window.textsecure.protobuf.UnidentifiedSenderMessage.Message; - return this.sendIndividualProto( - myUuid || myNumber, - contentMessage, - Date.now(), - ContentHint.IMPLICIT, - sendOptions - ); + return this.sendIndividualProto({ + identifier: myUuid || myNumber, + proto: contentMessage, + timestamp: Date.now(), + contentHint: ContentHint.IMPLICIT, + options, + }); } async sendStickerPackSync( @@ -1390,13 +1441,13 @@ export default class MessageSender { ContentHint, } = window.textsecure.protobuf.UnidentifiedSenderMessage.Message; - return this.sendIndividualProto( - myUuid || myNumber, - contentMessage, - Date.now(), - ContentHint.IMPLICIT, - options - ); + return this.sendIndividualProto({ + identifier: myUuid || myNumber, + proto: contentMessage, + timestamp: Date.now(), + contentHint: ContentHint.IMPLICIT, + options, + }); } async syncVerification( @@ -1446,13 +1497,13 @@ export default class MessageSender { ContentHint, } = window.textsecure.protobuf.UnidentifiedSenderMessage.Message; - return this.sendIndividualProto( - myUuid || myNumber, - secondMessage, - now, - ContentHint.IMPLICIT, - options - ); + await this.sendIndividualProto({ + identifier: myUuid || myNumber, + proto: secondMessage, + timestamp: now, + contentHint: ContentHint.IMPLICIT, + options, + }); }); } @@ -1461,15 +1512,15 @@ export default class MessageSender { async sendProfileKeyUpdate( profileKey: ArrayBuffer, recipients: Array, - sendOptions: SendOptionsType, + options: SendOptionsType, groupId?: string ): Promise { const { ContentHint, } = window.textsecure.protobuf.UnidentifiedSenderMessage.Message; - return this.sendMessage( - { + return this.sendMessage({ + messageOptions: { recipients, timestamp: Date.now(), profileKey, @@ -1483,16 +1534,16 @@ export default class MessageSender { } : {}), }, - ContentHint.IMPLICIT, - undefined, // groupId - sendOptions - ); + contentHint: ContentHint.IMPLICIT, + groupId: undefined, + options, + }); } async sendCallingMessage( recipientId: string, callingMessage: CallingMessageClass, - sendOptions?: SendOptionsType + options?: SendOptionsType ): Promise { const recipients = [recipientId]; const finalTimestamp = Date.now(); @@ -1504,29 +1555,31 @@ export default class MessageSender { ContentHint, } = window.textsecure.protobuf.UnidentifiedSenderMessage.Message; - await this.sendMessageProtoAndWait( - finalTimestamp, + await this.sendMessageProtoAndWait({ + timestamp: finalTimestamp, recipients, - contentMessage, - ContentHint.DEFAULT, - undefined, // groupId - sendOptions - ); + proto: contentMessage, + contentHint: ContentHint.DEFAULT, + groupId: undefined, + options, + }); } - async sendDeliveryReceipt( - recipientE164: string, - recipientUuid: string, - timestamps: Array, - options?: SendOptionsType - ): Promise { + async sendDeliveryReceipt({ + e164, + uuid, + timestamps, + options, + }: { + e164: string; + uuid: string; + timestamps: Array; + options?: SendOptionsType; + }): Promise { const myNumber = window.textsecure.storage.user.getNumber(); const myUuid = window.textsecure.storage.user.getUuid(); const myDevice = window.textsecure.storage.user.getDeviceId(); - if ( - (myNumber === recipientE164 || myUuid === recipientUuid) && - myDevice === 1 - ) { + if ((myNumber === e164 || myUuid === uuid) && myDevice === 1) { return Promise.resolve(); } @@ -1542,21 +1595,26 @@ export default class MessageSender { ContentHint, } = window.textsecure.protobuf.UnidentifiedSenderMessage.Message; - return this.sendIndividualProto( - recipientUuid || recipientE164, - contentMessage, - Date.now(), - ContentHint.IMPLICIT, - options - ); + return this.sendIndividualProto({ + identifier: uuid || e164, + proto: contentMessage, + timestamp: Date.now(), + contentHint: ContentHint.IMPLICIT, + options, + }); } - async sendReadReceipts( - senderE164: string, - senderUuid: string, - timestamps: Array, - options?: SendOptionsType - ): Promise { + async sendReadReceipts({ + senderE164, + senderUuid, + timestamps, + options, + }: { + senderE164: string; + senderUuid: string; + timestamps: Array; + options?: SendOptionsType; + }): Promise { const receiptMessage = new window.textsecure.protobuf.ReceiptMessage(); receiptMessage.type = window.textsecure.protobuf.ReceiptMessage.Type.READ; receiptMessage.timestamp = timestamps; @@ -1568,13 +1626,13 @@ export default class MessageSender { ContentHint, } = window.textsecure.protobuf.UnidentifiedSenderMessage.Message; - return this.sendIndividualProto( - senderUuid || senderE164, - contentMessage, - Date.now(), - ContentHint.IMPLICIT, - options - ); + return this.sendIndividualProto({ + identifier: senderUuid || senderE164, + proto: contentMessage, + timestamp: Date.now(), + contentHint: ContentHint.IMPLICIT, + options, + }); } async sendNullMessage( @@ -1603,13 +1661,13 @@ export default class MessageSender { // We want the NullMessage to look like a normal outgoing message const timestamp = Date.now(); - return this.sendIndividualProto( + return this.sendIndividualProto({ identifier, - contentMessage, + proto: contentMessage, timestamp, - ContentHint.IMPLICIT, - options - ); + contentHint: ContentHint.IMPLICIT, + options, + }); } async resetSession( @@ -1644,13 +1702,13 @@ export default class MessageSender { window.log.info( 'resetSession: finished closing local sessions, now sending to contact' ); - return this.sendIndividualProto( + return this.sendIndividualProto({ identifier, proto, timestamp, - ContentHint.DEFAULT, - options - ).catch(logError('resetSession/sendToContact error:')); + contentHint: ContentHint.DEFAULT, + options, + }).catch(logError('resetSession/sendToContact error:')); }) .then(async () => window.textsecure.storage.protocol @@ -1666,17 +1724,16 @@ export default class MessageSender { } const buffer = proto.toArrayBuffer(); - const sendSyncPromise = this.sendSyncMessage( - buffer, + const sendSyncPromise = this.sendSyncMessage({ + encodedDataMessage: buffer, timestamp, - e164, - uuid, - null, - [], - [], - false, - options - ).catch(logError('resetSession/sendSync error:')); + destination: e164, + destinationUuid: uuid, + expirationStartTimestamp: null, + sentTo: [], + unidentifiedDeliveries: [], + options, + }).catch(logError('resetSession/sendSync error:')); return Promise.all([sendToContactPromise, sendSyncPromise]); } @@ -1692,8 +1749,8 @@ export default class MessageSender { ContentHint, } = window.textsecure.protobuf.UnidentifiedSenderMessage.Message; - return this.sendMessage( - { + return this.sendMessage({ + messageOptions: { recipients: [identifier], timestamp, expireTimer, @@ -1701,10 +1758,10 @@ export default class MessageSender { flags: window.textsecure.protobuf.DataMessage.Flags.EXPIRATION_TIMER_UPDATE, }, - ContentHint.DEFAULT, - undefined, // groupId - options - ); + contentHint: ContentHint.DEFAULT, + groupId: undefined, + options, + }); } async sendRetryRequest({ @@ -1720,34 +1777,39 @@ export default class MessageSender { ContentHint, } = window.textsecure.protobuf.UnidentifiedSenderMessage.Message; - return this.sendMessageProtoAndWait( - Date.now(), - [uuid], - plaintext, - ContentHint.IMPLICIT, - undefined, // groupId - options - ); + return this.sendMessageProtoAndWait({ + timestamp: Date.now(), + recipients: [uuid], + proto: plaintext, + contentHint: ContentHint.IMPLICIT, + groupId: undefined, + options, + }); } // Group sends // No functions should really call this; since most group sends are now via Sender Key - async sendGroupProto( - providedIdentifiers: Array, - proto: ContentClass, + async sendGroupProto({ + recipients, + proto, timestamp = Date.now(), - contentHint: number, - groupId: string | undefined, - options?: SendOptionsType - ): Promise { + contentHint, + groupId, + options, + }: { + recipients: Array; + proto: ContentClass; + timestamp: number; + contentHint: number; + groupId: string | undefined; + options?: SendOptionsType; + }): Promise { const dataMessage = proto.dataMessage?.toArrayBuffer(); const myE164 = window.textsecure.storage.user.getNumber(); const myUuid = window.textsecure.storage.user.getUuid(); - const identifiers = providedIdentifiers.filter( - id => id !== myE164 && id !== myUuid - ); + const identifiers = recipients.filter(id => id !== myE164 && id !== myUuid); if (identifiers.length === 0) { return Promise.resolve({ @@ -1769,15 +1831,15 @@ export default class MessageSender { } }; - this.sendMessageProto( + this.sendMessageProto({ timestamp, - providedIdentifiers, + recipients: identifiers, proto, contentHint, groupId, callback, - options - ); + options, + }); }); } @@ -1834,14 +1896,14 @@ export default class MessageSender { typedArrayToArrayBuffer(senderKeyDistributionMessage.serialize()) ); - return this.sendGroupProto( - identifiers, - contentMessage, - Date.now(), + return this.sendGroupProto({ + recipients: identifiers, + proto: contentMessage, + timestamp: Date.now(), contentHint, groupId, - options - ); + options, + }); } // GroupV1-only functions; not to be used in the future @@ -1859,14 +1921,14 @@ export default class MessageSender { const { ContentHint, } = window.textsecure.protobuf.UnidentifiedSenderMessage.Message; - return this.sendGroupProto( - groupIdentifiers, + return this.sendGroupProto({ + recipients: groupIdentifiers, proto, - Date.now(), - ContentHint.DEFAULT, - undefined, // only for GV2 ids - options - ); + timestamp: Date.now(), + contentHint: ContentHint.DEFAULT, + groupId: undefined, // only for GV2 ids + options, + }); } async sendExpirationTimerUpdateToGroup( @@ -1882,7 +1944,7 @@ export default class MessageSender { const recipients = groupIdentifiers.filter( identifier => identifier !== myNumber && identifier !== myUuid ); - const attrs = { + const messageOptions = { recipients, timestamp, expireTimer, @@ -1901,19 +1963,19 @@ export default class MessageSender { failoverIdentifiers: [], errors: [], unidentifiedDeliveries: [], - dataMessage: await this.getDataMessage(attrs), + dataMessage: await this.getDataMessage(messageOptions), }); } const { ContentHint, } = window.textsecure.protobuf.UnidentifiedSenderMessage.Message; - return this.sendMessage( - attrs, - ContentHint.DEFAULT, - undefined, // only for GV2 ids - options - ); + return this.sendMessage({ + messageOptions, + contentHint: ContentHint.DEFAULT, + groupId: undefined, // only for GV2 ids + options, + }); } // Simple pass-throughs diff --git a/ts/util/sendReadReceiptsFor.ts b/ts/util/sendReadReceiptsFor.ts index 53669f36798f..526af7f7ed44 100644 --- a/ts/util/sendReadReceiptsFor.ts +++ b/ts/util/sendReadReceiptsFor.ts @@ -17,7 +17,7 @@ export async function sendReadReceiptsFor( isConversationAccepted(conversationAttrs) ) { window.log.info(`Sending ${items.length} read receipts`); - const convoSendOptions = await getSendOptions(conversationAttrs); + const sendOptions = await getSendOptions(conversationAttrs); const receiptsBySender = groupBy(items, 'senderId'); await Promise.all( @@ -27,14 +27,14 @@ export async function sendReadReceiptsFor( if (conversation) { await handleMessageSend( - window.textsecure.messaging.sendReadReceipts( + window.textsecure.messaging.sendReadReceipts({ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion - conversation.get('e164')!, + senderE164: conversation.get('e164')!, // eslint-disable-next-line @typescript-eslint/no-non-null-assertion - conversation.get('uuid')!, + senderUuid: conversation.get('uuid')!, timestamps, - convoSendOptions - ) + options: sendOptions, + }) ); } }) diff --git a/ts/util/sendToGroup.ts b/ts/util/sendToGroup.ts index 8406a12feacb..22ea4af79e18 100644 --- a/ts/util/sendToGroup.ts +++ b/ts/util/sendToGroup.ts @@ -55,13 +55,19 @@ const MAX_RECURSION = 5; // Public API: -export async function sendToGroup( - groupSendOptions: GroupSendOptionsType, - conversation: ConversationModel, - contentHint: number, - sendOptions?: SendOptionsType, - isPartialSend?: boolean -): Promise { +export async function sendToGroup({ + groupSendOptions, + conversation, + contentHint, + sendOptions, + isPartialSend, +}: { + groupSendOptions: GroupSendOptionsType; + conversation: ConversationModel; + contentHint: number; + sendOptions?: SendOptionsType; + isPartialSend?: boolean; +}): Promise { assert( window.textsecure.messaging, 'sendToGroup: textsecure.messaging not available!' @@ -145,14 +151,14 @@ export async function sendContentMessageToGroup({ const groupId = isGroupV2(conversation.attributes) ? conversation.get('groupId') : undefined; - return window.textsecure.messaging.sendGroupProto( + return window.textsecure.messaging.sendGroupProto({ recipients, - contentMessage, + proto: contentMessage, timestamp, contentHint, groupId, - { ...sendOptions, online } - ); + options: { ...sendOptions, online }, + }); } // The Primary Sender Key workflow @@ -433,14 +439,14 @@ export async function sendToGroupViaSenderKey(options: { // 12. Send normal message to the leftover normal recipients. Then combine normal send // result with result from sender key send for final return value. - const normalSendResult = await window.textsecure.messaging.sendGroupProto( - normalRecipients, - contentMessage, + const normalSendResult = await window.textsecure.messaging.sendGroupProto({ + recipients: normalRecipients, + proto: contentMessage, timestamp, contentHint, groupId, - { ...sendOptions, online } - ); + options: { ...sendOptions, online }, + }); return { dataMessage: contentMessage.dataMessage?.toArrayBuffer(),