|
|
@ -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) { |
|
|
|