diff --git a/protos/Backups.proto b/protos/Backups.proto index 41d0490e4..c08a3a0b9 100644 --- a/protos/Backups.proto +++ b/protos/Backups.proto @@ -1043,17 +1043,8 @@ message GroupExpirationTimerUpdate { message StickerPack { bytes packId = 1; bytes packKey = 2; - string title = 3; - string author = 4; - repeated StickerPackSticker stickers = 5; // First one should be cover sticker. } -message StickerPackSticker { - string emoji = 1; - uint32 id = 2; -} - - message ChatStyle { message Gradient { uint32 angle = 1; // degrees diff --git a/ts/services/backups/export.ts b/ts/services/backups/export.ts index 3c4aeb8e6..cffadd1e2 100644 --- a/ts/services/backups/export.ts +++ b/ts/services/backups/export.ts @@ -212,6 +212,7 @@ export class BackupExportStream extends Readable { distributionLists: 0, messages: 0, skippedMessages: 0, + stickerPacks: 0, }; for (const { attributes } of window.ConversationController.getAll()) { @@ -284,6 +285,21 @@ export class BackupExportStream extends Readable { stats.distributionLists += 1; } + const stickerPacks = await Data.getInstalledStickerPacks(); + + for (const { id, key } of stickerPacks) { + this.pushFrame({ + stickerPack: { + packId: Bytes.fromHex(id), + packKey: Bytes.fromBase64(key), + }, + }); + + // eslint-disable-next-line no-await-in-loop + await this.flush(); + stats.stickerPacks += 1; + } + const pinnedConversationIds = window.storage.get('pinnedConversationIds') || []; diff --git a/ts/services/backups/import.ts b/ts/services/backups/import.ts index 85e2f1af1..49ca1e9c9 100644 --- a/ts/services/backups/import.ts +++ b/ts/services/backups/import.ts @@ -26,6 +26,7 @@ import { import { STICKERPACK_ID_BYTE_LEN, STICKERPACK_KEY_BYTE_LEN, + downloadStickerPack, } from '../../types/Stickers'; import type { ConversationAttributesType, @@ -386,6 +387,8 @@ export class BackupImportStream extends Writable { } await this.fromChatItem(frame.chatItem, { aboutMe }); + } else if (frame.stickerPack) { + await this.fromStickerPack(frame.stickerPack); } else { log.warn(`${this.logId}: unsupported frame item ${frame.item}`); } @@ -2311,4 +2314,26 @@ export class BackupImportStream extends Writable { throw new Error('Not implemented'); } } + + private async fromStickerPack({ + packId: id, + packKey: key, + }: Backups.IStickerPack): Promise { + strictAssert( + id?.length === STICKERPACK_ID_BYTE_LEN, + 'Sticker pack must have a valid pack id' + ); + + const logId = `fromStickerPack(${Bytes.toHex(id).slice(-2)})`; + strictAssert( + key?.length === STICKERPACK_KEY_BYTE_LEN, + `${logId}: must have a valid pack key` + ); + + drop( + downloadStickerPack(Bytes.toHex(id), Bytes.toBase64(key), { + fromBackup: true, + }) + ); + } } diff --git a/ts/state/ducks/stickers.ts b/ts/state/ducks/stickers.ts index f1549b4cc..9ea7efb1b 100644 --- a/ts/state/ducks/stickers.ts +++ b/ts/state/ducks/stickers.ts @@ -214,7 +214,11 @@ function downloadStickerPack( function installStickerPack( packId: string, packKey: string, - options: { fromSync?: boolean; fromStorageService?: boolean } = {} + options: { + fromSync?: boolean; + fromStorageService?: boolean; + fromBackup?: boolean; + } = {} ): InstallStickerPackAction { return { type: 'stickers/INSTALL_STICKER_PACK', @@ -224,19 +228,27 @@ function installStickerPack( async function doInstallStickerPack( packId: string, packKey: string, - options: { fromSync?: boolean; fromStorageService?: boolean } = {} + options: { + fromSync?: boolean; + fromStorageService?: boolean; + fromBackup?: boolean; + } = {} ): Promise { - const { fromSync = false, fromStorageService = false } = options; + const { + fromSync = false, + fromStorageService = false, + fromBackup = false, + } = options; const timestamp = Date.now(); await dataInterface.installStickerPack(packId, timestamp); - if (!fromSync && !fromStorageService) { + if (!fromSync && !fromStorageService && !fromBackup) { // Kick this off, but don't wait for it void sendStickerPackSync(packId, packKey, true); } - if (!fromStorageService) { + if (!fromStorageService && !fromBackup) { storageServiceUploadJob(); } diff --git a/ts/types/Stickers.ts b/ts/types/Stickers.ts index 79544824b..9d859c10b 100644 --- a/ts/types/Stickers.ts +++ b/ts/types/Stickers.ts @@ -552,6 +552,7 @@ export type DownloadStickerPackOptions = Readonly<{ messageId?: string; fromSync?: boolean; fromStorageService?: boolean; + fromBackup?: boolean; finalStatus?: StickerPackStatusType; suppressError?: boolean; }>; @@ -582,6 +583,7 @@ async function doDownloadStickerPack( messageId, fromSync = false, fromStorageService = false, + fromBackup = false, suppressError = false, }: DownloadStickerPackOptions ): Promise { @@ -703,7 +705,7 @@ async function doDownloadStickerPack( status: 'pending', createdAt: Date.now(), stickers: {}, - storageNeedsSync: !fromStorageService, + storageNeedsSync: !fromStorageService && !fromBackup, title: proto.title ?? '', author: proto.author ?? '', }; @@ -788,6 +790,7 @@ async function doDownloadStickerPack( await installStickerPack(packId, packKey, { fromSync, fromStorageService, + fromBackup, }); } else { // Mark the pack as complete