diff --git a/src/main/events/auth/sign-out.ts b/src/main/events/auth/sign-out.ts index 9c2ce2e0..0eb8cf07 100644 --- a/src/main/events/auth/sign-out.ts +++ b/src/main/events/auth/sign-out.ts @@ -1,6 +1,6 @@ import { registerEvent } from "../register-event"; import * as Sentry from "@sentry/electron/main"; -import { HydraApi, TorrentDownloader, gamesPlaytime } from "@main/services"; +import { HydraApi, RPCManager, gamesPlaytime } from "@main/services"; import { dataSource } from "@main/data-source"; import { DownloadQueue, Game, UserAuth } from "@main/entity"; @@ -24,7 +24,7 @@ const signOut = async (_event: Electron.IpcMainInvokeEvent) => { Sentry.setUser(null); /* Disconnects libtorrent */ - TorrentDownloader.kill(); + RPCManager.kill(); await Promise.all([ databaseOperations, diff --git a/src/main/index.ts b/src/main/index.ts index cb20733a..1372539d 100644 --- a/src/main/index.ts +++ b/src/main/index.ts @@ -5,7 +5,7 @@ import i18n from "i18next"; import path from "node:path"; import url from "node:url"; import { electronApp, optimizer } from "@electron-toolkit/utils"; -import { logger, TorrentDownloader, WindowManager } from "@main/services"; +import { logger, RPCManager, WindowManager } from "@main/services"; import { dataSource } from "@main/data-source"; import * as resources from "@locales"; import { userPreferencesRepository } from "@main/repository"; @@ -116,7 +116,7 @@ app.on("window-all-closed", () => { app.on("before-quit", () => { /* Disconnects libtorrent */ - TorrentDownloader.kill(); + RPCManager.kill(); }); app.on("activate", () => { diff --git a/src/main/main.ts b/src/main/main.ts index 1abd8c2f..759b1714 100644 --- a/src/main/main.ts +++ b/src/main/main.ts @@ -1,4 +1,9 @@ -import { DownloadManager, RepacksManager, startMainLoop } from "./services"; +import { + DownloadManager, + RepacksManager, + RPCManager, + startMainLoop, +} from "./services"; import { downloadQueueRepository, repackRepository, @@ -12,8 +17,6 @@ import { MoreThan } from "typeorm"; import { HydraApi } from "./services/hydra-api"; import { uploadGamesBatch } from "./services/library-sync"; -startMainLoop(); - const loadState = async (userPreferences: UserPreferences | null) => { await RepacksManager.updateRepacks(); @@ -35,8 +38,13 @@ const loadState = async (userPreferences: UserPreferences | null) => { }, }); - if (nextQueueItem?.game.status === "active") + if (nextQueueItem?.game.status === "active") { DownloadManager.startDownload(nextQueueItem.game); + } else { + RPCManager.spawn(); + } + + startMainLoop(); const now = new Date(); diff --git a/src/main/services/download/download-manager.ts b/src/main/services/download/download-manager.ts index f7553c9c..8d402e5a 100644 --- a/src/main/services/download/download-manager.ts +++ b/src/main/services/download/download-manager.ts @@ -1,6 +1,6 @@ import { Game } from "@main/entity"; import { Downloader } from "@shared"; -import { TorrentDownloader } from "./torrent-downloader"; +import { RPCManager } from "./rpc-manager"; import { WindowManager } from "../window-manager"; import { downloadQueueRepository, gameRepository } from "@main/repository"; import { publishDownloadCompleteNotification } from "../notifications"; @@ -16,7 +16,7 @@ export class DownloadManager { if (this.currentDownloader === Downloader.RealDebrid) { status = await RealDebridDownloader.getStatus(); } else { - status = await TorrentDownloader.getStatus(); + status = await RPCManager.getStatus(); } if (status) { @@ -65,7 +65,7 @@ export class DownloadManager { if (this.currentDownloader === Downloader.RealDebrid) { RealDebridDownloader.pauseDownload(); } else { - await TorrentDownloader.pauseDownload(); + await RPCManager.pauseDownload(); } WindowManager.mainWindow?.setProgressBar(-1); @@ -77,7 +77,7 @@ export class DownloadManager { RealDebridDownloader.startDownload(game); this.currentDownloader = Downloader.RealDebrid; } else { - TorrentDownloader.startDownload(game); + RPCManager.startDownload(game); this.currentDownloader = Downloader.Torrent; } } @@ -86,7 +86,7 @@ export class DownloadManager { if (this.currentDownloader === Downloader.RealDebrid) { RealDebridDownloader.cancelDownload(); } else { - TorrentDownloader.cancelDownload(gameId); + RPCManager.cancelDownload(gameId); } WindowManager.mainWindow?.setProgressBar(-1); @@ -98,7 +98,7 @@ export class DownloadManager { RealDebridDownloader.startDownload(game); this.currentDownloader = Downloader.RealDebrid; } else { - TorrentDownloader.startDownload(game); + RPCManager.startDownload(game); this.currentDownloader = Downloader.Torrent; } } diff --git a/src/main/services/download/index.ts b/src/main/services/download/index.ts index 6244b81a..0298f7d8 100644 --- a/src/main/services/download/index.ts +++ b/src/main/services/download/index.ts @@ -1,2 +1,2 @@ export * from "./download-manager"; -export * from "./torrent-downloader"; +export * from "./rpc-manager"; diff --git a/src/main/services/download/torrent-downloader.ts b/src/main/services/download/rpc-manager.ts similarity index 88% rename from src/main/services/download/torrent-downloader.ts rename to src/main/services/download/rpc-manager.ts index e35bb617..12d40a28 100644 --- a/src/main/services/download/torrent-downloader.ts +++ b/src/main/services/download/rpc-manager.ts @@ -15,8 +15,8 @@ import { LibtorrentPayload, } from "./types"; -export class TorrentDownloader { - private static torrentClient: cp.ChildProcess | null = null; +export class RPCManager { + private static rpcProcess: cp.ChildProcess | null = null; private static downloadingGameId = -1; private static rpc = axios.create({ @@ -26,18 +26,22 @@ export class TorrentDownloader { }, }); - private static spawn(args: StartDownloadPayload) { - this.torrentClient = startTorrentClient(args); + public static spawn(args?: StartDownloadPayload) { + this.rpcProcess = startTorrentClient(args); } public static kill() { - if (this.torrentClient) { - this.torrentClient.kill(); - this.torrentClient = null; + if (this.rpcProcess) { + this.rpcProcess.kill(); + this.rpcProcess = null; this.downloadingGameId = -1; } } + public static async getProccessList() { + return (await this.rpc.get("/process-list")).data; + } + public static async getStatus() { if (this.downloadingGameId === -1) return null; @@ -113,7 +117,7 @@ export class TorrentDownloader { } static async startDownload(game: Game) { - if (!this.torrentClient) { + if (!this.rpcProcess) { this.spawn({ game_id: game.id, magnet: game.uri!, diff --git a/src/main/services/download/torrent-client.ts b/src/main/services/download/torrent-client.ts index 176ec664..93d20b7f 100644 --- a/src/main/services/download/torrent-client.ts +++ b/src/main/services/download/torrent-client.ts @@ -15,12 +15,12 @@ export const BITTORRENT_PORT = "5881"; export const RPC_PORT = "8084"; export const RPC_PASSWORD = crypto.randomBytes(32).toString("hex"); -export const startTorrentClient = (args: StartDownloadPayload) => { +export const startTorrentClient = (args?: StartDownloadPayload) => { const commonArgs = [ BITTORRENT_PORT, RPC_PORT, RPC_PASSWORD, - encodeURIComponent(JSON.stringify(args)), + args ? encodeURIComponent(JSON.stringify(args)) : "", ]; if (app.isPackaged) { diff --git a/src/main/services/process-watcher.ts b/src/main/services/process-watcher.ts index f20b4128..4dc12bc1 100644 --- a/src/main/services/process-watcher.ts +++ b/src/main/services/process-watcher.ts @@ -1,11 +1,9 @@ -import path from "node:path"; - import { IsNull, Not } from "typeorm"; import { gameRepository } from "@main/repository"; -import { getProcesses } from "@main/helpers"; import { WindowManager } from "./window-manager"; import { createGame, updateGamePlaytime } from "./library-sync"; import { GameRunning } from "@types"; +import { RPCManager } from "./download"; export const gamesPlaytime = new Map< number, @@ -22,22 +20,13 @@ export const watchProcesses = async () => { if (games.length === 0) return; - const processes = await getProcesses(); + const processes = (await RPCManager.getProccessList()) || []; for (const game of games) { const executablePath = game.executablePath!; - const basename = path.win32.basename(executablePath); - const basenameWithoutExtension = path.win32.basename( - executablePath, - path.extname(executablePath) - ); const gameProcess = processes.find((runningProcess) => { - if (process.platform === "win32") { - return runningProcess.name === basename; - } - - return [basename, basenameWithoutExtension].includes(runningProcess.name); + return executablePath == runningProcess; }); if (gameProcess) { diff --git a/src/renderer/src/pages/game-details/hero/hero-panel-actions.tsx b/src/renderer/src/pages/game-details/hero/hero-panel-actions.tsx index 4741668e..795aa8af 100644 --- a/src/renderer/src/pages/game-details/hero/hero-panel-actions.tsx +++ b/src/renderer/src/pages/game-details/hero/hero-panel-actions.tsx @@ -122,7 +122,7 @@ export function HeroPanelActions() {