Fix roundtripping of voice notes with body
This commit is contained in:
parent
c9c3d24fd9
commit
0b5f0df1ca
2 changed files with 50 additions and 14 deletions
|
@ -38,7 +38,6 @@ import type {
|
||||||
ConversationAttributesType,
|
ConversationAttributesType,
|
||||||
MessageAttributesType,
|
MessageAttributesType,
|
||||||
QuotedAttachmentType,
|
QuotedAttachmentType,
|
||||||
QuotedMessageType,
|
|
||||||
} from '../../model-types.d';
|
} from '../../model-types.d';
|
||||||
import { drop } from '../../util/drop';
|
import { drop } from '../../util/drop';
|
||||||
import { isNotNil } from '../../util/isNotNil';
|
import { isNotNil } from '../../util/isNotNil';
|
||||||
|
@ -2195,14 +2194,13 @@ export class BackupExportStream extends Readable {
|
||||||
}
|
}
|
||||||
|
|
||||||
async #toQuote({
|
async #toQuote({
|
||||||
quote,
|
message,
|
||||||
backupLevel,
|
backupLevel,
|
||||||
messageReceivedAt,
|
|
||||||
}: {
|
}: {
|
||||||
quote?: QuotedMessageType;
|
message: Pick<MessageAttributesType, 'quote' | 'received_at' | 'body'>;
|
||||||
backupLevel: BackupLevel;
|
backupLevel: BackupLevel;
|
||||||
messageReceivedAt: number;
|
|
||||||
}): Promise<Backups.IQuote | null> {
|
}): Promise<Backups.IQuote | null> {
|
||||||
|
const { quote } = message;
|
||||||
if (!quote) {
|
if (!quote) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
@ -2259,7 +2257,7 @@ export class BackupExportStream extends Readable {
|
||||||
? await this.#processMessageAttachment({
|
? await this.#processMessageAttachment({
|
||||||
attachment: attachment.thumbnail,
|
attachment: attachment.thumbnail,
|
||||||
backupLevel,
|
backupLevel,
|
||||||
messageReceivedAt,
|
message,
|
||||||
})
|
})
|
||||||
: undefined,
|
: undefined,
|
||||||
};
|
};
|
||||||
|
@ -2287,11 +2285,17 @@ export class BackupExportStream extends Readable {
|
||||||
}
|
}
|
||||||
|
|
||||||
#getMessageAttachmentFlag(
|
#getMessageAttachmentFlag(
|
||||||
|
message: Pick<MessageAttributesType, 'body'>,
|
||||||
attachment: AttachmentType
|
attachment: AttachmentType
|
||||||
): Backups.MessageAttachment.Flag {
|
): Backups.MessageAttachment.Flag {
|
||||||
const flag = SignalService.AttachmentPointer.Flags.VOICE_MESSAGE;
|
const flag = SignalService.AttachmentPointer.Flags.VOICE_MESSAGE;
|
||||||
// eslint-disable-next-line no-bitwise
|
// eslint-disable-next-line no-bitwise
|
||||||
if (((attachment.flags || 0) & flag) === flag) {
|
if (((attachment.flags || 0) & flag) === flag) {
|
||||||
|
// Legacy data support for iOS
|
||||||
|
if (message.body) {
|
||||||
|
return Backups.MessageAttachment.Flag.NONE;
|
||||||
|
}
|
||||||
|
|
||||||
return Backups.MessageAttachment.Flag.VOICE_MESSAGE;
|
return Backups.MessageAttachment.Flag.VOICE_MESSAGE;
|
||||||
}
|
}
|
||||||
if (isGIF([attachment])) {
|
if (isGIF([attachment])) {
|
||||||
|
@ -2311,22 +2315,22 @@ export class BackupExportStream extends Readable {
|
||||||
async #processMessageAttachment({
|
async #processMessageAttachment({
|
||||||
attachment,
|
attachment,
|
||||||
backupLevel,
|
backupLevel,
|
||||||
messageReceivedAt,
|
message,
|
||||||
}: {
|
}: {
|
||||||
attachment: AttachmentType;
|
attachment: AttachmentType;
|
||||||
backupLevel: BackupLevel;
|
backupLevel: BackupLevel;
|
||||||
messageReceivedAt: number;
|
message: Pick<MessageAttributesType, 'quote' | 'received_at' | 'body'>;
|
||||||
}): Promise<Backups.MessageAttachment> {
|
}): Promise<Backups.MessageAttachment> {
|
||||||
const { clientUuid } = attachment;
|
const { clientUuid } = attachment;
|
||||||
const filePointer = await this.#processAttachment({
|
const filePointer = await this.#processAttachment({
|
||||||
attachment,
|
attachment,
|
||||||
backupLevel,
|
backupLevel,
|
||||||
messageReceivedAt,
|
messageReceivedAt: message.received_at,
|
||||||
});
|
});
|
||||||
|
|
||||||
return new Backups.MessageAttachment({
|
return new Backups.MessageAttachment({
|
||||||
pointer: filePointer,
|
pointer: filePointer,
|
||||||
flag: this.#getMessageAttachmentFlag(attachment),
|
flag: this.#getMessageAttachmentFlag(message, attachment),
|
||||||
wasDownloaded: isDownloaded(attachment),
|
wasDownloaded: isDownloaded(attachment),
|
||||||
clientUuid: clientUuid ? uuidToBytes(clientUuid) : undefined,
|
clientUuid: clientUuid ? uuidToBytes(clientUuid) : undefined,
|
||||||
});
|
});
|
||||||
|
@ -2550,9 +2554,8 @@ export class BackupExportStream extends Readable {
|
||||||
}): Promise<Backups.IStandardMessage> {
|
}): Promise<Backups.IStandardMessage> {
|
||||||
return {
|
return {
|
||||||
quote: await this.#toQuote({
|
quote: await this.#toQuote({
|
||||||
quote: message.quote,
|
message,
|
||||||
backupLevel,
|
backupLevel,
|
||||||
messageReceivedAt: message.received_at,
|
|
||||||
}),
|
}),
|
||||||
attachments: message.attachments?.length
|
attachments: message.attachments?.length
|
||||||
? await Promise.all(
|
? await Promise.all(
|
||||||
|
@ -2560,7 +2563,7 @@ export class BackupExportStream extends Readable {
|
||||||
return this.#processMessageAttachment({
|
return this.#processMessageAttachment({
|
||||||
attachment,
|
attachment,
|
||||||
backupLevel,
|
backupLevel,
|
||||||
messageReceivedAt: message.received_at,
|
message,
|
||||||
});
|
});
|
||||||
})
|
})
|
||||||
)
|
)
|
||||||
|
@ -2667,7 +2670,7 @@ export class BackupExportStream extends Readable {
|
||||||
: await this.#processMessageAttachment({
|
: await this.#processMessageAttachment({
|
||||||
attachment,
|
attachment,
|
||||||
backupLevel,
|
backupLevel,
|
||||||
messageReceivedAt: message.received_at,
|
message,
|
||||||
}),
|
}),
|
||||||
reactions: this.#getMessageReactions(message),
|
reactions: this.#getMessageReactions(message),
|
||||||
};
|
};
|
||||||
|
|
|
@ -355,6 +355,39 @@ describe('backup/attachments', () => {
|
||||||
{ backupLevel: BackupLevel.Paid }
|
{ backupLevel: BackupLevel.Paid }
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
it('drops voice message flag when body is present', async () => {
|
||||||
|
const attachment = composeAttachment(1);
|
||||||
|
attachment.contentType = AUDIO_MP3;
|
||||||
|
attachment.flags = SignalService.AttachmentPointer.Flags.VOICE_MESSAGE;
|
||||||
|
|
||||||
|
strictAssert(isVoiceMessage(attachment), 'it is a voice attachment');
|
||||||
|
strictAssert(attachment.digest, 'digest exists');
|
||||||
|
|
||||||
|
await asymmetricRoundtripHarness(
|
||||||
|
[
|
||||||
|
composeMessage(1, {
|
||||||
|
body: 'hello',
|
||||||
|
attachments: [attachment],
|
||||||
|
}),
|
||||||
|
],
|
||||||
|
[
|
||||||
|
composeMessage(1, {
|
||||||
|
body: 'hello',
|
||||||
|
hasAttachments: true,
|
||||||
|
attachments: [
|
||||||
|
{
|
||||||
|
...omit(attachment, NON_ROUNDTRIPPED_BACKUP_LOCATOR_FIELDS),
|
||||||
|
flags: undefined,
|
||||||
|
backupLocator: {
|
||||||
|
mediaName: digestToMediaName(attachment.digest),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
}),
|
||||||
|
],
|
||||||
|
{ backupLevel: BackupLevel.Paid }
|
||||||
|
);
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('Preview attachments', () => {
|
describe('Preview attachments', () => {
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue