feat: improving cloud sync manual mapping

This commit is contained in:
Chubby Granny Chaser 2024-10-22 13:34:34 +01:00
parent 7de6e96f63
commit bfcf8178d8
No known key found for this signature in database
15 changed files with 164 additions and 132 deletions

View file

@ -1,6 +1,8 @@
import { app } from "electron";
import path from "node:path";
export const LUDUSAVI_MANIFEST_URL = "https://cdn.losbroxas.org/manifest.yaml";
export const defaultDownloadsPath = app.getPath("downloads");
export const databaseDirectory = path.join(app.getPath("appData"), "hydra");

View file

@ -122,12 +122,9 @@ const downloadGameArtifact = async (
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.replaceAll(":", "_"),
objectId,
normalizePath(homeDir)
);

View file

@ -1,17 +1,13 @@
import { registerEvent } from "../register-event";
import type { GameShop } from "@types";
import { Ludusavi } from "@main/services";
import path from "node:path";
import { backupsPath } from "@main/constants";
const getGameBackupPreview = async (
_event: Electron.IpcMainInvokeEvent,
objectId: string,
shop: GameShop
) => {
const backupPath = path.join(backupsPath, `${shop}-${objectId}`);
return Ludusavi.getBackupPreview(shop, objectId, backupPath);
return Ludusavi.getBackupPreview(shop, objectId);
};
registerEvent("getGameBackupPreview", getGameBackupPreview);

View file

@ -0,0 +1,14 @@
import { registerEvent } from "../register-event";
import type { GameShop } from "@types";
import { Ludusavi } from "@main/services";
const selectGameBackupPath = async (
_event: Electron.IpcMainInvokeEvent,
_shop: GameShop,
objectId: string,
backupPath: string | null
) => {
return Ludusavi.addCustomGame(objectId, backupPath);
};
registerEvent("selectGameBackupPath", selectGameBackupPath);

View file

@ -65,6 +65,7 @@ import "./cloud-save/get-game-artifacts";
import "./cloud-save/get-game-backup-preview";
import "./cloud-save/upload-save-game";
import "./cloud-save/delete-game-artifact";
import "./cloud-save/select-game-backup-path";
import "./notifications/publish-new-repacks-notification";
import { isPortableVersion } from "@main/helpers";
import "./misc/show-item-in-folder";

View file

@ -7,6 +7,7 @@ import path from "node:path";
import YAML from "yaml";
import ludusaviWorkerPath from "../workers/ludusavi.worker?modulePath";
import { LUDUSAVI_MANIFEST_URL } from "@main/constants";
export class Ludusavi {
private static ludusaviPath = path.join(app.getPath("appData"), "ludusavi");
@ -25,15 +26,6 @@ export class Ludusavi {
},
});
static async findGames(shop: GameShop, objectId: string): Promise<string[]> {
const games = await this.worker.run(
{ objectId, shop },
{ name: "findGames" }
);
return games;
}
static async getConfig() {
if (!fs.existsSync(this.ludusaviConfigPath)) {
await this.worker.run(undefined, { name: "generateConfig" });
@ -47,36 +39,36 @@ export class Ludusavi {
}
static async backupGame(
shop: GameShop,
_shop: GameShop,
objectId: string,
backupPath: string,
winePrefix?: string | null
): Promise<LudusaviBackup> {
const games = await this.findGames(shop, objectId);
if (!games.length) throw new Error("Game not found");
return this.worker.run(
{ title: games[0], backupPath, winePrefix },
{ title: objectId, backupPath, winePrefix },
{ name: "backupGame" }
);
}
static async getBackupPreview(
shop: GameShop,
objectId: string,
backupPath: string
_shop: GameShop,
objectId: string
): Promise<LudusaviBackup | null> {
const games = await this.findGames(shop, objectId);
if (!games.length) return null;
const [game] = games;
const config = await this.getConfig();
const backupData = await this.worker.run(
{ title: game, backupPath, preview: true },
{ title: objectId, preview: true },
{ name: "backupGame" }
);
return backupData;
const customGame = config.customGames.find(
(game) => game.name === objectId
);
return {
...backupData,
customBackupPath: customGame?.files[0] || null,
};
}
static async restoreBackup(backupPath: string) {
@ -87,24 +79,24 @@ export class Ludusavi {
const config = await this.getConfig();
config.manifest.enable = false;
config.manifest.secondary = [
{ url: "https://cdn.losbroxas.org/manifest.yaml", enable: true },
];
config.manifest.secondary = [{ url: LUDUSAVI_MANIFEST_URL, enable: true }];
fs.writeFileSync(this.ludusaviConfigPath, YAML.stringify(config));
}
static async addCustomGame(title: string, savePath: string) {
static async addCustomGame(title: string, savePath: string | null) {
const config = await this.getConfig();
const filteredGames = config.customGames.filter(
(game) => game.name !== title
);
filteredGames.push({
name: title,
files: [savePath],
registry: [],
});
if (savePath) {
filteredGames.push({
name: title,
files: [savePath],
registry: [],
});
}
config.customGames = filteredGames;
fs.writeFileSync(this.ludusaviConfigPath, YAML.stringify(config));

View file

@ -1,29 +1,10 @@
import type { GameShop, LudusaviBackup, LudusaviFindResult } from "@types";
import type { LudusaviBackup } from "@types";
import cp from "node:child_process";
import { workerData } from "node:worker_threads";
const { binaryPath } = workerData;
export const findGames = ({
shop,
objectId,
}: {
shop: GameShop;
objectId: string;
}) => {
const args = ["find", "--api"];
if (shop === "steam") {
args.push("--steam-id", objectId);
}
const result = cp.execFileSync(binaryPath, args);
const games = JSON.parse(result.toString("utf-8")) as LudusaviFindResult;
return Object.keys(games.games);
};
export const backupGame = ({
title,
backupPath,
@ -35,7 +16,7 @@ export const backupGame = ({
preview?: boolean;
winePrefix?: string;
}) => {
const args = ["backup", `"${title}"`, "--api", "--force"];
const args = ["backup", title, "--api", "--force"];
if (preview) args.push("--preview");
if (backupPath) args.push("--path", backupPath);