diff --git a/src/main/constants.ts b/src/main/constants.ts index 91f9d008..4e2f1c00 100644 --- a/src/main/constants.ts +++ b/src/main/constants.ts @@ -20,5 +20,3 @@ export const seedsPath = app.isPackaged export const backupsPath = path.join(app.getPath("userData"), "Backups"); export const appVersion = app.getVersion(); - -export const artifactMetadataFileName = "hydra-launcher-metadata.json"; diff --git a/src/main/events/cloud-save/download-game-artifact.ts b/src/main/events/cloud-save/download-game-artifact.ts index b13a8137..00fae6aa 100644 --- a/src/main/events/cloud-save/download-game-artifact.ts +++ b/src/main/events/cloud-save/download-game-artifact.ts @@ -3,9 +3,10 @@ import fs from "node:fs"; import * as tar from "tar"; import { registerEvent } from "../register-event"; import axios from "axios"; +import os from "node:os"; import { app } from "electron"; import path from "node:path"; -import { artifactMetadataFileName, backupsPath } from "@main/constants"; +import { backupsPath } from "@main/constants"; import type { GameShop } from "@types"; import YAML from "yaml"; @@ -22,7 +23,8 @@ export interface LudusaviBackup { const replaceLudusaviBackupWithCurrentUser = ( backupPath: string, - title: string + title: string, + homeDir: string ) => { const gameBackupPath = path.join(backupPath, title); const mappingYamlPath = path.join(gameBackupPath, "mapping.yaml"); @@ -33,50 +35,26 @@ const replaceLudusaviBackupWithCurrentUser = ( drives: Record; }; - const metadataPath = path.join(backupPath, artifactMetadataFileName); - - if (!fs.existsSync(metadataPath)) { - logger.error(`metadata not found in backup ${gameBackupPath}`); - return; - } - - const metadata = JSON.parse(fs.readFileSync(metadataPath, "utf8")) as { - home: string; - documents: string; - }; - const currentHomeDir = normalizePath(app.getPath("home")); - const currentDocumentsDir = normalizePath(app.getPath("documents")); /* Renaming logic */ - const mappedHomeDir = path.join( - gameBackupPath, - metadata.home.replace("C:", "drive-C") - ); - const mappedDocumentsDir = path.join( - gameBackupPath, - metadata.documents.replace("C:", "drive-C") - ); - - if (fs.existsSync(mappedHomeDir)) { - fs.renameSync( - mappedHomeDir, - path.join(gameBackupPath, currentHomeDir.replace("C:", "drive-C")) + if (os.platform() === "win32") { + const mappedHomeDir = path.join( + gameBackupPath, + path.join("drive-C", homeDir.replace("C:", "")) ); - } - if (fs.existsSync(mappedDocumentsDir)) { - fs.renameSync( - mappedDocumentsDir, - path.join(gameBackupPath, currentDocumentsDir.replace("C:", "drive-C")) - ); + if (fs.existsSync(mappedHomeDir)) { + fs.renameSync( + mappedHomeDir, + path.join(gameBackupPath, "drive-C", currentHomeDir.replace("C:", "")) + ); + } } const backups = manifest.backups.map((backup: LudusaviBackup) => { const files = Object.entries(backup.files).reduce((prev, [key, value]) => { - const updatedKey = key - .replace(metadata.documents, currentDocumentsDir) - .replace(metadata.home, currentHomeDir); + const updatedKey = key.replace(homeDir, currentHomeDir); return { ...prev, @@ -99,62 +77,70 @@ const downloadGameArtifact = async ( shop: GameShop, gameArtifactId: string ) => { - const { downloadUrl, objectKey } = await HydraApi.post<{ - downloadUrl: string; - objectKey: string; - }>(`/profile/games/artifacts/${gameArtifactId}/download`); + try { + const { downloadUrl, objectKey, homeDir } = await HydraApi.post<{ + downloadUrl: string; + objectKey: string; + homeDir: string; + }>(`/profile/games/artifacts/${gameArtifactId}/download`); - const zipLocation = path.join(app.getPath("userData"), objectKey); - const backupPath = path.join(backupsPath, `${shop}-${objectId}`); + const zipLocation = path.join(app.getPath("userData"), objectKey); + const backupPath = path.join(backupsPath, `${shop}-${objectId}`); - if (fs.existsSync(backupPath)) { - fs.rmSync(backupPath, { - recursive: true, - force: true, - }); - } - - const response = await axios.get(downloadUrl, { - responseType: "stream", - onDownloadProgress: (progressEvent) => { - WindowManager.mainWindow?.webContents.send( - `on-backup-download-progress-${objectId}-${shop}`, - progressEvent - ); - }, - }); - - const writer = fs.createWriteStream(zipLocation); - - response.data.pipe(writer); - - writer.on("error", (err) => { - logger.error("Failed to write zip", err); - throw err; - }); - - fs.mkdirSync(backupPath, { recursive: true }); - - writer.on("close", () => { - tar - .x({ - file: zipLocation, - cwd: backupPath, - }) - .then(async () => { - const [game] = await Ludusavi.findGames(shop, objectId); - if (!game) throw new Error("Game not found in Ludusavi manifest"); - - replaceLudusaviBackupWithCurrentUser(backupPath, game); - - Ludusavi.restoreBackup(backupPath).then(() => { - WindowManager.mainWindow?.webContents.send( - `on-backup-download-complete-${objectId}-${shop}`, - true - ); - }); + if (fs.existsSync(backupPath)) { + fs.rmSync(backupPath, { + recursive: true, + force: true, }); - }); + } + + const response = await axios.get(downloadUrl, { + responseType: "stream", + onDownloadProgress: (progressEvent) => { + WindowManager.mainWindow?.webContents.send( + `on-backup-download-progress-${objectId}-${shop}`, + progressEvent + ); + }, + }); + + const writer = fs.createWriteStream(zipLocation); + + response.data.pipe(writer); + + writer.on("error", (err) => { + logger.error("Failed to write zip", err); + throw err; + }); + + fs.mkdirSync(backupPath, { recursive: true }); + + writer.on("close", () => { + tar + .x({ + file: zipLocation, + cwd: backupPath, + }) + .then(async () => { + const [game] = await Ludusavi.findGames(shop, objectId); + if (!game) throw new Error("Game not found in Ludusavi manifest"); + + replaceLudusaviBackupWithCurrentUser(backupPath, game, homeDir); + + Ludusavi.restoreBackup(backupPath).then(() => { + WindowManager.mainWindow?.webContents.send( + `on-backup-download-complete-${objectId}-${shop}`, + true + ); + }); + }); + }); + } catch (err) { + WindowManager.mainWindow?.webContents.send( + `on-backup-download-complete-${objectId}-${shop}`, + false + ); + } }; registerEvent("downloadGameArtifact", downloadGameArtifact); diff --git a/src/main/events/cloud-save/upload-save-game.ts b/src/main/events/cloud-save/upload-save-game.ts index 5e133c9f..b66fd081 100644 --- a/src/main/events/cloud-save/upload-save-game.ts +++ b/src/main/events/cloud-save/upload-save-game.ts @@ -7,7 +7,7 @@ import crypto from "node:crypto"; import { GameShop } from "@types"; import axios from "axios"; import os from "node:os"; -import { artifactMetadataFileName, backupsPath } from "@main/constants"; +import { backupsPath } from "@main/constants"; import { app } from "electron"; import { normalizePath } from "@main/helpers"; @@ -21,22 +21,7 @@ const bundleBackup = async (shop: GameShop, objectId: string) => { await Ludusavi.backupGame(shop, objectId, backupPath); - const tarLocation = path.join(backupsPath, `${crypto.randomUUID()}.zip`); - - fs.writeFileSync( - path.join(backupPath, artifactMetadataFileName), - JSON.stringify({ - home: normalizePath(app.getPath("home")), - documents: normalizePath(app.getPath("documents")), - }) - ); - - console.log( - JSON.stringify({ - home: normalizePath(app.getPath("home")), - documents: normalizePath(app.getPath("documents")), - }) - ); + const tarLocation = path.join(backupsPath, `${crypto.randomUUID()}.tar`); await tar.create( {