diff --git a/WebAPI_Changelog.md b/WebAPI_Changelog.md index 2345df422..2cb5fe033 100644 --- a/WebAPI_Changelog.md +++ b/WebAPI_Changelog.md @@ -6,6 +6,10 @@ * `endpoints` is an array of tracker endpoints, each with `name`, `updating`, `status`, `msg`, `bt_version`, `num_peers`, `num_peers`, `num_leeches`, `num_downloaded`, `next_announce` and `min_announce` fields * `torrents/trackers` now returns `5` and `6` in `status` field as possible values * `5` for `Tracker error` and `6` for `Unreachable` +* [#22963](https://github.com/qbittorrent/qBittorrent/pull/22963) + * `torrents/editTracker` endpoint now supports setting a tracker's tier via `tier` parameter + * `torrents/editTracker` endpoint always responds with a 204 when successful + * `torrents/editTracker` endpoint `origUrl` parameter renamed to `url` ## 2.12.1 * [#23031](https://github.com/qbittorrent/qBittorrent/pull/23031) diff --git a/src/webui/api/torrentscontroller.cpp b/src/webui/api/torrentscontroller.cpp index 1df3a820c..4c7083c51 100644 --- a/src/webui/api/torrentscontroller.cpp +++ b/src/webui/api/torrentscontroller.cpp @@ -1160,22 +1160,44 @@ void TorrentsController::addTrackersAction() void TorrentsController::editTrackerAction() { - requireParams({u"hash"_s, u"origUrl"_s, u"newUrl"_s}); + requireParams({u"hash"_s, u"url"_s}); const auto id = BitTorrent::TorrentID::fromString(params()[u"hash"_s]); - const QString origUrl = params()[u"origUrl"_s]; - const QString newUrl = params()[u"newUrl"_s]; + const QString origUrl = params()[u"url"_s]; + const std::optional newUrlParam = getOptionalString(params(), u"newUrl"_s); + const std::optional newTierParam = getOptionalString(params(), u"tier"_s); BitTorrent::Torrent *const torrent = BitTorrent::Session::instance()->getTorrent(id); if (!torrent) throw APIError(APIErrorType::NotFound); + if (!newUrlParam && !newTierParam) + throw APIError(APIErrorType::BadParams, tr("Must specify at least one of [newUrl, tier]")); + + std::optional newTier; + if (newTierParam) + { + bool ok = false; + const auto number = newTierParam.value().toInt(&ok); + if (!ok) + throw APIError(APIErrorType::BadParams, tr("tier must be an integer")); + if ((number < 0) || (number > 255)) + throw APIError(APIErrorType::BadParams, tr("tier must be between 0 and 255")); + newTier = number; + } const QUrl origTrackerUrl {origUrl}; - const QUrl newTrackerUrl {newUrl}; - if (origTrackerUrl == newTrackerUrl) + std::optional newTrackerUrl; + if (newUrlParam) + { + const QUrl url = newUrlParam.value(); + if (!url.isValid()) + throw APIError(APIErrorType::BadParams, tr("New tracker URL is invalid")); + if (url != origTrackerUrl) + newTrackerUrl = url; + } + + if (!newTrackerUrl && !newTier) return; - if (!newTrackerUrl.isValid()) - throw APIError(APIErrorType::BadParams, u"New tracker URL is invalid"_s); const QList currentTrackers = torrent->trackers(); QList entries; @@ -1186,8 +1208,8 @@ void TorrentsController::editTrackerAction() { const QUrl trackerUrl {tracker.url}; - if (trackerUrl == newTrackerUrl) - throw APIError(APIErrorType::Conflict, u"New tracker URL already exists"_s); + if (newTrackerUrl && (trackerUrl == newTrackerUrl)) + throw APIError(APIErrorType::Conflict, tr("New tracker URL already exists")); BitTorrent::TrackerEntry entry { @@ -1197,18 +1219,23 @@ void TorrentsController::editTrackerAction() if (trackerUrl == origTrackerUrl) { + const bool isTrackerTierChanged = newTier && (tracker.tier != newTier); + if (!newTrackerUrl && !isTrackerTierChanged) + return; + match = true; - entry.url = newTrackerUrl.toString(); + if (newTrackerUrl) + entry.url = newTrackerUrl.value().toString(); + if (newTier) + entry.tier = newTier.value(); } entries.append(entry); } if (!match) - throw APIError(APIErrorType::Conflict, u"Tracker not found"_s); + throw APIError(APIErrorType::Conflict, tr("Tracker not found")); torrent->replaceTrackers(entries); torrent->forceReannounce(); - - setResult(QString()); } void TorrentsController::removeTrackersAction() @@ -1246,7 +1273,7 @@ void TorrentsController::addPeersAction() } if (peerList.isEmpty()) - throw APIError(APIErrorType::BadParams, u"No valid peers were specified"_s); + throw APIError(APIErrorType::BadParams, tr("No valid peers were specified")); QJsonObject results; diff --git a/src/webui/www/private/edittracker.html b/src/webui/www/private/edittracker.html index b5aff329d..383937cfc 100644 --- a/src/webui/www/private/edittracker.html +++ b/src/webui/www/private/edittracker.html @@ -26,9 +26,11 @@ const searchParams = new URLSearchParams(window.location.search); const currentUrl = searchParams.get("url"); - if (currentUrl === null) + const currentTier = searchParams.get("tier"); + if ((currentUrl === null) || (currentTier === null)) return; + document.getElementById("trackerTier").value = currentTier; document.getElementById("trackerUrl").value = currentUrl; document.getElementById("trackerUrl").focus(); @@ -40,8 +42,9 @@ method: "POST", body: new URLSearchParams({ hash: searchParams.get("hash"), - origUrl: currentUrl, - newUrl: document.getElementById("trackerUrl").value + url: currentUrl, + newUrl: document.getElementById("trackerUrl").value, + tier: document.getElementById("trackerTier").value }) }) .then((response) => { @@ -63,6 +66,11 @@
+ +
+ +
+
diff --git a/src/webui/www/private/scripts/prop-trackers.js b/src/webui/www/private/scripts/prop-trackers.js index f5fb10f81..e25f2e3b7 100644 --- a/src/webui/www/private/scripts/prop-trackers.js +++ b/src/webui/www/private/scripts/prop-trackers.js @@ -255,13 +255,21 @@ window.qBittorrent.PropTrackers ??= (() => { if (current_hash.length === 0) return; - const trackerUrl = encodeURIComponent(torrentTrackersTable.selectedRowsIds()[0]); + const tracker = torrentTrackersTable.getRow(torrentTrackersTable.getSelectedRowId()); + const contentURL = new URL("edittracker.html", window.location); + contentURL.search = new URLSearchParams({ + v: "${CACHEID}", + hash: current_hash, + url: tracker.full_data.url, + tier: tracker.full_data.tier + }); + new MochaUI.Window({ id: "trackersPage", icon: "images/qbittorrent-tray.svg", title: "QBT_TR(Tracker editing)QBT_TR[CONTEXT=TrackerListWidget]", loadMethod: "iframe", - contentURL: `edittracker.html?v=${CACHEID}&hash=${current_hash}&url=${trackerUrl}`, + contentURL: contentURL.toString(), scrollbars: true, resizable: false, maximizable: false, @@ -269,7 +277,7 @@ window.qBittorrent.PropTrackers ??= (() => { paddingVertical: 0, paddingHorizontal: 0, width: window.qBittorrent.Dialog.limitWidthToViewport(500), - height: 150, + height: 200, onCloseComplete: () => { updateData(); }