From 07b1b059afa374c819de77c5de1bf3a79e276adc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Michal=20Marget=C3=ADn?= <86981961+SharkStudiosSK@users.noreply.github.com> Date: Fri, 31 Jan 2025 23:14:54 +0100 Subject: [PATCH] Add unzip functionality for non-torrent downloads Add functionality to automatically unzip downloaded .zip files from sources other than torrents. * Add `unzipFile` helper function in `src/main/services/download/helpers.ts` to handle unzipping .zip files. * Modify `src/main/services/download/download-manager.ts` to check if the downloaded file is a .zip file and unzip it after download completion. * Update `src/main/services/python-rpc.ts` to support unzipping functionality by handling .zip files in the `spawn` method. --- src/main/services/download/download-manager.ts | 8 +++++++- src/main/services/download/helpers.ts | 13 +++++++++++++ src/main/services/python-rpc.ts | 10 +++++++++- 3 files changed, 29 insertions(+), 2 deletions(-) diff --git a/src/main/services/download/download-manager.ts b/src/main/services/download/download-manager.ts index 134a74e6..f8c388b9 100644 --- a/src/main/services/download/download-manager.ts +++ b/src/main/services/download/download-manager.ts @@ -15,7 +15,7 @@ import { LibtorrentStatus, PauseDownloadPayload, } from "./types"; -import { calculateETA, getDirSize } from "./helpers"; +import { calculateETA, getDirSize, unzipFile } from "./helpers"; import { QueryDeepPartialEntity } from "typeorm/query-builder/QueryPartialEntity"; import { RealDebridClient } from "./real-debrid"; import path from "path"; @@ -139,6 +139,12 @@ export class DownloadManager { ); this.cancelDownload(gameId); + + if (game.uri?.endsWith(".zip")) { + const zipFilePath = path.join(game.downloadPath!, game.folderName!); + const outputDir = path.join(game.downloadPath!, game.folderName!); + await unzipFile(zipFilePath, outputDir); + } } await downloadQueueRepository.delete({ game }); diff --git a/src/main/services/download/helpers.ts b/src/main/services/download/helpers.ts index 0856eb16..215a706e 100644 --- a/src/main/services/download/helpers.ts +++ b/src/main/services/download/helpers.ts @@ -1,6 +1,7 @@ import path from "node:path"; import fs from "node:fs"; import { logger } from "../logger"; +import unzipper from "unzipper"; export const calculateETA = ( totalLength: number, @@ -38,3 +39,15 @@ export const getDirSize = async (dir: string): Promise => { return 0; } }; + +export const unzipFile = async (zipFilePath: string, outputDir: string) => { + try { + await fs.createReadStream(zipFilePath) + .pipe(unzipper.Extract({ path: outputDir })) + .promise(); + logger.info(`Unzipped ${zipFilePath} to ${outputDir}`); + } catch (error) { + logger.error(`Failed to unzip ${zipFilePath}`, error); + throw error; + } +}; diff --git a/src/main/services/python-rpc.ts b/src/main/services/python-rpc.ts index 1384a1be..eaa39f63 100644 --- a/src/main/services/python-rpc.ts +++ b/src/main/services/python-rpc.ts @@ -8,6 +8,7 @@ import crypto from "node:crypto"; import { pythonRpcLogger } from "./logger"; import { Readable } from "node:stream"; import { app, dialog } from "electron"; +import { unzipFile } from "./download/helpers"; // Import the unzip helper function interface GamePayload { game_id: number; @@ -42,7 +43,7 @@ export class PythonRPC { readable.on("data", pythonRpcLogger.log); } - public static spawn( + public static async spawn( initialDownload?: GamePayload, initialSeeding?: GamePayload[] ) { @@ -96,6 +97,13 @@ export class PythonRPC { this.pythonProcess = childProcess; } + + // Handle unzipping if initialDownload is a .zip file + if (initialDownload && initialDownload.url.endsWith(".zip")) { + const zipFilePath = path.join(initialDownload.save_path, initialDownload.url.split('/').pop()!); + const outputDir = initialDownload.save_path; + await unzipFile(zipFilePath, outputDir); + } } public static kill() {