From 7846eb6672cc48596b2c15eb3eb99abd4159fb12 Mon Sep 17 00:00:00 2001 From: Jesse Chan Date: Thu, 29 Apr 2021 14:34:16 +0800 Subject: [PATCH] server: qBittorrent: implement syncing syncTorrentPeers --- .../qBittorrent/clientRequestManager.ts | 65 +++++++++++++++---- .../types/QBittorrentSyncMethods.ts | 14 ++-- 2 files changed, 64 insertions(+), 15 deletions(-) diff --git a/server/services/qBittorrent/clientRequestManager.ts b/server/services/qBittorrent/clientRequestManager.ts index 584f2913..06c687c1 100644 --- a/server/services/qBittorrent/clientRequestManager.ts +++ b/server/services/qBittorrent/clientRequestManager.ts @@ -4,7 +4,7 @@ import FormData from 'form-data'; import type {QBittorrentConnectionSettings} from '@shared/schema/ClientConnectionSettings'; import type {QBittorrentAppPreferences} from './types/QBittorrentAppMethods'; -import type {QBittorrentSyncTorrentPeers} from './types/QBittorrentSyncMethods'; +import type {QBittorrentSyncTorrentPeers, QBittorrentTorrentPeers} from './types/QBittorrentSyncMethods'; import type {QBittorrentTransferInfo} from './types/QBittorrentTransferMethods'; import type { QBittorrentTorrentContentPriority, @@ -20,6 +20,16 @@ class ClientRequestManager { private apiBase: string; private authCookie?: Promise; + private syncRids: { + torrentPeers: Record>; + } = { + torrentPeers: {}, + }; + + private syncStates: { + torrentPeers: Record; + } = {torrentPeers: {}}; + async authenticate(connectionSettings = this.connectionSettings): Promise { const {url, username, password} = connectionSettings; @@ -128,16 +138,49 @@ class ClientRequestManager { .then((json) => json.data); } - async syncTorrentPeers(hash: string): Promise { - return axios - .get(`${this.apiBase}/sync/torrentPeers`, { - params: { - hash, - rid: 0, - }, - headers: {Cookie: await this.authCookie}, - }) - .then((json) => json.data.peers); + async syncTorrentPeers(hash: string): Promise { + const Cookie = await this.authCookie; + + this.syncRids.torrentPeers[hash] = (this.syncRids.torrentPeers[hash] ?? Promise.resolve(0)).then((rid) => + axios + .get(`${this.apiBase}/sync/torrentPeers`, { + params: { + hash, + rid, + }, + headers: {Cookie}, + }) + .then(({data}) => { + const {peers = {}, peers_removed = [], rid: newRid = 0} = data; + + if (this.syncStates.torrentPeers[hash] == null) { + this.syncStates.torrentPeers[hash] = {}; + } + + Object.keys(peers).forEach((ip_and_port) => { + this.syncStates.torrentPeers[hash][ip_and_port] = { + ...this.syncStates.torrentPeers[hash][ip_and_port], + ...peers[ip_and_port], + }; + }); + + peers_removed.forEach((ip_and_port) => { + delete this.syncStates.torrentPeers[hash][ip_and_port]; + }); + + return newRid; + }), + ); + + try { + await this.syncRids.torrentPeers[hash]; + } catch (e) { + delete this.syncRids.torrentPeers[hash]; + delete this.syncStates.torrentPeers[hash]; + throw e; + } + + return this.syncStates.torrentPeers[hash]; } async torrentsPause(hashes: Array): Promise { diff --git a/server/services/qBittorrent/types/QBittorrentSyncMethods.ts b/server/services/qBittorrent/types/QBittorrentSyncMethods.ts index 691adc7a..c4e14d87 100644 --- a/server/services/qBittorrent/types/QBittorrentSyncMethods.ts +++ b/server/services/qBittorrent/types/QBittorrentSyncMethods.ts @@ -1,4 +1,4 @@ -export interface QBittorrentSyncTorrentPeer { +export interface QBittorrentTorrentPeer { client: string; connection: string; country: string; @@ -16,6 +16,12 @@ export interface QBittorrentSyncTorrentPeer { relevance: number; } -export type QBittorrentSyncTorrentPeers = { - [ip_and_port: string]: QBittorrentSyncTorrentPeer; -}; +export interface QBittorrentSyncTorrentPeers { + rid: number; + peers?: { + [ip_and_port: string]: QBittorrentTorrentPeer; + }; + peers_removed?: string[]; +} + +export type QBittorrentTorrentPeers = Exclude;