Import/export sticker packs
Co-authored-by: Fedor Indutny <79877362+indutny-signal@users.noreply.github.com>
This commit is contained in:
parent
d426109734
commit
a0fb131294
5 changed files with 62 additions and 15 deletions
|
@ -1043,17 +1043,8 @@ message GroupExpirationTimerUpdate {
|
||||||
message StickerPack {
|
message StickerPack {
|
||||||
bytes packId = 1;
|
bytes packId = 1;
|
||||||
bytes packKey = 2;
|
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 ChatStyle {
|
||||||
message Gradient {
|
message Gradient {
|
||||||
uint32 angle = 1; // degrees
|
uint32 angle = 1; // degrees
|
||||||
|
|
|
@ -212,6 +212,7 @@ export class BackupExportStream extends Readable {
|
||||||
distributionLists: 0,
|
distributionLists: 0,
|
||||||
messages: 0,
|
messages: 0,
|
||||||
skippedMessages: 0,
|
skippedMessages: 0,
|
||||||
|
stickerPacks: 0,
|
||||||
};
|
};
|
||||||
|
|
||||||
for (const { attributes } of window.ConversationController.getAll()) {
|
for (const { attributes } of window.ConversationController.getAll()) {
|
||||||
|
@ -284,6 +285,21 @@ export class BackupExportStream extends Readable {
|
||||||
stats.distributionLists += 1;
|
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 =
|
const pinnedConversationIds =
|
||||||
window.storage.get('pinnedConversationIds') || [];
|
window.storage.get('pinnedConversationIds') || [];
|
||||||
|
|
||||||
|
|
|
@ -26,6 +26,7 @@ import {
|
||||||
import {
|
import {
|
||||||
STICKERPACK_ID_BYTE_LEN,
|
STICKERPACK_ID_BYTE_LEN,
|
||||||
STICKERPACK_KEY_BYTE_LEN,
|
STICKERPACK_KEY_BYTE_LEN,
|
||||||
|
downloadStickerPack,
|
||||||
} from '../../types/Stickers';
|
} from '../../types/Stickers';
|
||||||
import type {
|
import type {
|
||||||
ConversationAttributesType,
|
ConversationAttributesType,
|
||||||
|
@ -386,6 +387,8 @@ export class BackupImportStream extends Writable {
|
||||||
}
|
}
|
||||||
|
|
||||||
await this.fromChatItem(frame.chatItem, { aboutMe });
|
await this.fromChatItem(frame.chatItem, { aboutMe });
|
||||||
|
} else if (frame.stickerPack) {
|
||||||
|
await this.fromStickerPack(frame.stickerPack);
|
||||||
} else {
|
} else {
|
||||||
log.warn(`${this.logId}: unsupported frame item ${frame.item}`);
|
log.warn(`${this.logId}: unsupported frame item ${frame.item}`);
|
||||||
}
|
}
|
||||||
|
@ -2311,4 +2314,26 @@ export class BackupImportStream extends Writable {
|
||||||
throw new Error('Not implemented');
|
throw new Error('Not implemented');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private async fromStickerPack({
|
||||||
|
packId: id,
|
||||||
|
packKey: key,
|
||||||
|
}: Backups.IStickerPack): Promise<void> {
|
||||||
|
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,
|
||||||
|
})
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -214,7 +214,11 @@ function downloadStickerPack(
|
||||||
function installStickerPack(
|
function installStickerPack(
|
||||||
packId: string,
|
packId: string,
|
||||||
packKey: string,
|
packKey: string,
|
||||||
options: { fromSync?: boolean; fromStorageService?: boolean } = {}
|
options: {
|
||||||
|
fromSync?: boolean;
|
||||||
|
fromStorageService?: boolean;
|
||||||
|
fromBackup?: boolean;
|
||||||
|
} = {}
|
||||||
): InstallStickerPackAction {
|
): InstallStickerPackAction {
|
||||||
return {
|
return {
|
||||||
type: 'stickers/INSTALL_STICKER_PACK',
|
type: 'stickers/INSTALL_STICKER_PACK',
|
||||||
|
@ -224,19 +228,27 @@ function installStickerPack(
|
||||||
async function doInstallStickerPack(
|
async function doInstallStickerPack(
|
||||||
packId: string,
|
packId: string,
|
||||||
packKey: string,
|
packKey: string,
|
||||||
options: { fromSync?: boolean; fromStorageService?: boolean } = {}
|
options: {
|
||||||
|
fromSync?: boolean;
|
||||||
|
fromStorageService?: boolean;
|
||||||
|
fromBackup?: boolean;
|
||||||
|
} = {}
|
||||||
): Promise<InstallStickerPackPayloadType> {
|
): Promise<InstallStickerPackPayloadType> {
|
||||||
const { fromSync = false, fromStorageService = false } = options;
|
const {
|
||||||
|
fromSync = false,
|
||||||
|
fromStorageService = false,
|
||||||
|
fromBackup = false,
|
||||||
|
} = options;
|
||||||
|
|
||||||
const timestamp = Date.now();
|
const timestamp = Date.now();
|
||||||
await dataInterface.installStickerPack(packId, timestamp);
|
await dataInterface.installStickerPack(packId, timestamp);
|
||||||
|
|
||||||
if (!fromSync && !fromStorageService) {
|
if (!fromSync && !fromStorageService && !fromBackup) {
|
||||||
// Kick this off, but don't wait for it
|
// Kick this off, but don't wait for it
|
||||||
void sendStickerPackSync(packId, packKey, true);
|
void sendStickerPackSync(packId, packKey, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!fromStorageService) {
|
if (!fromStorageService && !fromBackup) {
|
||||||
storageServiceUploadJob();
|
storageServiceUploadJob();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -552,6 +552,7 @@ export type DownloadStickerPackOptions = Readonly<{
|
||||||
messageId?: string;
|
messageId?: string;
|
||||||
fromSync?: boolean;
|
fromSync?: boolean;
|
||||||
fromStorageService?: boolean;
|
fromStorageService?: boolean;
|
||||||
|
fromBackup?: boolean;
|
||||||
finalStatus?: StickerPackStatusType;
|
finalStatus?: StickerPackStatusType;
|
||||||
suppressError?: boolean;
|
suppressError?: boolean;
|
||||||
}>;
|
}>;
|
||||||
|
@ -582,6 +583,7 @@ async function doDownloadStickerPack(
|
||||||
messageId,
|
messageId,
|
||||||
fromSync = false,
|
fromSync = false,
|
||||||
fromStorageService = false,
|
fromStorageService = false,
|
||||||
|
fromBackup = false,
|
||||||
suppressError = false,
|
suppressError = false,
|
||||||
}: DownloadStickerPackOptions
|
}: DownloadStickerPackOptions
|
||||||
): Promise<void> {
|
): Promise<void> {
|
||||||
|
@ -703,7 +705,7 @@ async function doDownloadStickerPack(
|
||||||
status: 'pending',
|
status: 'pending',
|
||||||
createdAt: Date.now(),
|
createdAt: Date.now(),
|
||||||
stickers: {},
|
stickers: {},
|
||||||
storageNeedsSync: !fromStorageService,
|
storageNeedsSync: !fromStorageService && !fromBackup,
|
||||||
title: proto.title ?? '',
|
title: proto.title ?? '',
|
||||||
author: proto.author ?? '',
|
author: proto.author ?? '',
|
||||||
};
|
};
|
||||||
|
@ -788,6 +790,7 @@ async function doDownloadStickerPack(
|
||||||
await installStickerPack(packId, packKey, {
|
await installStickerPack(packId, packKey, {
|
||||||
fromSync,
|
fromSync,
|
||||||
fromStorageService,
|
fromStorageService,
|
||||||
|
fromBackup,
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
// Mark the pack as complete
|
// Mark the pack as complete
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue