From 3aa8230e17a1785ac99671163b031c3a594da134 Mon Sep 17 00:00:00 2001 From: Hachi-R Date: Sun, 22 Dec 2024 22:40:18 -0300 Subject: [PATCH 1/6] feat: restart downloads and move seed process initiation to main.ts --- src/main/main.ts | 25 +++++++++++++++++++++++-- src/main/services/python-rpc.ts | 3 --- src/main/services/seed.ts | 5 +---- 3 files changed, 24 insertions(+), 9 deletions(-) diff --git a/src/main/main.ts b/src/main/main.ts index 18b61c37..b8436c48 100644 --- a/src/main/main.ts +++ b/src/main/main.ts @@ -1,11 +1,13 @@ -import { Ludusavi, startMainLoop } from "./services"; -import { userPreferencesRepository } from "./repository"; +import { DownloadManager, Ludusavi, startMainLoop } from "./services"; +import { downloadQueueRepository, userPreferencesRepository } from "./repository"; import { UserPreferences } from "./entity"; import { RealDebridClient } from "./services/download/real-debrid"; import { HydraApi } from "./services/hydra-api"; import { uploadGamesBatch } from "./services/library-sync"; import { PythonRPC } from "./services/python-rpc"; import { Aria2 } from "./services/aria2"; +import { startSeedProcess } from "./services/seed"; +import { sleep } from "./helpers"; const loadState = async (userPreferences: UserPreferences | null) => { import("./events"); @@ -22,7 +24,26 @@ const loadState = async (userPreferences: UserPreferences | null) => { uploadGamesBatch(); }); + + const [nextQueueItem] = await downloadQueueRepository.find({ + order: { + id: "DESC", + }, + relations: { + game: true, + }, + }); + PythonRPC.spawn(); + await sleep(1000); + // wait for python process to start + + if (nextQueueItem?.game.status === "active") { + DownloadManager.startDownload(nextQueueItem.game); + } + + await startSeedProcess(); + startMainLoop(); }; diff --git a/src/main/services/python-rpc.ts b/src/main/services/python-rpc.ts index d8e09911..55e3845b 100644 --- a/src/main/services/python-rpc.ts +++ b/src/main/services/python-rpc.ts @@ -8,7 +8,6 @@ import crypto from "node:crypto"; import { logger } from "./logger"; import { Readable } from "node:stream"; import { app, dialog } from "electron"; -import { startSeedProcess } from "./seed"; const binaryNameByPlatform: Partial> = { darwin: "hydra-python-rpc", @@ -84,8 +83,6 @@ export class PythonRPC { this.logStderr(childProcess.stderr); this.pythonProcess = childProcess; - - startSeedProcess(); } } diff --git a/src/main/services/seed.ts b/src/main/services/seed.ts index 26ac7fc6..b1147eca 100644 --- a/src/main/services/seed.ts +++ b/src/main/services/seed.ts @@ -13,11 +13,8 @@ export const startSeedProcess = async () => { if (seedList.length === 0) return; - await sleep(1000); - // wait for python process to start - seedList.map(async (game) => { await DownloadManager.startDownload(game); - await sleep(100); + await sleep(300); }); }; From 35d14b33ca1163665c165659ad80c23963712f6b Mon Sep 17 00:00:00 2001 From: Hachi-R Date: Sun, 22 Dec 2024 22:40:51 -0300 Subject: [PATCH 2/6] lint --- src/main/main.ts | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/src/main/main.ts b/src/main/main.ts index b8436c48..df14c4b4 100644 --- a/src/main/main.ts +++ b/src/main/main.ts @@ -1,5 +1,8 @@ import { DownloadManager, Ludusavi, startMainLoop } from "./services"; -import { downloadQueueRepository, userPreferencesRepository } from "./repository"; +import { + downloadQueueRepository, + userPreferencesRepository, +} from "./repository"; import { UserPreferences } from "./entity"; import { RealDebridClient } from "./services/download/real-debrid"; import { HydraApi } from "./services/hydra-api"; @@ -24,7 +27,6 @@ const loadState = async (userPreferences: UserPreferences | null) => { uploadGamesBatch(); }); - const [nextQueueItem] = await downloadQueueRepository.find({ order: { id: "DESC", @@ -36,7 +38,7 @@ const loadState = async (userPreferences: UserPreferences | null) => { PythonRPC.spawn(); await sleep(1000); - // wait for python process to start + // wait for python process to start if (nextQueueItem?.game.status === "active") { DownloadManager.startDownload(nextQueueItem.game); From e463ee569a053e846cbe6d307c705a62cce15fb7 Mon Sep 17 00:00:00 2001 From: Hachi-R Date: Mon, 23 Dec 2024 01:25:01 -0300 Subject: [PATCH 3/6] feat: add initial download handling in Python RPC and update spawn method to accept download parameters --- python_rpc/main.py | 15 +++++++++++++++ src/main/main.ts | 22 ++++++++++++++-------- src/main/services/python-rpc.ts | 16 ++++++++++++++-- 3 files changed, 43 insertions(+), 10 deletions(-) diff --git a/python_rpc/main.py b/python_rpc/main.py index 060e01c2..028e9fa3 100644 --- a/python_rpc/main.py +++ b/python_rpc/main.py @@ -11,6 +11,7 @@ app = Flask(__name__) torrent_port = sys.argv[1] http_port = sys.argv[2] rpc_password = sys.argv[3] +start_download_payload = sys.argv[4] downloads = {} # This can be streamed down from Node @@ -18,6 +19,20 @@ downloading_game_id = -1 torrent_session = lt.session({'listen_interfaces': '0.0.0.0:{port}'.format(port=torrent_port)}) +if start_download_payload: + initial_download = json.loads(urllib.parse.unquote(start_download_payload)) + downloading_game_id = initial_download['game_id'] + + if initial_download['url'].startswith('magnet'): + torrent_downloader = TorrentDownloader(torrent_session) + downloads[initial_download['game_id']] = torrent_downloader + torrent_downloader.start_download(initial_download['url'], initial_download['save_path'], "") + else: + http_downloader = HttpDownloader() + downloads[initial_download['game_id']] = http_downloader + http_downloader.start_download(initial_download['url'], initial_download['save_path'], initial_download.get('header')) + + def validate_rpc_password(): """Middleware to validate RPC password.""" header_password = request.headers.get('x-hydra-rpc-password') diff --git a/src/main/main.ts b/src/main/main.ts index df14c4b4..63517ce2 100644 --- a/src/main/main.ts +++ b/src/main/main.ts @@ -1,4 +1,4 @@ -import { DownloadManager, Ludusavi, startMainLoop } from "./services"; +import { Ludusavi, startMainLoop } from "./services"; import { downloadQueueRepository, userPreferencesRepository, @@ -10,7 +10,6 @@ import { uploadGamesBatch } from "./services/library-sync"; import { PythonRPC } from "./services/python-rpc"; import { Aria2 } from "./services/aria2"; import { startSeedProcess } from "./services/seed"; -import { sleep } from "./helpers"; const loadState = async (userPreferences: UserPreferences | null) => { import("./events"); @@ -36,12 +35,19 @@ const loadState = async (userPreferences: UserPreferences | null) => { }, }); - PythonRPC.spawn(); - await sleep(1000); - // wait for python process to start - - if (nextQueueItem?.game.status === "active") { - DownloadManager.startDownload(nextQueueItem.game); + if ( + nextQueueItem?.game.status === "active" && + nextQueueItem?.game.id && + nextQueueItem?.game.uri && + nextQueueItem?.game.downloadPath + ) { + PythonRPC.spawn({ + game_id: nextQueueItem.game.id, + url: nextQueueItem.game.uri, + save_path: nextQueueItem.game.downloadPath, + }); + } else { + PythonRPC.spawn(); } await startSeedProcess(); diff --git a/src/main/services/python-rpc.ts b/src/main/services/python-rpc.ts index 55e3845b..622fb4ce 100644 --- a/src/main/services/python-rpc.ts +++ b/src/main/services/python-rpc.ts @@ -9,6 +9,12 @@ import { logger } from "./logger"; import { Readable } from "node:stream"; import { app, dialog } from "electron"; +interface StartDownloadPayload { + game_id: number; + url: string; + save_path: string; +} + const binaryNameByPlatform: Partial> = { darwin: "hydra-python-rpc", linux: "hydra-python-rpc", @@ -36,9 +42,15 @@ export class PythonRPC { readable.on("data", logger.log); } - public static spawn() { + public static spawn(initialDownload?: StartDownloadPayload) { console.log([this.BITTORRENT_PORT, this.RPC_PORT, this.RPC_PASSWORD]); - const commonArgs = [this.BITTORRENT_PORT, this.RPC_PORT, this.RPC_PASSWORD]; + + const commonArgs = [ + this.BITTORRENT_PORT, + this.RPC_PORT, + this.RPC_PASSWORD, + initialDownload ? JSON.stringify(initialDownload) : "", + ]; if (app.isPackaged) { const binaryName = binaryNameByPlatform[process.platform]!; From af2b42215414250e3a98167fc3fd5b59098c1184 Mon Sep 17 00:00:00 2001 From: Hachi-R Date: Mon, 23 Dec 2024 02:07:37 -0300 Subject: [PATCH 4/6] feat: integrate DownloadManager for active game downloads and streamline RPC handling --- src/main/main.ts | 17 ++++------------- src/main/services/download/download-manager.ts | 14 +++++++++++++- 2 files changed, 17 insertions(+), 14 deletions(-) diff --git a/src/main/main.ts b/src/main/main.ts index 63517ce2..c39a5196 100644 --- a/src/main/main.ts +++ b/src/main/main.ts @@ -1,4 +1,4 @@ -import { Ludusavi, startMainLoop } from "./services"; +import { DownloadManager, Ludusavi, startMainLoop } from "./services"; import { downloadQueueRepository, userPreferencesRepository, @@ -7,9 +7,9 @@ import { UserPreferences } from "./entity"; import { RealDebridClient } from "./services/download/real-debrid"; import { HydraApi } from "./services/hydra-api"; import { uploadGamesBatch } from "./services/library-sync"; -import { PythonRPC } from "./services/python-rpc"; import { Aria2 } from "./services/aria2"; import { startSeedProcess } from "./services/seed"; +import { PythonRPC } from "./services/python-rpc"; const loadState = async (userPreferences: UserPreferences | null) => { import("./events"); @@ -35,17 +35,8 @@ const loadState = async (userPreferences: UserPreferences | null) => { }, }); - if ( - nextQueueItem?.game.status === "active" && - nextQueueItem?.game.id && - nextQueueItem?.game.uri && - nextQueueItem?.game.downloadPath - ) { - PythonRPC.spawn({ - game_id: nextQueueItem.game.id, - url: nextQueueItem.game.uri, - save_path: nextQueueItem.game.downloadPath, - }); + if (nextQueueItem?.game.status === "active") { + DownloadManager.startRPC(nextQueueItem.game); } else { PythonRPC.spawn(); } diff --git a/src/main/services/download/download-manager.ts b/src/main/services/download/download-manager.ts index a4106fef..47822ec4 100644 --- a/src/main/services/download/download-manager.ts +++ b/src/main/services/download/download-manager.ts @@ -23,6 +23,18 @@ import path from "path"; export class DownloadManager { private static downloadingGameId: number | null = null; + public static startRPC(game: Game) { + if (game && game.status === "active") { + PythonRPC.spawn({ + game_id: game.id, + url: game.uri!, + save_path: game.downloadPath!, + }); + + this.downloadingGameId = game.id; + } + } + private static async getDownloadStatus() { const response = await PythonRPC.rpc.get( "/status" @@ -188,7 +200,7 @@ export class DownloadManager { action: "pause", game_id: this.downloadingGameId, } as PauseDownloadPayload) - .catch(() => {}); + .catch(() => { }); WindowManager.mainWindow?.setProgressBar(-1); From c755aa388b73f477e19d9d84d2d75da703a56386 Mon Sep 17 00:00:00 2001 From: Hachi-R Date: Mon, 23 Dec 2024 02:07:48 -0300 Subject: [PATCH 5/6] lint --- src/main/services/download/download-manager.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/services/download/download-manager.ts b/src/main/services/download/download-manager.ts index 47822ec4..78452380 100644 --- a/src/main/services/download/download-manager.ts +++ b/src/main/services/download/download-manager.ts @@ -200,7 +200,7 @@ export class DownloadManager { action: "pause", game_id: this.downloadingGameId, } as PauseDownloadPayload) - .catch(() => { }); + .catch(() => {}); WindowManager.mainWindow?.setProgressBar(-1); From f9719c995c323825ade3052d1944886feab7ebe9 Mon Sep 17 00:00:00 2001 From: Hachi-R Date: Mon, 23 Dec 2024 03:07:06 -0300 Subject: [PATCH 6/6] feat: delay in seed process --- src/main/services/seed.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/src/main/services/seed.ts b/src/main/services/seed.ts index b1147eca..89172f50 100644 --- a/src/main/services/seed.ts +++ b/src/main/services/seed.ts @@ -12,6 +12,7 @@ export const startSeedProcess = async () => { }); if (seedList.length === 0) return; + await sleep(1000); seedList.map(async (game) => { await DownloadManager.startDownload(game);