Files
hydra/src/main/events/cloud-save/upload-save-game.ts
Zamitto 3d571edccb Merge branch 'feat/migration-to-leveldb' into feature/torbox-integration
# Conflicts:
#	src/locales/en/translation.json
#	src/locales/pt-BR/translation.json
#	src/main/entity/user-preferences.entity.ts
#	src/main/events/auth/sign-out.ts
#	src/main/knex-client.ts
#	src/main/main.ts
#	src/main/services/download/download-manager.ts
#	src/main/services/process-watcher.ts
#	src/renderer/src/pages/downloads/download-group.tsx
#	src/types/index.ts
#	src/types/torbox.types.ts
2025-02-01 15:43:32 -03:00

115 lines
2.8 KiB
TypeScript

import { HydraApi, logger, Ludusavi, WindowManager } from "@main/services";
import { registerEvent } from "../register-event";
import fs from "node:fs";
import path from "node:path";
import * as tar from "tar";
import crypto from "node:crypto";
import type { GameShop } from "@types";
import axios from "axios";
import os from "node:os";
import { backupsPath } from "@main/constants";
import { app } from "electron";
import { normalizePath } from "@main/helpers";
import { gamesSublevel, levelKeys } from "@main/level";
const bundleBackup = async (
shop: GameShop,
objectId: string,
winePrefix: string | null
) => {
const backupPath = path.join(backupsPath, `${shop}-${objectId}`);
// Remove existing backup
if (fs.existsSync(backupPath)) {
fs.rmSync(backupPath, { recursive: true });
}
await Ludusavi.backupGame(shop, objectId, backupPath, winePrefix);
const tarLocation = path.join(backupsPath, `${crypto.randomUUID()}.tar`);
await tar.create(
{
gzip: false,
file: tarLocation,
cwd: backupPath,
},
["."]
);
return tarLocation;
};
export const createBackup = async (
objectId: string,
shop: GameShop,
downloadOptionTitle: string | null
) => {
const game = await gamesSublevel.get(levelKeys.game(shop, objectId));
const bundleLocation = await bundleBackup(
shop,
objectId,
game?.winePrefixPath ?? null
);
fs.stat(bundleLocation, async (err, stat) => {
if (err) {
logger.error("Failed to get zip file stats", err);
throw err;
}
const { uploadUrl } = await HydraApi.post<{
id: string;
uploadUrl: string;
}>("/profile/games/artifacts", {
artifactLengthInBytes: stat.size,
shop,
objectId,
hostname: os.hostname(),
homeDir: normalizePath(app.getPath("home")),
downloadOptionTitle,
platform: os.platform(),
});
fs.readFile(bundleLocation, async (err, fileBuffer) => {
if (err) {
logger.error("Failed to read zip file", err);
throw err;
}
await axios.put(uploadUrl, fileBuffer, {
headers: {
"Content-Type": "application/tar",
},
onUploadProgress: (progressEvent) => {
logger.log(progressEvent);
},
});
WindowManager.mainWindow?.webContents.send(
`on-upload-complete-${objectId}-${shop}`,
true
);
fs.rm(bundleLocation, (err) => {
if (err) {
logger.error("Failed to remove tar file", err);
throw err;
}
});
});
});
};
const uploadSaveGame = async (
_event: Electron.IpcMainInvokeEvent,
objectId: string,
shop: GameShop,
downloadOptionTitle: string | null
) => {
return createBackup(objectId, shop, downloadOptionTitle);
};
registerEvent("uploadSaveGame", uploadSaveGame);