signal-desktop/ts/util/wrapWithSyncMessageSend.ts
2022-02-16 10:36:21 -08:00

108 lines
3.2 KiB
TypeScript

// Copyright 2022 Signal Messenger, LLC
// SPDX-License-Identifier: AGPL-3.0-only
import * as log from '../logging/log';
import { SendMessageProtoError } from '../textsecure/Errors';
import { getSendOptions } from './getSendOptions';
import { handleMessageSend } from './handleMessageSend';
import type { CallbackResultType } from '../textsecure/Types.d';
import type { ConversationModel } from '../models/conversations';
import type { SendTypesType } from './handleMessageSend';
import type MessageSender from '../textsecure/SendMessage';
import { areAllErrorsUnregistered } from '../jobs/helpers/areAllErrorsUnregistered';
export async function wrapWithSyncMessageSend({
conversation,
logId,
messageIds,
send,
sendType,
timestamp,
}: {
conversation: ConversationModel;
logId: string;
messageIds: Array<string>;
send: (sender: MessageSender) => Promise<CallbackResultType>;
sendType: SendTypesType;
timestamp: number;
}): Promise<void> {
const sender = window.textsecure.messaging;
if (!sender) {
throw new Error(
`wrapWithSyncMessageSend/${logId}: textsecure.messaging is not available!`
);
}
let response: CallbackResultType | undefined;
let error: Error | undefined;
let didSuccessfullySendOne = false;
try {
response = await handleMessageSend(send(sender), { messageIds, sendType });
didSuccessfullySendOne = true;
} catch (thrown) {
if (thrown instanceof SendMessageProtoError) {
didSuccessfullySendOne = Boolean(
thrown.successfulIdentifiers && thrown.successfulIdentifiers.length > 0
);
error = thrown;
}
if (thrown instanceof Error) {
error = thrown;
} else {
log.error(
`wrapWithSyncMessageSend/${logId}: Thrown value was not an Error, returning early`
);
throw error;
}
}
if (!response && !error) {
throw new Error(
`wrapWithSyncMessageSend/${logId}: message send didn't return result or error!`
);
}
const dataMessage =
response?.dataMessage ||
(error instanceof SendMessageProtoError ? error.dataMessage : undefined);
if (didSuccessfullySendOne) {
if (!dataMessage) {
log.error(
`wrapWithSyncMessageSend/${logId}: dataMessage was not returned by send!`
);
} else {
log.error(`wrapWithSyncMessageSend/${logId}: Sending sync message...`);
const ourConversation =
window.ConversationController.getOurConversationOrThrow();
const options = await getSendOptions(ourConversation.attributes, {
syncMessage: true,
});
await handleMessageSend(
sender.sendSyncMessage({
destination: ourConversation.get('e164'),
destinationUuid: ourConversation.get('uuid'),
encodedDataMessage: dataMessage,
expirationStartTimestamp: null,
options,
timestamp,
}),
{ messageIds, sendType: sendType === 'message' ? 'sentSync' : sendType }
);
}
}
if (error instanceof Error) {
if (areAllErrorsUnregistered(conversation.attributes, error)) {
log.info(
`wrapWithSyncMessageSend/${logId}: Group send failures were all UnregisteredUserError, returning succcessfully.`
);
return;
}
throw error;
}
}