From 1397e3932d53c855e8cbe2edbaf9841426f85872 Mon Sep 17 00:00:00 2001 From: Zamitto <167933696+zamitto@users.noreply.github.com> Date: Wed, 3 Jul 2024 15:29:59 -0300 Subject: [PATCH] feat: remove pslist and use sudo-prompt to close game if needed --- .gitignore | 1 - electron-builder.yml | 5 -- package.json | 2 +- resources/hydralauncher.vbs | 3 -- src/main/constants.ts | 9 ---- src/main/events/library/close-game.ts | 48 +++++++++++-------- .../events/user-preferences/auto-launch.ts | 22 ++------- src/main/helpers/index.ts | 1 - src/main/helpers/ps.ts | 41 ---------------- src/main/services/download/rpc-manager.ts | 7 ++- src/main/services/download/types.ts | 5 ++ src/main/services/process-watcher.ts | 5 +- torrent-client/main.py | 6 +-- yarn.lock | 10 ++-- 14 files changed, 51 insertions(+), 114 deletions(-) delete mode 100644 resources/hydralauncher.vbs delete mode 100644 src/main/helpers/ps.ts diff --git a/.gitignore b/.gitignore index fb4badd7..017a9141 100644 --- a/.gitignore +++ b/.gitignore @@ -1,7 +1,6 @@ .vscode node_modules hydra-download-manager/ -fastlist.exe __pycache__ dist out diff --git a/electron-builder.yml b/electron-builder.yml index fec128a6..cfdafe7d 100644 --- a/electron-builder.yml +++ b/electron-builder.yml @@ -5,10 +5,7 @@ directories: extraResources: - hydra-download-manager - seeds - - from: node_modules/ps-list/vendor/fastlist-0.3.0-x64.exe - to: fastlist.exe - from: node_modules/create-desktop-shortcuts/src/windows.vbs - - from: resources/hydralauncher.vbs files: - "!**/.vscode/*" - "!src/*" @@ -20,7 +17,6 @@ asarUnpack: - resources/** win: executableName: Hydra - requestedExecutionLevel: requireAdministrator target: - nsis - portable @@ -33,7 +29,6 @@ nsis: allowToChangeInstallationDirectory: true portable: artifactName: ${name}-${version}-portable.${ext} - requestExecutionLevel: admin mac: entitlementsInherit: build/entitlements.mac.plist extendInfo: diff --git a/package.json b/package.json index c029e4db..549f7a1b 100644 --- a/package.json +++ b/package.json @@ -65,11 +65,11 @@ "lottie-react": "^2.4.0", "parse-torrent": "^11.0.16", "piscina": "^4.5.1", - "ps-list": "^8.1.1", "react-i18next": "^14.1.0", "react-loading-skeleton": "^3.4.0", "react-redux": "^9.1.1", "react-router-dom": "^6.22.3", + "sudo-prompt": "^9.2.1", "typeorm": "^0.3.20", "user-agents": "^1.1.193", "yaml": "^2.4.1", diff --git a/resources/hydralauncher.vbs b/resources/hydralauncher.vbs deleted file mode 100644 index ff611acf..00000000 --- a/resources/hydralauncher.vbs +++ /dev/null @@ -1,3 +0,0 @@ -Set WshShell = CreateObject("WScript.Shell" ) -WshShell.Run """%localappdata%\Programs\Hydra\Hydra.exe""", 0 'Must quote command if it has spaces; must escape quotes -Set WshShell = Nothing diff --git a/src/main/constants.ts b/src/main/constants.ts index 62713a2c..850c9ada 100644 --- a/src/main/constants.ts +++ b/src/main/constants.ts @@ -14,12 +14,3 @@ export const logsPath = path.join(app.getPath("appData"), "hydra", "logs"); export const seedsPath = app.isPackaged ? path.join(process.resourcesPath, "seeds") : path.join(__dirname, "..", "..", "seeds"); - -export const windowsStartupPath = path.join( - app.getPath("appData"), - "Microsoft", - "Windows", - "Start Menu", - "Programs", - "Startup" -); diff --git a/src/main/events/library/close-game.ts b/src/main/events/library/close-game.ts index ccf446d3..7f3b74a5 100644 --- a/src/main/events/library/close-game.ts +++ b/src/main/events/library/close-game.ts @@ -1,39 +1,45 @@ -import path from "node:path"; - import { gameRepository } from "@main/repository"; -import { getProcesses } from "@main/helpers"; - import { registerEvent } from "../register-event"; +import { RPCManager, logger } from "@main/services"; +import sudo from "sudo-prompt"; +import { app } from "electron"; + +const getKillCommand = (pid: number) => { + if (process.platform == "win32") { + return `taskkill /PID ${pid}`; + } + + return `kill -9 ${pid}`; +}; const closeGame = async ( _event: Electron.IpcMainInvokeEvent, gameId: number ) => { - const processes = await getProcesses(); + const processes = await RPCManager.getProcessList(); const game = await gameRepository.findOne({ where: { id: gameId, isDeleted: false }, }); - if (!game) return false; - - const executablePath = game.executablePath!; - - const basename = path.win32.basename(executablePath); - const basenameWithoutExtension = path.win32.basename( - executablePath, - path.extname(executablePath) - ); + if (!game) return; const gameProcess = processes.find((runningProcess) => { - if (process.platform === "win32") { - return runningProcess.name === basename; - } - - return [basename, basenameWithoutExtension].includes(runningProcess.name); + return runningProcess.exe === game.executablePath; }); - if (gameProcess) return process.kill(gameProcess.pid); - return false; + if (gameProcess) { + try { + process.kill(gameProcess.pid); + } catch (err) { + sudo.exec( + getKillCommand(gameProcess.pid), + { name: app.getName() }, + (error, _stdout, _stderr) => { + logger.error(error); + } + ); + } + } }; registerEvent("closeGame", closeGame); diff --git a/src/main/events/user-preferences/auto-launch.ts b/src/main/events/user-preferences/auto-launch.ts index cb40a969..ade7833d 100644 --- a/src/main/events/user-preferences/auto-launch.ts +++ b/src/main/events/user-preferences/auto-launch.ts @@ -1,9 +1,6 @@ -import { windowsStartupPath } from "@main/constants"; import { registerEvent } from "../register-event"; import AutoLaunch from "auto-launch"; import { app } from "electron"; -import fs from "node:fs"; -import path from "node:path"; const autoLaunch = async ( _event: Electron.IpcMainInvokeEvent, @@ -15,23 +12,10 @@ const autoLaunch = async ( name: app.getName(), }); - if (process.platform == "win32") { - const destination = path.join(windowsStartupPath, "Hydra.vbs"); - - if (enabled) { - const scriptPath = path.join(process.resourcesPath, "hydralauncher.vbs"); - - fs.copyFileSync(scriptPath, destination); - } else { - appLauncher.disable().catch(); - fs.rmSync(destination); - } + if (enabled) { + appLauncher.enable().catch(); } else { - if (enabled) { - appLauncher.enable().catch(); - } else { - appLauncher.disable().catch(); - } + appLauncher.disable().catch(); } }; diff --git a/src/main/helpers/index.ts b/src/main/helpers/index.ts index db1d13ff..902b927d 100644 --- a/src/main/helpers/index.ts +++ b/src/main/helpers/index.ts @@ -57,5 +57,4 @@ export const requestWebPage = async (url: string) => { .then((response) => response.data); }; -export * from "./ps"; export * from "./download-source"; diff --git a/src/main/helpers/ps.ts b/src/main/helpers/ps.ts deleted file mode 100644 index 5b326dfa..00000000 --- a/src/main/helpers/ps.ts +++ /dev/null @@ -1,41 +0,0 @@ -import psList from "ps-list"; -import path from "node:path"; -import childProcess from "node:child_process"; -import { promisify } from "node:util"; -import { app } from "electron"; - -const TEN_MEGABYTES = 1000 * 1000 * 10; -const execFile = promisify(childProcess.execFile); - -export const getProcesses = async () => { - if (process.platform == "win32") { - const binaryPath = app.isPackaged - ? path.join(process.resourcesPath, "fastlist.exe") - : path.join( - __dirname, - "..", - "..", - "node_modules", - "ps-list", - "vendor", - "fastlist-0.3.0-x64.exe" - ); - - const { stdout } = await execFile(binaryPath, { - maxBuffer: TEN_MEGABYTES, - windowsHide: true, - }); - - return stdout - .trim() - .split("\r\n") - .map((line) => line.split("\t")) - .map(([pid, ppid, name]) => ({ - pid: Number.parseInt(pid, 10), - ppid: Number.parseInt(ppid, 10), - name, - })); - } else { - return psList(); - } -}; diff --git a/src/main/services/download/rpc-manager.ts b/src/main/services/download/rpc-manager.ts index 9ada3e54..58cc1daa 100644 --- a/src/main/services/download/rpc-manager.ts +++ b/src/main/services/download/rpc-manager.ts @@ -17,6 +17,7 @@ import { PauseDownloadPayload, LibtorrentStatus, LibtorrentPayload, + ProcessPayload, } from "./types"; export class RPCManager { @@ -49,8 +50,10 @@ export class RPCManager { } } - public static async getProccessList() { - return (await this.rpc.get("/process-list")).data || []; + public static async getProcessList() { + return ( + (await this.rpc.get("/process-list")).data || [] + ); } public static async getStatus() { diff --git a/src/main/services/download/types.ts b/src/main/services/download/types.ts index 516cd84f..fd8009a2 100644 --- a/src/main/services/download/types.ts +++ b/src/main/services/download/types.ts @@ -31,3 +31,8 @@ export interface LibtorrentPayload { status: LibtorrentStatus; gameId: number; } + +export interface ProcessPayload { + exe: string; + pid: number; +} diff --git a/src/main/services/process-watcher.ts b/src/main/services/process-watcher.ts index 8512f1d8..ec7d8e20 100644 --- a/src/main/services/process-watcher.ts +++ b/src/main/services/process-watcher.ts @@ -19,14 +19,13 @@ export const watchProcesses = async () => { }); if (games.length === 0) return; - - const processes = await RPCManager.getProccessList(); + const processes = await RPCManager.getProcessList(); for (const game of games) { const executablePath = game.executablePath!; const gameProcess = processes.find((runningProcess) => { - return executablePath == runningProcess; + return executablePath == runningProcess.exe; }); if (gameProcess) { diff --git a/torrent-client/main.py b/torrent-client/main.py index 1099af91..8f57de8a 100644 --- a/torrent-client/main.py +++ b/torrent-client/main.py @@ -44,17 +44,17 @@ class Handler(BaseHTTPRequestHandler): self.end_headers() return - process_path = list(set([proc.info["exe"] for proc in psutil.process_iter(['exe'])])) + process_list = [proc.info for proc in psutil.process_iter(['exe', 'pid', 'username'])] self.send_response(200) self.send_header("Content-type", "application/json") self.end_headers() - self.wfile.write(json.dumps(process_path).encode('utf-8')) + self.wfile.write(json.dumps(process_list).encode('utf-8')) def do_POST(self): global downloader - + if self.path == "/action": if self.headers.get(self.rpc_password_header) != rpc_password: self.send_response(401) diff --git a/yarn.lock b/yarn.lock index 9fce82e7..30dfe715 100644 --- a/yarn.lock +++ b/yarn.lock @@ -6311,11 +6311,6 @@ proxy-from-env@^1.1.0: resolved "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz" integrity sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg== -ps-list@^8.1.1: - version "8.1.1" - resolved "https://registry.npmjs.org/ps-list/-/ps-list-8.1.1.tgz" - integrity sha512-OPS9kEJYVmiO48u/B9qneqhkMvgCxT+Tm28VCEJpheTpl8cJ0ffZRRNgS5mrQRTrX5yRTpaJ+hRDeefXYmmorQ== - psl@^1.1.33: version "1.9.0" resolved "https://registry.npmjs.org/psl/-/psl-1.9.0.tgz" @@ -6999,6 +6994,11 @@ strtok3@^7.0.0: "@tokenizer/token" "^0.3.0" peek-readable "^5.0.0" +sudo-prompt@^9.2.1: + version "9.2.1" + resolved "https://registry.yarnpkg.com/sudo-prompt/-/sudo-prompt-9.2.1.tgz#77efb84309c9ca489527a4e749f287e6bdd52afd" + integrity sha512-Mu7R0g4ig9TUuGSxJavny5Rv0egCEtpZRNMrZaYS1vxkiIxGiGUwoezU3LazIQ+KE04hTrTfNPgxU5gzi7F5Pw== + sumchecker@^3.0.1: version "3.0.1" resolved "https://registry.npmjs.org/sumchecker/-/sumchecker-3.0.1.tgz"