feat: adding initial download sources

This commit is contained in:
Chubby Granny Chaser
2025-04-01 21:39:54 +01:00
parent 73f4b0e869
commit 0d75878b07
41 changed files with 306 additions and 520 deletions

38
src/main/services/7zip.ts Normal file
View File

@@ -0,0 +1,38 @@
import { app } from "electron";
import cp from "node:child_process";
import path from "node:path";
export const binaryName = {
linux: "7zzs",
darwin: "7zz",
win32: "7zr.exe",
};
export class _7Zip {
private static readonly binaryPath = app.isPackaged
? path.join(process.resourcesPath, binaryName[process.platform])
: path.join(
__dirname,
"..",
"..",
"binaries",
binaryName[process.platform]
);
public static extractFile(
filePath: string,
outputPath: string,
cb: () => void
) {
const child = cp.spawn(this.binaryPath, [
"x",
filePath,
"-o" + outputPath,
"-y",
]);
child.on("exit", () => {
cb();
});
}
}

View File

@@ -2,18 +2,15 @@ import path from "node:path";
import cp from "node:child_process";
import { app } from "electron";
export const startAria2 = () => {};
export class Aria2 {
private static process: cp.ChildProcess | null = null;
private static readonly binaryPath = app.isPackaged
? path.join(process.resourcesPath, "aria2", "aria2c")
: path.join(__dirname, "..", "..", "aria2", "aria2c");
public static spawn() {
const binaryPath = app.isPackaged
? path.join(process.resourcesPath, "aria2", "aria2c")
: path.join(__dirname, "..", "..", "aria2", "aria2c");
this.process = cp.spawn(
binaryPath,
this.binaryPath,
[
"--enable-rpc",
"--rpc-listen-all",

View File

@@ -1,6 +1,9 @@
import { Downloader, DownloadError } from "@shared";
import { WindowManager } from "../window-manager";
import { publishDownloadCompleteNotification } from "../notifications";
import {
publishDownloadCompleteNotification,
publishExtractionCompleteNotification,
} from "../notifications";
import type { Download, DownloadProgress, UserPreferences } from "@types";
import {
GofileApi,
@@ -22,9 +25,11 @@ import { logger } from "../logger";
import { db, downloadsSublevel, gamesSublevel, levelKeys } from "@main/level";
import { sortBy } from "lodash-es";
import { TorBoxClient } from "./torbox";
import { _7Zip } from "../7zip";
export class DownloadManager {
private static downloadingGameId: string | null = null;
private static readonly extensionsToExtract = [".rar", ".zip", ".7z"];
public static async startRPC(
download?: Download,
@@ -150,13 +155,47 @@ export class DownloadManager {
queued: false,
});
} else {
const shouldExtract =
download.downloader !== Downloader.Torrent &&
this.extensionsToExtract.some((ext) =>
download.folderName?.endsWith(ext)
) &&
download.automaticallyExtract;
downloadsSublevel.put(gameId, {
...download,
status: "complete",
shouldSeed: false,
queued: false,
extracting: shouldExtract,
});
if (shouldExtract) {
_7Zip.extractFile(
path.join(download.downloadPath, download.folderName!),
path.join(
download.downloadPath,
path.parse(download.folderName!).name
),
async () => {
const download = await downloadsSublevel.get(gameId);
downloadsSublevel.put(gameId, {
...download!,
extracting: false,
});
WindowManager.mainWindow?.webContents.send(
"on-extraction-complete",
game.shop,
game.objectId
);
publishExtractionCompleteNotification(game);
}
);
}
this.cancelDownload(gameId);
}

View File

@@ -8,3 +8,4 @@ export * from "./main-loop";
export * from "./hydra-api";
export * from "./ludusavi";
export * from "./cloud-sync";
export * from "./7zip";

View File

@@ -128,6 +128,17 @@ export const publishCombinedNewAchievementNotification = async (
}
};
export const publishExtractionCompleteNotification = async (game: Game) => {
new Notification({
title: t("extraction_complete", { ns: "notifications" }),
body: t("game_extracted", {
ns: "notifications",
title: game.title,
}),
icon: trayIcon,
}).show();
};
export const publishNewAchievementNotification = async (info: {
achievements: { displayName: string; iconUrl: string }[];
unlockedAchievementCount: number;

View File

@@ -6,9 +6,9 @@ import axios from "axios";
import { exec } from "child_process";
import { ProcessPayload } from "./download/types";
import { gamesSublevel, levelKeys } from "@main/level";
import { t } from "i18next";
import i18next, { t } from "i18next";
import { CloudSync } from "./cloud-sync";
import { format } from "date-fns";
import { formatDate } from "date-fns";
const commands = {
findWineDir: `lsof -c wine 2>/dev/null | grep '/drive_c/windows$' | head -n 1 | awk '{for(i=9;i<=NF;i++) printf "%s ", $i; print ""}'`,
@@ -229,6 +229,8 @@ function onOpenGame(game: Game) {
if (game.remoteId) {
updateGamePlaytime(game, 0, new Date()).catch(() => {});
const { language } = i18next;
if (game.automaticCloudSync) {
CloudSync.uploadSaveGame(
game.objectId,
@@ -236,7 +238,7 @@ function onOpenGame(game: Game) {
null,
t("automatic_backup_from", {
ns: "game_details",
date: format(new Date(), "dd/MM/yyyy"),
date: formatDate(new Date(), language),
})
);
}
@@ -296,6 +298,8 @@ const onCloseGame = (game: Game) => {
)!;
gamesPlaytime.delete(levelKeys.game(game.shop, game.objectId));
const { language } = i18next;
if (game.remoteId) {
updateGamePlaytime(
game,
@@ -310,7 +314,7 @@ const onCloseGame = (game: Game) => {
null,
t("automatic_backup_from", {
ns: "game_details",
date: format(new Date(), "dd/MM/yyyy"),
date: formatDate(new Date(), language),
})
);
}