diff --git a/src/main/services/download/download-manager.ts b/src/main/services/download/download-manager.ts index 3cd30a7b..c36bf8ce 100644 --- a/src/main/services/download/download-manager.ts +++ b/src/main/services/download/download-manager.ts @@ -29,17 +29,20 @@ import { BuzzheavierApi, FuckingFastApi } from "@main/services/hosters"; export class DownloadManager { private static downloadingGameId: string | null = null; - private static extractFilename(url: string, originalUrl?: string): string | undefined { - if (originalUrl?.includes('#')) { - const hashPart = originalUrl.split('#')[1]; - if (hashPart && !hashPart.startsWith('http') && hashPart.includes('.')) { + private static extractFilename( + url: string, + originalUrl?: string + ): string | undefined { + if (originalUrl?.includes("#")) { + const hashPart = originalUrl.split("#")[1]; + if (hashPart && !hashPart.startsWith("http") && hashPart.includes(".")) { return hashPart; } } - if (url.includes('#')) { - const hashPart = url.split('#')[1]; - if (hashPart && !hashPart.startsWith('http') && hashPart.includes('.')) { + if (url.includes("#")) { + const hashPart = url.split("#")[1]; + if (hashPart && !hashPart.startsWith("http") && hashPart.includes(".")) { return hashPart; } } @@ -47,10 +50,10 @@ export class DownloadManager { try { const urlObj = new URL(url); const pathname = urlObj.pathname; - const pathParts = pathname.split('/'); + const pathParts = pathname.split("/"); const filename = pathParts[pathParts.length - 1]; - - if (filename?.includes('.') && filename.length > 0) { + + if (filename?.includes(".") && filename.length > 0) { return decodeURIComponent(filename); } } catch { @@ -61,17 +64,28 @@ export class DownloadManager { } private static sanitizeFilename(filename: string): string { - return filename.replaceAll(/[<>:"/\\|?*]/g, '_'); + return filename.replaceAll(/[<>:"/\\|?*]/g, "_"); } - private static createDownloadPayload(directUrl: string, originalUrl: string, downloadId: string, savePath: string) { - const filename = this.extractFilename(originalUrl, directUrl) || this.extractFilename(directUrl); - const sanitizedFilename = filename ? this.sanitizeFilename(filename) : undefined; - + private static createDownloadPayload( + directUrl: string, + originalUrl: string, + downloadId: string, + savePath: string + ) { + const filename = + this.extractFilename(originalUrl, directUrl) || + this.extractFilename(directUrl); + const sanitizedFilename = filename + ? this.sanitizeFilename(filename) + : undefined; + if (sanitizedFilename) { logger.log(`[DownloadManager] Using filename: ${sanitizedFilename}`); } else { - logger.log(`[DownloadManager] No filename extracted, aria2 will use default`); + logger.log( + `[DownloadManager] No filename extracted, aria2 will use default` + ); } return { @@ -109,7 +123,9 @@ export class DownloadManager { } private static async getDownloadStatus() { - const response = await PythonRPC.rpc.get("/status"); + const response = await PythonRPC.rpc.get( + "/status" + ); if (response.data === null || !this.downloadingGameId) return null; const downloadId = this.downloadingGameId; @@ -125,7 +141,8 @@ export class DownloadManager { status, } = response.data; - const isDownloadingMetadata = status === LibtorrentStatus.DownloadingMetadata; + const isDownloadingMetadata = + status === LibtorrentStatus.DownloadingMetadata; const isCheckingFiles = status === LibtorrentStatus.CheckingFiles; const download = await downloadsSublevel.get(downloadId); @@ -190,7 +207,10 @@ export class DownloadManager { if (progress === 1 && download) { publishDownloadCompleteNotification(game); - if (userPreferences?.seedAfterDownloadComplete && download.downloader === Downloader.Torrent) { + if ( + userPreferences?.seedAfterDownloadComplete && + download.downloader === Downloader.Torrent + ) { await downloadsSublevel.put(gameId, { ...download, status: "seeding", @@ -211,13 +231,22 @@ export class DownloadManager { } if (shouldExtract) { - const gameFilesManager = new GameFilesManager(game.shop, game.objectId); + const gameFilesManager = new GameFilesManager( + game.shop, + game.objectId + ); - if (FILE_EXTENSIONS_TO_EXTRACT.some((ext) => download.folderName?.endsWith(ext))) { + if ( + FILE_EXTENSIONS_TO_EXTRACT.some((ext) => + download.folderName?.endsWith(ext) + ) + ) { gameFilesManager.extractDownloadedFile(); - } else { + } else if (download.folderName) { gameFilesManager - .extractFilesInDirectory(path.join(download.downloadPath, download.folderName)) + .extractFilesInDirectory( + path.join(download.downloadPath, download.folderName) + ) .then(() => gameFilesManager.setExtractionComplete()); } } @@ -225,11 +254,13 @@ export class DownloadManager { const downloads = await downloadsSublevel .values() .all() - .then((games) => sortBy( - games.filter((game) => game.status === "paused" && game.queued), - "timestamp", - "DESC" - )); + .then((games) => + sortBy( + games.filter((game) => game.status === "paused" && game.queued), + "timestamp", + "DESC" + ) + ); const [nextItemOnQueue] = downloads; @@ -256,7 +287,9 @@ export class DownloadManager { if (!download) return; - const totalSize = await getDirSize(path.join(download.downloadPath, status.folderName)); + const totalSize = await getDirSize( + path.join(download.downloadPath, status.folderName) + ); if (totalSize < status.fileSize) { await this.cancelDownload(status.gameId); @@ -277,7 +310,10 @@ export class DownloadManager { static async pauseDownload(downloadKey = this.downloadingGameId) { await PythonRPC.rpc - .post("/action", { action: "pause", game_id: downloadKey } as PauseDownloadPayload) + .post("/action", { + action: "pause", + game_id: downloadKey, + } as PauseDownloadPayload) .catch(() => {}); if (downloadKey === this.downloadingGameId) { @@ -368,24 +404,44 @@ export class DownloadManager { }; } case Downloader.Buzzheavier: { - logger.log(`[DownloadManager] Processing Buzzheavier download for URI: ${download.uri}`); + logger.log( + `[DownloadManager] Processing Buzzheavier download for URI: ${download.uri}` + ); try { const directUrl = await BuzzheavierApi.getDirectLink(download.uri); logger.log(`[DownloadManager] Buzzheavier direct URL obtained`); - return this.createDownloadPayload(directUrl, download.uri, downloadId, download.downloadPath); + return this.createDownloadPayload( + directUrl, + download.uri, + downloadId, + download.downloadPath + ); } catch (error) { - logger.error(`[DownloadManager] Error processing Buzzheavier download:`, error); + logger.error( + `[DownloadManager] Error processing Buzzheavier download:`, + error + ); throw error; } } case Downloader.FuckingFast: { - logger.log(`[DownloadManager] Processing FuckingFast download for URI: ${download.uri}`); + logger.log( + `[DownloadManager] Processing FuckingFast download for URI: ${download.uri}` + ); try { const directUrl = await FuckingFastApi.getDirectLink(download.uri); logger.log(`[DownloadManager] FuckingFast direct URL obtained`); - return this.createDownloadPayload(directUrl, download.uri, downloadId, download.downloadPath); + return this.createDownloadPayload( + directUrl, + download.uri, + downloadId, + download.downloadPath + ); } catch (error) { - logger.error(`[DownloadManager] Error processing FuckingFast download:`, error); + logger.error( + `[DownloadManager] Error processing FuckingFast download:`, + error + ); throw error; } } @@ -430,7 +486,9 @@ export class DownloadManager { }; } case Downloader.Hydra: { - const downloadUrl = await HydraDebridClient.getDownloadUrl(download.uri); + const downloadUrl = await HydraDebridClient.getDownloadUrl( + download.uri + ); if (!downloadUrl) throw new Error(DownloadError.NotCachedOnHydra); return {