From 470144e29375808c52dfd2f6deced73e59d5390a Mon Sep 17 00:00:00 2001 From: automated-signal <37887102+automated-signal@users.noreply.github.com> Date: Thu, 19 Mar 2026 08:06:52 -0500 Subject: [PATCH] More backup export fixes Co-authored-by: trevor-signal <131492920+trevor-signal@users.noreply.github.com> --- ts/services/backups/export.preload.ts | 80 +++++++++++++++++---------- 1 file changed, 52 insertions(+), 28 deletions(-) diff --git a/ts/services/backups/export.preload.ts b/ts/services/backups/export.preload.ts index 3df9ba4001..536c4377d2 100644 --- a/ts/services/backups/export.preload.ts +++ b/ts/services/backups/export.preload.ts @@ -850,18 +850,12 @@ export class BackupExportStream extends Readable { objectMode: true, highWaterMark: FLUSH_EVERY, }), - message => { - if (skippedConversationIds.has(message.conversationId)) { - this.#stats.skippedMessages += 1; - return undefined; - } - - return this.#toChatItem(message, { + message => + this.#toChatItem(message, { aboutMe, callHistoryByCallId, pinnedMessagesByMessageId, - }); - }, + }), { concurrency: MAX_CONCURRENCY, backpressure: FLUSH_EVERY, @@ -1149,7 +1143,7 @@ export class BackupExportStream extends Readable { fnLog.warn('recipient convoId missing', reason); this.#incrementUnknownConversationReference(reason); } - return this.#convoIdToRecipientId.get(convoId); + return recipientId; } #getRecipientByServiceId( @@ -1506,6 +1500,47 @@ export class BackupExportStream extends Readable { callHistoryByCallId, pinnedMessagesByMessageId, }: ToChatItemOptionsType + ): Promise { + const chatItem = await this.#toChatItemInner(message, { + aboutMe, + callHistoryByCallId, + pinnedMessagesByMessageId, + }); + + // Drop messages in the wrong 1:1 chat + const conversation = window.ConversationController.get( + message.conversationId + ); + const me = this.#getRecipientByServiceId(aboutMe.aci, 'getting self'); + strictAssert(me, 'self recipient must exist'); + + if ( + chatItem && + conversation && + isDirectConversation(conversation.attributes) + ) { + const convoAuthor = this.#getRecipientByConversationId( + conversation.attributes.id, + 'message.conversationId' + ); + + if (chatItem.authorId !== me && chatItem.authorId !== convoAuthor) { + log.warn( + `${message.sent_at}: Dropping direct message with mismatched author` + ); + return undefined; + } + } + return chatItem; + } + + async #toChatItemInner( + message: MessageAttributesType, + { + aboutMe, + callHistoryByCallId, + pinnedMessagesByMessageId, + }: ToChatItemOptionsType ): Promise { const conversation = window.ConversationController.get( message.conversationId @@ -1605,22 +1640,10 @@ export class BackupExportStream extends Readable { if (authorId !== convoAuthor) { authorId = convoAuthor; - this.#stats.fixedDirectMessages += 1; - } - } - - // Drop messages in the wrong 1:1 chat - if (conversation && isDirectConversation(conversation.attributes)) { - const convoAuthor = this.#getRecipientByConversationId( - conversation.attributes.id, - 'message.conversationId' - ); - - if (authorId !== me && authorId !== convoAuthor) { log.warn( - `${message.sent_at}: Dropping direct message with mismatched author` + `${message.sent_at}: Fixing misattributed e164-only 1:1 message` ); - return undefined; + this.#stats.fixedDirectMessages += 1; } } @@ -3375,7 +3398,11 @@ export class BackupExportStream extends Readable { const sendStatuses = new Array(); for (const [id, entry] of Object.entries(sendStateByConversationId)) { const target = window.ConversationController.get(id); - if (!target) { + const recipientId = + this.#getRecipientByConversationId(id, 'sendStateByConversationId') ?? + null; + + if (!target || recipientId == null) { log.warn(`no send target for a message ${sentAt}`); continue; } @@ -3391,9 +3418,6 @@ export class BackupExportStream extends Readable { } const { serviceId } = target.attributes; - const recipientId = - this.#getRecipientByConversationId(id, 'sendStateByConversationId') ?? - null; const timestamp = entry.updatedAt != null ? getSafeLongFromTimestamp(entry.updatedAt)