mirror of
https://github.com/signalapp/Signal-Desktop.git
synced 2025-12-20 10:19:08 +00:00
Fix roundtripping of voice notes with body
This commit is contained in:
@@ -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', () => {
|
||||||
|
|||||||
Reference in New Issue
Block a user