diff --git a/ts/services/backups/export.preload.ts b/ts/services/backups/export.preload.ts index 7bcfdb151b..158c9887fa 100644 --- a/ts/services/backups/export.preload.ts +++ b/ts/services/backups/export.preload.ts @@ -1612,9 +1612,25 @@ export class BackupExportStream extends Readable { ); } else if (message.source) { authorId = this.#getRecipientByE164(message.source, 'message.source'); + } else if (isIncoming) { + if (conversation && isDirectConversation(conversation.attributes)) { + authorId = this.#getRecipientByConversationId( + conversation.id, + 'message-missing-source' + ); + } + if (authorId != null) { + log.warn( + `${message.sent_at}: Incoming message in group missing source, using conversation` + ); + } else { + log.warn( + `${message.sent_at}: Incoming message in group or unknown conversation` + + ' without source, dropping' + ); + return undefined; + } } else { - strictAssert(!isIncoming, 'Incoming message must have source'); - // Author must be always present, even if we are directionless authorId = me; } diff --git a/ts/test-electron/backup/bubble_test.preload.ts b/ts/test-electron/backup/bubble_test.preload.ts index fe8e655ea9..75ae9dd83f 100644 --- a/ts/test-electron/backup/bubble_test.preload.ts +++ b/ts/test-electron/backup/bubble_test.preload.ts @@ -387,6 +387,63 @@ describe('backup/bubble messages', () => { ); }); + it('fixes source-missing incoming 1:1 messages', async () => { + await asymmetricRoundtripHarness( + [ + { + conversationId: contactA.id, + id: generateGuid(), + type: 'incoming', + received_at: 3, + received_at_ms: 3, + sent_at: 3, + readStatus: ReadStatus.Unread, + seenStatus: SeenStatus.Unseen, + unidentifiedDeliveryReceived: true, + timestamp: 3, + body: 'hello', + }, + ], + [ + { + conversationId: contactA.id, + id: generateGuid(), + type: 'incoming', + received_at: 3, + received_at_ms: 3, + sent_at: 3, + sourceServiceId: CONTACT_A, + readStatus: ReadStatus.Unread, + seenStatus: SeenStatus.Unseen, + unidentifiedDeliveryReceived: true, + timestamp: 3, + body: 'hello', + }, + ] + ); + }); + + it('drops source-missing incoming group messages', async () => { + await asymmetricRoundtripHarness( + [ + { + conversationId: gv2.id, + id: generateGuid(), + type: 'incoming', + received_at: 3, + received_at_ms: 3, + sent_at: 3, + readStatus: ReadStatus.Unread, + seenStatus: SeenStatus.Unseen, + unidentifiedDeliveryReceived: true, + timestamp: 3, + body: 'hello', + }, + ], + [] + ); + }); + it('drops misattributed incoming 1:1 messages', async () => { await asymmetricRoundtripHarness( [