diff --git a/src/webui/api/torrentscontroller.cpp b/src/webui/api/torrentscontroller.cpp index f7c6118a0..98c01c3a2 100644 --- a/src/webui/api/torrentscontroller.cpp +++ b/src/webui/api/torrentscontroller.cpp @@ -1116,16 +1116,42 @@ void TorrentsController::addAction() void TorrentsController::addTrackersAction() { requireParams({u"hash"_s, u"urls"_s}); - - const auto id = BitTorrent::TorrentID::fromString(params()[u"hash"_s]); - BitTorrent::Torrent *const torrent = BitTorrent::Session::instance()->getTorrent(id); - if (!torrent) - throw APIError(APIErrorType::NotFound); - + const QString hashParam = params()[u"hash"_s]; + QList torrents; const QList entries = BitTorrent::parseTrackerEntries(params()[u"urls"_s]); - torrent->addTrackers(entries); - setResult(QString()); + if (hashParam == u"*"_s) + { + // add this tracker to all torrents + torrents = BitTorrent::Session::instance()->torrents(); + } + else if (hashParam.contains(u'|')) + { + // add this tracker to all torrents in the list + const QStringList idStrings = hashParam.split(u'|', Qt::SkipEmptyParts); + for (const QString &hash : idStrings) + { + const auto id = BitTorrent::TorrentID::fromString(hash); + BitTorrent::Torrent *const torrent = BitTorrent::Session::instance()->getTorrent(id); + if (!torrent) + throw APIError(APIErrorType::NotFound); + + torrents.append(torrent); + } + } + else + { + // add this tracker just to this torrent + const auto id = BitTorrent::TorrentID::fromString(hashParam); + BitTorrent::Torrent *const torrent = BitTorrent::Session::instance()->getTorrent(id); + if (!torrent) + throw APIError(APIErrorType::NotFound); + + torrents.append(torrent); + } + + for (BitTorrent::Torrent *const torrent : asConst(torrents)) + torrent->addTrackers(entries); } void TorrentsController::editTrackerAction() @@ -1202,6 +1228,20 @@ void TorrentsController::removeTrackersAction() // remove trackers from all torrents torrents = BitTorrent::Session::instance()->torrents(); } + else if (hashParam.contains(u'|')) + { + // remove trackers from all torrents in the list + const QStringList idStrings = hashParam.split(u'|', Qt::SkipEmptyParts); + for (const QString &hash : idStrings) + { + const auto id = BitTorrent::TorrentID::fromString(hash); + BitTorrent::Torrent *const torrent = BitTorrent::Session::instance()->getTorrent(id); + if (!torrent) + throw APIError(APIErrorType::NotFound); + + torrents.append(torrent); + } + } else { // remove trackers from specified torrent diff --git a/src/webui/www/private/scripts/prop-trackers.js b/src/webui/www/private/scripts/prop-trackers.js index 7214895b4..195fb62b7 100644 --- a/src/webui/www/private/scripts/prop-trackers.js +++ b/src/webui/www/private/scripts/prop-trackers.js @@ -178,8 +178,17 @@ window.qBittorrent.PropTrackers ??= (() => { }); const addTrackerFN = () => { + const selectedTorrents = torrentsTable.selectedRowsIds(); if (current_hash.length === 0) + { return; + } + + if (selectedTorrents.length !== 0) + { + current_hash = selectedTorrents.map(encodeURIComponent).join("|"); + } + new MochaUI.Window({ id: "trackersPage", icon: "images/qbittorrent-tray.svg", @@ -226,8 +235,16 @@ window.qBittorrent.PropTrackers ??= (() => { }; const removeTrackerFN = (element) => { + const selectedTorrents = torrentsTable.selectedRowsIds(); if (current_hash.length === 0) + { return; + } + + if (selectedTorrents.length !== 0) + { + current_hash = selectedTorrents.map(encodeURIComponent).join("|"); + } fetch("api/v2/torrents/removeTrackers", { method: "POST",