Add downloadPath to attachments after import to support resumable download
Co-authored-by: trevor-signal <131492920+trevor-signal@users.noreply.github.com>
This commit is contained in:
parent
ca0468ec27
commit
f0c2abc30c
3 changed files with 52 additions and 6 deletions
|
@ -2,6 +2,7 @@
|
||||||
// SPDX-License-Identifier: AGPL-3.0-only
|
// SPDX-License-Identifier: AGPL-3.0-only
|
||||||
import Long from 'long';
|
import Long from 'long';
|
||||||
import { BackupLevel } from '@signalapp/libsignal-client/zkgroup';
|
import { BackupLevel } from '@signalapp/libsignal-client/zkgroup';
|
||||||
|
import { omit } from 'lodash';
|
||||||
|
|
||||||
import {
|
import {
|
||||||
APPLICATION_OCTET_STREAM,
|
APPLICATION_OCTET_STREAM,
|
||||||
|
@ -39,9 +40,12 @@ import { redactGenericText } from '../../../util/privacy';
|
||||||
import { missingCaseError } from '../../../util/missingCaseError';
|
import { missingCaseError } from '../../../util/missingCaseError';
|
||||||
import { toLogFormat } from '../../../types/errors';
|
import { toLogFormat } from '../../../types/errors';
|
||||||
import { bytesToUuid } from '../../../util/uuidToBytes';
|
import { bytesToUuid } from '../../../util/uuidToBytes';
|
||||||
|
import { createName } from '../../../util/attachmentPath';
|
||||||
|
|
||||||
export function convertFilePointerToAttachment(
|
export function convertFilePointerToAttachment(
|
||||||
filePointer: Backups.FilePointer
|
filePointer: Backups.FilePointer,
|
||||||
|
// Only for testing
|
||||||
|
{ _createName: doCreateName = createName } = {}
|
||||||
): AttachmentType {
|
): AttachmentType {
|
||||||
const {
|
const {
|
||||||
contentType,
|
contentType,
|
||||||
|
@ -70,6 +74,7 @@ export function convertFilePointerToAttachment(
|
||||||
? Bytes.toBase64(incrementalMac)
|
? Bytes.toBase64(incrementalMac)
|
||||||
: undefined,
|
: undefined,
|
||||||
incrementalMacChunkSize: incrementalMacChunkSize ?? undefined,
|
incrementalMacChunkSize: incrementalMacChunkSize ?? undefined,
|
||||||
|
downloadPath: doCreateName(),
|
||||||
};
|
};
|
||||||
|
|
||||||
if (attachmentLocator) {
|
if (attachmentLocator) {
|
||||||
|
@ -117,7 +122,7 @@ export function convertFilePointerToAttachment(
|
||||||
|
|
||||||
if (invalidAttachmentLocator) {
|
if (invalidAttachmentLocator) {
|
||||||
return {
|
return {
|
||||||
...commonProps,
|
...omit(commonProps, 'downloadPath'),
|
||||||
error: true,
|
error: true,
|
||||||
size: 0,
|
size: 0,
|
||||||
};
|
};
|
||||||
|
|
|
@ -40,7 +40,8 @@ describe('convertFilePointerToAttachment', () => {
|
||||||
digest: Bytes.fromString('digest'),
|
digest: Bytes.fromString('digest'),
|
||||||
uploadTimestamp: Long.fromNumber(1970),
|
uploadTimestamp: Long.fromNumber(1970),
|
||||||
}),
|
}),
|
||||||
})
|
}),
|
||||||
|
{ _createName: () => 'downloadPath' }
|
||||||
);
|
);
|
||||||
|
|
||||||
assert.deepStrictEqual(result, {
|
assert.deepStrictEqual(result, {
|
||||||
|
@ -58,6 +59,7 @@ describe('convertFilePointerToAttachment', () => {
|
||||||
uploadTimestamp: 1970,
|
uploadTimestamp: 1970,
|
||||||
incrementalMac: Bytes.toBase64(Bytes.fromString('incrementalMac')),
|
incrementalMac: Bytes.toBase64(Bytes.fromString('incrementalMac')),
|
||||||
incrementalMacChunkSize: 1000,
|
incrementalMacChunkSize: 1000,
|
||||||
|
downloadPath: 'downloadPath',
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -81,7 +83,8 @@ describe('convertFilePointerToAttachment', () => {
|
||||||
transitCdnKey: 'transitCdnKey',
|
transitCdnKey: 'transitCdnKey',
|
||||||
transitCdnNumber: 2,
|
transitCdnNumber: 2,
|
||||||
}),
|
}),
|
||||||
})
|
}),
|
||||||
|
{ _createName: () => 'downloadPath' }
|
||||||
);
|
);
|
||||||
|
|
||||||
assert.deepStrictEqual(result, {
|
assert.deepStrictEqual(result, {
|
||||||
|
@ -102,6 +105,7 @@ describe('convertFilePointerToAttachment', () => {
|
||||||
mediaName: 'mediaName',
|
mediaName: 'mediaName',
|
||||||
cdnNumber: 3,
|
cdnNumber: 3,
|
||||||
},
|
},
|
||||||
|
downloadPath: 'downloadPath',
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -139,12 +143,14 @@ describe('convertFilePointerToAttachment', () => {
|
||||||
const result = convertFilePointerToAttachment(
|
const result = convertFilePointerToAttachment(
|
||||||
new Backups.FilePointer({
|
new Backups.FilePointer({
|
||||||
backupLocator: new Backups.FilePointer.BackupLocator(),
|
backupLocator: new Backups.FilePointer.BackupLocator(),
|
||||||
})
|
}),
|
||||||
|
{ _createName: () => 'downloadPath' }
|
||||||
);
|
);
|
||||||
|
|
||||||
assert.deepStrictEqual(result, {
|
assert.deepStrictEqual(result, {
|
||||||
contentType: APPLICATION_OCTET_STREAM,
|
contentType: APPLICATION_OCTET_STREAM,
|
||||||
size: 0,
|
size: 0,
|
||||||
|
downloadPath: 'downloadPath',
|
||||||
width: undefined,
|
width: undefined,
|
||||||
height: undefined,
|
height: undefined,
|
||||||
blurHash: undefined,
|
blurHash: undefined,
|
||||||
|
|
|
@ -4,7 +4,7 @@
|
||||||
import { assert } from 'chai';
|
import { assert } from 'chai';
|
||||||
import path from 'path';
|
import path from 'path';
|
||||||
import { tmpdir } from 'os';
|
import { tmpdir } from 'os';
|
||||||
import { sortBy } from 'lodash';
|
import { omit, sortBy } from 'lodash';
|
||||||
import { createReadStream } from 'fs';
|
import { createReadStream } from 'fs';
|
||||||
import { mkdtemp, rm } from 'fs/promises';
|
import { mkdtemp, rm } from 'fs/promises';
|
||||||
import * as sinon from 'sinon';
|
import * as sinon from 'sinon';
|
||||||
|
@ -65,6 +65,11 @@ function sortAndNormalize(
|
||||||
reactions,
|
reactions,
|
||||||
sendStateByConversationId,
|
sendStateByConversationId,
|
||||||
verifiedChanged,
|
verifiedChanged,
|
||||||
|
attachments,
|
||||||
|
preview,
|
||||||
|
contact,
|
||||||
|
quote,
|
||||||
|
sticker,
|
||||||
|
|
||||||
// This is not in the backup
|
// This is not in the backup
|
||||||
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||||||
|
@ -122,6 +127,36 @@ function sortAndNormalize(
|
||||||
};
|
};
|
||||||
}),
|
}),
|
||||||
|
|
||||||
|
attachments: attachments?.map(attachment =>
|
||||||
|
omit(attachment, 'downloadPath')
|
||||||
|
),
|
||||||
|
preview: preview?.map(previewItem => ({
|
||||||
|
...previewItem,
|
||||||
|
image: omit(previewItem.image, 'downloadPath'),
|
||||||
|
})),
|
||||||
|
contact: contact?.map(contactItem => ({
|
||||||
|
...contactItem,
|
||||||
|
avatar: {
|
||||||
|
...contactItem.avatar,
|
||||||
|
avatar: omit(contactItem.avatar?.avatar, 'downloadPath'),
|
||||||
|
},
|
||||||
|
})),
|
||||||
|
quote: quote
|
||||||
|
? {
|
||||||
|
...quote,
|
||||||
|
attachments: quote?.attachments.map(quotedAttachment => ({
|
||||||
|
...quotedAttachment,
|
||||||
|
thumbnail: omit(quotedAttachment.thumbnail, 'downloadPath'),
|
||||||
|
})),
|
||||||
|
}
|
||||||
|
: undefined,
|
||||||
|
sticker: sticker
|
||||||
|
? {
|
||||||
|
...sticker,
|
||||||
|
data: omit(sticker.data, 'downloadPath'),
|
||||||
|
}
|
||||||
|
: undefined,
|
||||||
|
|
||||||
// Not an original property, but useful
|
// Not an original property, but useful
|
||||||
isUnsupported: isUnsupportedMessage(message),
|
isUnsupported: isUnsupportedMessage(message),
|
||||||
})
|
})
|
||||||
|
|
Loading…
Reference in a new issue