|
|
@ -1,3 +1,5 @@ |
|
|
|
import { mkdir } from "fs/promises"; |
|
|
|
import { dirname } from "path"; |
|
|
|
import ipc from "node-ipc"; |
|
|
|
import type { Server } from "node-ipc"; |
|
|
|
import { Socket } from "net"; |
|
|
@ -12,6 +14,9 @@ type IAddTorrent = string | { |
|
|
|
|
|
|
|
export default class IpcInterface |
|
|
|
{ |
|
|
|
/** |
|
|
|
* The torrent client instance |
|
|
|
*/ |
|
|
|
protected torrentClient: TorrentClient; |
|
|
|
|
|
|
|
/** |
|
|
@ -34,8 +39,9 @@ export default class IpcInterface |
|
|
|
* Boot the IPC interface |
|
|
|
*/ |
|
|
|
public boot() { |
|
|
|
return new Promise<void>((resolve, reject) => { |
|
|
|
return new Promise<void>(async (resolve, reject) => { |
|
|
|
console.log("Serving:", process.env["IPC_SOCKET_PATH"]); |
|
|
|
await mkdir(dirname(<string>process.env["IPC_SOCKET_PATH"]), { recursive: true }); |
|
|
|
ipc.serve(<string>process.env["IPC_SOCKET_PATH"], () => { |
|
|
|
this.server = ipc.server; |
|
|
|
this.installEventHandlers(this.server); |
|
|
@ -53,6 +59,7 @@ export default class IpcInterface |
|
|
|
this.addEventHandler(server, "remove", this.removeTorrent); |
|
|
|
this.addEventHandler(server, "list", this.listTorrents); |
|
|
|
this.addEventHandler(server, "details", this.torrentDetails); |
|
|
|
this.torrentClient.on("torrent_finished", this.torrentFinished.bind(this)); |
|
|
|
} |
|
|
|
|
|
|
|
/** |
|
|
@ -61,7 +68,7 @@ export default class IpcInterface |
|
|
|
protected addEventHandler(server: Server, method: string, handle: (...args: any[]) => Promise<any>) { |
|
|
|
server.on(method, async (message: any, socket: Socket) => { |
|
|
|
try { |
|
|
|
let response = await handle.apply(this, [message]); |
|
|
|
let response = await handle.apply(this, message); |
|
|
|
this.server.emit(socket, method, { response }); |
|
|
|
} catch (error) { |
|
|
|
console.log("Error:", method, error); |
|
|
@ -81,9 +88,9 @@ export default class IpcInterface |
|
|
|
protected async addTorrent(torrentInfo: IAddTorrent, downloadPath?: string) { |
|
|
|
let torrent: WebTorrent.Torrent; |
|
|
|
if (typeof torrentInfo == "string") { |
|
|
|
torrent = await this.torrentClient.add(torrentInfo); |
|
|
|
torrent = await this.torrentClient.add(torrentInfo, { downloadPath }); |
|
|
|
} else { |
|
|
|
torrent = await this.torrentClient.add(Buffer.from(torrentInfo.data)); |
|
|
|
torrent = await this.torrentClient.add(Buffer.from(torrentInfo.data), { downloadPath }); |
|
|
|
} |
|
|
|
return torrent.infoHash; |
|
|
|
} |
|
|
@ -120,4 +127,22 @@ export default class IpcInterface |
|
|
|
} |
|
|
|
return torrents.map(torrent => this.torrentClient.serializeTorrent(torrent)); |
|
|
|
} |
|
|
|
|
|
|
|
// Subscription Interface Methods --------------------------------------------------------------
|
|
|
|
|
|
|
|
/** |
|
|
|
* Broadcast a message to the connected clients |
|
|
|
*/ |
|
|
|
protected broadcast(method: string, ...message: any[]) { |
|
|
|
for (let socket of <Socket[]>(<any>ipc.server).sockets) { |
|
|
|
this.server.emit(socket, method, message); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
/** |
|
|
|
* Notify connected clients that a torrent has finished |
|
|
|
*/ |
|
|
|
public torrentFinished(torrent: WebTorrent.Torrent) { |
|
|
|
this.broadcast("torrent_finished", torrent.infoHash); |
|
|
|
} |
|
|
|
} |