// Copyright 2024 Signal Messenger, LLC // SPDX-License-Identifier: AGPL-3.0-only import { strictAssert } from '../../util/assert'; import { tusUpload } from '../../util/uploads/tusProtocol'; import { defaultFileReader } from '../../util/uploads/uploads'; import type { WebAPIType, AttachmentV3ResponseType, GetBackupInfoResponseType, BackupMediaItemType, BackupMediaBatchResponseType, BackupListMediaResponseType, } from '../../textsecure/WebAPI'; import type { BackupCredentials } from './credentials'; export class BackupAPI { private cachedBackupInfo: GetBackupInfoResponseType | undefined; constructor(private credentials: BackupCredentials) {} public async refresh(): Promise { // TODO: DESKTOP-6979 await this.server.refreshBackup( await this.credentials.getHeadersForToday() ); } public async getInfo(): Promise { const backupInfo = await this.server.getBackupInfo( await this.credentials.getHeadersForToday() ); this.cachedBackupInfo = backupInfo; return backupInfo; } private async getCachedInfo(): Promise { if (this.cachedBackupInfo) { return this.cachedBackupInfo; } return this.getInfo(); } public async getMediaDir(): Promise { return (await this.getCachedInfo()).mediaDir; } public async getBackupDir(): Promise { return (await this.getCachedInfo())?.backupDir; } // Backup name will change whenever a new backup is created, so we don't want to cache // it public async getBackupName(): Promise { return (await this.getInfo()).backupName; } public async upload(filePath: string, fileSize: number): Promise { const form = await this.server.getBackupUploadForm( await this.credentials.getHeadersForToday() ); const fetchFn = this.server.createFetchForAttachmentUpload(form); await tusUpload({ endpoint: form.signedUploadLocation, headers: {}, fileName: form.key, filePath, fileSize, reader: defaultFileReader, fetchFn, }); } public async getMediaUploadForm(): Promise { return this.server.getBackupMediaUploadForm( await this.credentials.getHeadersForToday() ); } public async backupMediaBatch( items: ReadonlyArray ): Promise { return this.server.backupMediaBatch({ headers: await this.credentials.getHeadersForToday(), items, }); } public async listMedia({ cursor, limit, }: { cursor?: string; limit: number; }): Promise { return this.server.backupListMedia({ headers: await this.credentials.getHeadersForToday(), cursor, limit, }); } public clearCache(): void { this.cachedBackupInfo = undefined; } private get server(): WebAPIType { const { server } = window.textsecure; strictAssert(server, 'server not available'); return server; } }