From 53f07107b5a3498a8a0a8f2dd1b682ff67461519 Mon Sep 17 00:00:00 2001 From: David Ludwig Date: Wed, 12 May 2021 07:43:20 -0500 Subject: [PATCH] Torrent client can now also remove a torrent's files. Fixed bug where torrent was removed before files were deleted --- api/torrent/src/IpcClient.ts | 4 +-- services/torrent/src/services/IpcInterface.ts | 6 ++-- .../torrent/src/services/TorrentClient.ts | 30 ++++++++++++------- 3 files changed, 24 insertions(+), 16 deletions(-) diff --git a/api/torrent/src/IpcClient.ts b/api/torrent/src/IpcClient.ts index 67e3703..a6859ac 100644 --- a/api/torrent/src/IpcClient.ts +++ b/api/torrent/src/IpcClient.ts @@ -31,8 +31,8 @@ export class IpcClient extends IpcClientS * Remove a torrent from the client * @param torrent Torrent info hash */ - public async remove(torrent: string) { - let response = await this.request("remove", torrent); + public async remove(torrentId: string, withData: boolean = false) { + let response = await this.request("remove", { torrentId, withData }); if (response.error) { throw new Error("Failed to remove torrent"); } diff --git a/services/torrent/src/services/IpcInterface.ts b/services/torrent/src/services/IpcInterface.ts index b99222a..cb0d175 100644 --- a/services/torrent/src/services/IpcInterface.ts +++ b/services/torrent/src/services/IpcInterface.ts @@ -64,11 +64,11 @@ export default class IpcInterface extends IpcServerService /** * Remove a torrent from the client */ - protected async remove(torrentId: string) { - if (!this.torrentClient.has(torrentId)) { + protected async remove(payload: { torrentId: string, withData: boolean }) { + if (!this.torrentClient.has(payload.torrentId)) { return false; } - await this.torrentClient.remove(torrentId); + await this.torrentClient.remove(payload.torrentId, payload.withData); return true; } diff --git a/services/torrent/src/services/TorrentClient.ts b/services/torrent/src/services/TorrentClient.ts index 6b97491..635f717 100644 --- a/services/torrent/src/services/TorrentClient.ts +++ b/services/torrent/src/services/TorrentClient.ts @@ -3,6 +3,7 @@ import assert from "assert"; import MagnetUri from "magnet-uri"; import WebTorrent from "webtorrent-hybrid"; import parseTorrent from "parse-torrent"; +import { lstat } from "fs/promises"; import { extname, join, sep } from "path"; import rimraf from "rimraf"; import Torrent from "../database/entities/Torrent"; @@ -68,7 +69,7 @@ export class TorrentClient extends InternalService * Start the torrent client */ public start() { - console.log("Loading torrents..."); + this.log("Loading torrents..."); this.loadTorrents(); } @@ -93,7 +94,7 @@ export class TorrentClient extends InternalService * Invoked when a torrent has finished */ protected onTorrentFinish(torrent: WebTorrent.Torrent) { - console.log("Torrent finished:", torrent.name); + this.log("Torrent finished:", torrent.name); this.emit("torrent_finished", torrent); } @@ -153,6 +154,7 @@ export class TorrentClient extends InternalService toRemove.add(file.path.split(sep)[0]); }); toRemove.forEach(path => { + this.log("Removing:", join(torrent.path, path)); rimraf(join(torrent.path, path), (err) => { if (err) { return reject(err); @@ -171,16 +173,16 @@ export class TorrentClient extends InternalService protected addTorrent(torrent: MagnetUri.Instance, downloadPath: string, selectOnly?: number[]) { // Select only: Select no files by default due to broken selection mechanism in Webtorrent torrent.so = selectOnly ?? []; - console.log("Torrent added:", torrent.infoHash); + this.log("Torrent added:", torrent.infoHash); return this.__webtorrent.add(torrent, { path: downloadPath }); } /** * Remove a torrent from the client */ - protected removeTorrent(torrent: WebTorrent.Torrent) { - this.deleteTorrent(torrent); - // console.log("Torrent removed:", torrent.infoHash); + protected async removeTorrent(torrent: WebTorrent.Torrent) { + await this.deleteTorrent(torrent); + // this.log("Torrent removed:", torrent.infoHash); this.__webtorrent.remove(torrent); } @@ -215,15 +217,18 @@ export class TorrentClient extends InternalService // If the torrent already exists, skip it assert(this.__webtorrent.get(torrentInfo.infoHash) === null, "Torrent has already been added"); + // Ensure that the download path exists + let downloadPath = options.downloadPath ?? "/mnt/storage/Downloads"; + assert((await lstat(downloadPath)).isDirectory(), "The provided download path is invalid"); + // Add the torrent to the client - let torrent = this.addTorrent(torrentInfo, options.downloadPath ?? "/mnt/storage/Downloads"); + let torrent = this.addTorrent(torrentInfo, downloadPath); // When the metadata has beened fetched, select the files to download and store the torrent torrent.once("metadata", () => { this.filterSelectFiles(torrent, options.extensions); this.storeTorrent(torrent); - console.log(torrent.path); - + this.log(torrent.path); }); return torrent; @@ -241,13 +246,16 @@ export class TorrentClient extends InternalService let torrent = this.__webtorrent.get(torrentInfo.infoHash); assert(torrent !== null, "Torrent has not been added"); - // Remove the torrent - this.removeTorrent(torrent); + // Pause the torrent to prevent further download + torrent.pause(); // Delete data if necessary if (withData) { this.removeTorrentFiles(torrent); } + + // Remove the torrent + await this.removeTorrent(torrent); } public has(infoHash: string) {