mirror of
https://github.com/hydralauncher/hydra.git
synced 2025-02-03 00:33:49 +03:00
feat: adding initial torrent as arg command
This commit is contained in:
parent
a0cc15b5d8
commit
41dc504660
@ -2,6 +2,7 @@ import path from "node:path";
|
|||||||
import cp from "node:child_process";
|
import cp from "node:child_process";
|
||||||
import fs from "node:fs";
|
import fs from "node:fs";
|
||||||
import { app, dialog } from "electron";
|
import { app, dialog } from "electron";
|
||||||
|
import type { StartDownloadPayload } from "./types";
|
||||||
|
|
||||||
const binaryNameByPlatform: Partial<Record<NodeJS.Platform, string>> = {
|
const binaryNameByPlatform: Partial<Record<NodeJS.Platform, string>> = {
|
||||||
darwin: "hydra-download-manager",
|
darwin: "hydra-download-manager",
|
||||||
@ -12,9 +13,13 @@ const binaryNameByPlatform: Partial<Record<NodeJS.Platform, string>> = {
|
|||||||
export const BITTORRENT_PORT = "5881";
|
export const BITTORRENT_PORT = "5881";
|
||||||
export const RPC_PORT = "8084";
|
export const RPC_PORT = "8084";
|
||||||
|
|
||||||
const commonArgs = [BITTORRENT_PORT, RPC_PORT];
|
export const startTorrentClient = (args: StartDownloadPayload) => {
|
||||||
|
const commonArgs = [
|
||||||
|
BITTORRENT_PORT,
|
||||||
|
RPC_PORT,
|
||||||
|
encodeURIComponent(JSON.stringify(args)),
|
||||||
|
];
|
||||||
|
|
||||||
export const startTorrentClient = () => {
|
|
||||||
if (app.isPackaged) {
|
if (app.isPackaged) {
|
||||||
const binaryName = binaryNameByPlatform[process.platform]!;
|
const binaryName = binaryNameByPlatform[process.platform]!;
|
||||||
const binaryPath = path.join(
|
const binaryPath = path.join(
|
||||||
|
@ -7,59 +7,24 @@ import { DownloadProgress } from "@types";
|
|||||||
import { QueryDeepPartialEntity } from "typeorm/query-builder/QueryPartialEntity";
|
import { QueryDeepPartialEntity } from "typeorm/query-builder/QueryPartialEntity";
|
||||||
import { calculateETA } from "./helpers";
|
import { calculateETA } from "./helpers";
|
||||||
import axios from "axios";
|
import axios from "axios";
|
||||||
import { sleep } from "@main/helpers";
|
import {
|
||||||
import { logger } from "../logger";
|
type CancelDownloadPayload,
|
||||||
|
type StartDownloadPayload,
|
||||||
enum LibtorrentStatus {
|
type PauseDownloadPayload,
|
||||||
CheckingFiles = 1,
|
LibtorrentStatus,
|
||||||
DownloadingMetadata = 2,
|
LibtorrentPayload,
|
||||||
Downloading = 3,
|
} from "./types";
|
||||||
Finished = 4,
|
|
||||||
Seeding = 5,
|
|
||||||
}
|
|
||||||
|
|
||||||
interface LibtorrentPayload {
|
|
||||||
progress: number;
|
|
||||||
numPeers: number;
|
|
||||||
numSeeds: number;
|
|
||||||
downloadSpeed: number;
|
|
||||||
bytesDownloaded: number;
|
|
||||||
fileSize: number;
|
|
||||||
folderName: string;
|
|
||||||
status: LibtorrentStatus;
|
|
||||||
gameId: number;
|
|
||||||
}
|
|
||||||
|
|
||||||
export class TorrentDownloader {
|
export class TorrentDownloader {
|
||||||
private static torrentClient: cp.ChildProcess | null = null;
|
private static torrentClient: cp.ChildProcess | null = null;
|
||||||
private static downloadingGameId = -1;
|
private static downloadingGameId = -1;
|
||||||
|
|
||||||
private static rpc = axios.create({
|
private static rpc = axios.create({
|
||||||
baseURL: `http://localhost:${RPC_PORT}`,
|
baseURL: `http://localhost:${RPC_PORT}`,
|
||||||
});
|
});
|
||||||
|
|
||||||
private static async healthCheck(retries = 15) {
|
private static spawn(args: StartDownloadPayload) {
|
||||||
try {
|
this.torrentClient = startTorrentClient(args);
|
||||||
await this.rpc.get("/healthcheck");
|
|
||||||
} catch (err) {
|
|
||||||
if (retries === 0) {
|
|
||||||
throw new Error("Failed to connect to libtorrent client");
|
|
||||||
}
|
|
||||||
|
|
||||||
await sleep(1000);
|
|
||||||
|
|
||||||
return this.healthCheck(retries - 1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private static async spawn() {
|
|
||||||
try {
|
|
||||||
this.torrentClient = startTorrentClient();
|
|
||||||
await this.healthCheck();
|
|
||||||
|
|
||||||
logger.log("libtorrent client started");
|
|
||||||
} catch (err) {
|
|
||||||
logger.error(err);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static kill() {
|
public static kill() {
|
||||||
@ -71,7 +36,6 @@ export class TorrentDownloader {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public static async getStatus() {
|
public static async getStatus() {
|
||||||
if (!this.torrentClient) this.spawn();
|
|
||||||
if (this.downloadingGameId === -1) return null;
|
if (this.downloadingGameId === -1) return null;
|
||||||
|
|
||||||
const response = await this.rpc.get<LibtorrentPayload | null>("/status");
|
const response = await this.rpc.get<LibtorrentPayload | null>("/status");
|
||||||
@ -134,36 +98,42 @@ export class TorrentDownloader {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static async pauseDownload() {
|
static async pauseDownload() {
|
||||||
if (!this.torrentClient) await this.spawn();
|
await this.rpc
|
||||||
|
.post("/action", {
|
||||||
await this.rpc.post("/action", {
|
|
||||||
action: "pause",
|
action: "pause",
|
||||||
game_id: this.downloadingGameId,
|
game_id: this.downloadingGameId,
|
||||||
});
|
} as PauseDownloadPayload)
|
||||||
|
.catch(() => {});
|
||||||
|
|
||||||
this.downloadingGameId = -1;
|
this.downloadingGameId = -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
static async startDownload(game: Game) {
|
static async startDownload(game: Game) {
|
||||||
if (!this.torrentClient) await this.spawn();
|
if (!this.torrentClient) {
|
||||||
|
this.spawn({
|
||||||
|
game_id: game.id,
|
||||||
|
magnet: game.uri!,
|
||||||
|
save_path: game.downloadPath!,
|
||||||
|
});
|
||||||
|
} else {
|
||||||
await this.rpc.post("/action", {
|
await this.rpc.post("/action", {
|
||||||
action: "start",
|
action: "start",
|
||||||
game_id: game.id,
|
game_id: game.id,
|
||||||
magnet: game.uri,
|
magnet: game.uri,
|
||||||
save_path: game.downloadPath,
|
save_path: game.downloadPath,
|
||||||
});
|
} as StartDownloadPayload);
|
||||||
|
}
|
||||||
|
|
||||||
this.downloadingGameId = game.id;
|
this.downloadingGameId = game.id;
|
||||||
}
|
}
|
||||||
|
|
||||||
static async cancelDownload(gameId: number) {
|
static async cancelDownload(gameId: number) {
|
||||||
if (!this.torrentClient) await this.spawn();
|
await this.rpc
|
||||||
|
.post("/action", {
|
||||||
await this.rpc.post("/action", {
|
|
||||||
action: "cancel",
|
action: "cancel",
|
||||||
game_id: gameId,
|
game_id: gameId,
|
||||||
});
|
} as CancelDownloadPayload)
|
||||||
|
.catch(() => {});
|
||||||
|
|
||||||
this.downloadingGameId = -1;
|
this.downloadingGameId = -1;
|
||||||
}
|
}
|
||||||
|
33
src/main/services/download/types.ts
Normal file
33
src/main/services/download/types.ts
Normal file
@ -0,0 +1,33 @@
|
|||||||
|
export interface StartDownloadPayload {
|
||||||
|
game_id: number;
|
||||||
|
magnet: string;
|
||||||
|
save_path: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface PauseDownloadPayload {
|
||||||
|
game_id: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface CancelDownloadPayload {
|
||||||
|
game_id: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
export enum LibtorrentStatus {
|
||||||
|
CheckingFiles = 1,
|
||||||
|
DownloadingMetadata = 2,
|
||||||
|
Downloading = 3,
|
||||||
|
Finished = 4,
|
||||||
|
Seeding = 5,
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface LibtorrentPayload {
|
||||||
|
progress: number;
|
||||||
|
numPeers: number;
|
||||||
|
numSeeds: number;
|
||||||
|
downloadSpeed: number;
|
||||||
|
bytesDownloaded: number;
|
||||||
|
fileSize: number;
|
||||||
|
folderName: string;
|
||||||
|
status: LibtorrentStatus;
|
||||||
|
gameId: number;
|
||||||
|
}
|
@ -4,9 +4,11 @@ from http.server import HTTPServer, BaseHTTPRequestHandler
|
|||||||
import json
|
import json
|
||||||
import threading
|
import threading
|
||||||
import time
|
import time
|
||||||
|
import urllib.parse
|
||||||
|
|
||||||
torrent_port = sys.argv[1]
|
torrent_port = sys.argv[1]
|
||||||
http_port = sys.argv[2]
|
http_port = sys.argv[2]
|
||||||
|
initial_download = json.loads(urllib.parse.unquote(sys.argv[3]))
|
||||||
|
|
||||||
class Downloader:
|
class Downloader:
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
@ -62,6 +64,8 @@ class Downloader:
|
|||||||
|
|
||||||
downloader = Downloader()
|
downloader = Downloader()
|
||||||
|
|
||||||
|
downloader.start_download(initial_download['game_id'], initial_download['magnet'], initial_download['save_path'])
|
||||||
|
|
||||||
class Handler(BaseHTTPRequestHandler):
|
class Handler(BaseHTTPRequestHandler):
|
||||||
def do_GET(self):
|
def do_GET(self):
|
||||||
if self.path == "/status":
|
if self.path == "/status":
|
||||||
|
Loading…
Reference in New Issue
Block a user