From ba3f010576686158aeffe5e939c1163cb6a1512e Mon Sep 17 00:00:00 2001 From: Chubby Granny Chaser Date: Fri, 11 Apr 2025 18:06:02 +0100 Subject: [PATCH] ci: adding electron builder for http --- .github/workflows/build.yml | 3 +- electron-builder.yml | 3 + python_rpc/http_downloader.py | 123 +++++++++++++++++++++----------- python_rpc/main.py | 9 +-- src/main/services/python-rpc.ts | 20 ++++++ 5 files changed, 111 insertions(+), 47 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 920f3fc5..4577adb2 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -10,7 +10,8 @@ jobs: build: strategy: matrix: - os: [windows-latest, ubuntu-latest] + # os: [windows-latest, ubuntu-latest] + os: [windows-latest] runs-on: ${{ matrix.os }} diff --git a/electron-builder.yml b/electron-builder.yml index dd10e81a..e86dd2fb 100644 --- a/electron-builder.yml +++ b/electron-builder.yml @@ -23,6 +23,7 @@ win: extraResources: - from: binaries/7z.exe - from: binaries/7z.dll + - from: rust_rpc/target/release/hydra-httpdl.exe target: - nsis - portable @@ -40,6 +41,7 @@ mac: entitlementsInherit: build/entitlements.mac.plist extraResources: - from: binaries/7zz + - from: rust_rpc/target/release/hydra-httpdl extendInfo: - NSCameraUsageDescription: Application requests access to the device's camera. - NSMicrophoneUsageDescription: Application requests access to the device's microphone. @@ -51,6 +53,7 @@ dmg: linux: extraResources: - from: binaries/7zzs + - from: rust_rpc/target/release/hydra-httpdl target: - AppImage - snap diff --git a/python_rpc/http_downloader.py b/python_rpc/http_downloader.py index 71e4b57e..31fcc756 100644 --- a/python_rpc/http_downloader.py +++ b/python_rpc/http_downloader.py @@ -1,48 +1,87 @@ -import aria2p +import os +import subprocess +import json class HttpDownloader: - def __init__(self): - self.download = None - self.aria2 = aria2p.API( - aria2p.Client( - host="http://localhost", - port=6800, - secret="" - ) - ) + def __init__(self, hydra_httpdl_bin: str): + self.hydra_exe = hydra_httpdl_bin + self.process = None + self.last_status = None + + def start_download(self, url: str, save_path: str, header: str = None, out: str = None, allow_multiple_connections: bool = False): + cmd = [self.hydra_exe] + + cmd.append(url) + + cmd.extend([ + "--chunk-size", "10", + "--buffer-size", "16", + "--json-output", + "--silent" + ]) + + if allow_multiple_connections: + cmd.extend(["--connections", "24"]) + + print(f"running hydra-httpdl: {' '.join(cmd)}") + + try: + self.process = subprocess.Popen( + cmd, + cwd=save_path, + stdout=subprocess.PIPE, + stderr=subprocess.PIPE, + universal_newlines=True + ) + except Exception as e: + print(f"error running hydra-httpdl: {e}") - def start_download(self, url: str, save_path: str, header: str, out: str = None): - if self.download: - self.aria2.resume([self.download]) - else: - downloads = self.aria2.add(url, options={"header": header, "dir": save_path, "out": out}) - - self.download = downloads[0] - - def pause_download(self): - if self.download: - self.aria2.pause([self.download]) - - def cancel_download(self): - if self.download: - self.aria2.remove([self.download]) - self.download = None def get_download_status(self): - if self.download == None: + + if not self.process: return None - - download = self.aria2.get_download(self.download.gid) - - response = { - 'folderName': download.name, - 'fileSize': download.total_length, - 'progress': download.completed_length / download.total_length if download.total_length else 0, - 'downloadSpeed': download.download_speed, - 'numPeers': 0, - 'numSeeds': 0, - 'status': download.status, - 'bytesDownloaded': download.completed_length, - } - - return response + + try: + line = self.process.stdout.readline() + if line: + status = json.loads(line.strip()) + self.last_status = status + elif self.last_status: + status = self.last_status + else: + return None + + response = { + "status": "active", + "progress": status["progress"] / 100, + "downloadSpeed": status["download_speed"], + "numPeers": 0, + "numSeeds": 0, + "bytesDownloaded": status["bytes_downloaded"], + "fileSize": status["file_size"], + "folderName": status["file_name"] + } + + if status["progress"] == 100.0: + response["status"] = "complete" + + return response + + except Exception as e: + print(f"error getting download status: {e}") + return None + + + + def stop_download(self): + if self.process: + self.process.terminate() + self.process = None + self.last_status = None + + def pause_download(self): + self.stop_download() + + def cancel_download(self): + self.stop_download() diff --git a/python_rpc/main.py b/python_rpc/main.py index 94c34e17..bc108a33 100644 --- a/python_rpc/main.py +++ b/python_rpc/main.py @@ -13,6 +13,7 @@ http_port = sys.argv[2] rpc_password = sys.argv[3] start_download_payload = sys.argv[4] start_seeding_payload = sys.argv[5] +hydra_httpdl_bin = sys.argv[6] downloads = {} # This can be streamed down from Node @@ -32,7 +33,7 @@ if start_download_payload: except Exception as e: print("Error starting torrent download", e) else: - http_downloader = HttpDownloader() + http_downloader = HttpDownloader(hydra_httpdl_bin) downloads[initial_download['game_id']] = http_downloader try: http_downloader.start_download(initial_download['url'], initial_download['save_path'], initial_download.get('header'), initial_download.get("out")) @@ -147,11 +148,11 @@ def action(): torrent_downloader.start_download(url, data['save_path']) else: if existing_downloader and isinstance(existing_downloader, HttpDownloader): - existing_downloader.start_download(url, data['save_path'], data.get('header'), data.get('out')) + existing_downloader.start_download(url, data['save_path'], data.get('header'), data.get('out'), data.get('allow_multiple_connections', False)) else: - http_downloader = HttpDownloader() + http_downloader = HttpDownloader(hydra_httpdl_bin) downloads[game_id] = http_downloader - http_downloader.start_download(url, data['save_path'], data.get('header'), data.get('out')) + http_downloader.start_download(url, data['save_path'], data.get('header'), data.get('out'), data.get('allow_multiple_connections', False)) downloading_game_id = game_id diff --git a/src/main/services/python-rpc.ts b/src/main/services/python-rpc.ts index 22e60461..bd38ae2d 100644 --- a/src/main/services/python-rpc.ts +++ b/src/main/services/python-rpc.ts @@ -21,6 +21,12 @@ const binaryNameByPlatform: Partial> = { win32: "hydra-python-rpc.exe", }; +const rustBinaryNameByPlatform: Partial> = { + darwin: "hydra-httpdl", + linux: "hydra-httpdl", + win32: "hydra-httpdl.exe", +}; + export class PythonRPC { public static readonly BITTORRENT_PORT = "5881"; public static readonly RPC_PORT = "8084"; @@ -52,6 +58,20 @@ export class PythonRPC { this.RPC_PASSWORD, initialDownload ? JSON.stringify(initialDownload) : "", initialSeeding ? JSON.stringify(initialSeeding) : "", + app.isPackaged + ? path.join( + process.resourcesPath, + rustBinaryNameByPlatform[process.platform]! + ) + : path.join( + __dirname, + "..", + "..", + "rust_rpc", + "target", + "release", + rustBinaryNameByPlatform[process.platform]! + ), ]; if (app.isPackaged) {