mirror of
https://github.com/qbittorrent/qBittorrent
synced 2025-08-20 13:23:34 -07:00
WebUI: Support editing tracker tier
This PR adds the ability to direct modify a tracker's tier from the WebUI. This process is notably different than the GUI, which provides arrows for increasing/decreasing a tracker's tier. Closes #12233. PR #22963.
This commit is contained in:
parent
b2d6323034
commit
6ef9db89f9
4 changed files with 67 additions and 20 deletions
|
@ -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
|
* `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
|
* `torrents/trackers` now returns `5` and `6` in `status` field as possible values
|
||||||
* `5` for `Tracker error` and `6` for `Unreachable`
|
* `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
|
## 2.12.1
|
||||||
* [#23031](https://github.com/qbittorrent/qBittorrent/pull/23031)
|
* [#23031](https://github.com/qbittorrent/qBittorrent/pull/23031)
|
||||||
|
|
|
@ -1160,22 +1160,44 @@ void TorrentsController::addTrackersAction()
|
||||||
|
|
||||||
void TorrentsController::editTrackerAction()
|
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 auto id = BitTorrent::TorrentID::fromString(params()[u"hash"_s]);
|
||||||
const QString origUrl = params()[u"origUrl"_s];
|
const QString origUrl = params()[u"url"_s];
|
||||||
const QString newUrl = params()[u"newUrl"_s];
|
const std::optional<QString> newUrlParam = getOptionalString(params(), u"newUrl"_s);
|
||||||
|
const std::optional<QString> newTierParam = getOptionalString(params(), u"tier"_s);
|
||||||
|
|
||||||
BitTorrent::Torrent *const torrent = BitTorrent::Session::instance()->getTorrent(id);
|
BitTorrent::Torrent *const torrent = BitTorrent::Session::instance()->getTorrent(id);
|
||||||
if (!torrent)
|
if (!torrent)
|
||||||
throw APIError(APIErrorType::NotFound);
|
throw APIError(APIErrorType::NotFound);
|
||||||
|
if (!newUrlParam && !newTierParam)
|
||||||
|
throw APIError(APIErrorType::BadParams, tr("Must specify at least one of [newUrl, tier]"));
|
||||||
|
|
||||||
|
std::optional<int> 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 origTrackerUrl {origUrl};
|
||||||
const QUrl newTrackerUrl {newUrl};
|
std::optional<QUrl> newTrackerUrl;
|
||||||
if (origTrackerUrl == 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;
|
return;
|
||||||
if (!newTrackerUrl.isValid())
|
|
||||||
throw APIError(APIErrorType::BadParams, u"New tracker URL is invalid"_s);
|
|
||||||
|
|
||||||
const QList<BitTorrent::TrackerEntryStatus> currentTrackers = torrent->trackers();
|
const QList<BitTorrent::TrackerEntryStatus> currentTrackers = torrent->trackers();
|
||||||
QList<BitTorrent::TrackerEntry> entries;
|
QList<BitTorrent::TrackerEntry> entries;
|
||||||
|
@ -1186,8 +1208,8 @@ void TorrentsController::editTrackerAction()
|
||||||
{
|
{
|
||||||
const QUrl trackerUrl {tracker.url};
|
const QUrl trackerUrl {tracker.url};
|
||||||
|
|
||||||
if (trackerUrl == newTrackerUrl)
|
if (newTrackerUrl && (trackerUrl == newTrackerUrl))
|
||||||
throw APIError(APIErrorType::Conflict, u"New tracker URL already exists"_s);
|
throw APIError(APIErrorType::Conflict, tr("New tracker URL already exists"));
|
||||||
|
|
||||||
BitTorrent::TrackerEntry entry
|
BitTorrent::TrackerEntry entry
|
||||||
{
|
{
|
||||||
|
@ -1197,18 +1219,23 @@ void TorrentsController::editTrackerAction()
|
||||||
|
|
||||||
if (trackerUrl == origTrackerUrl)
|
if (trackerUrl == origTrackerUrl)
|
||||||
{
|
{
|
||||||
|
const bool isTrackerTierChanged = newTier && (tracker.tier != newTier);
|
||||||
|
if (!newTrackerUrl && !isTrackerTierChanged)
|
||||||
|
return;
|
||||||
|
|
||||||
match = true;
|
match = true;
|
||||||
entry.url = newTrackerUrl.toString();
|
if (newTrackerUrl)
|
||||||
|
entry.url = newTrackerUrl.value().toString();
|
||||||
|
if (newTier)
|
||||||
|
entry.tier = newTier.value();
|
||||||
}
|
}
|
||||||
entries.append(entry);
|
entries.append(entry);
|
||||||
}
|
}
|
||||||
if (!match)
|
if (!match)
|
||||||
throw APIError(APIErrorType::Conflict, u"Tracker not found"_s);
|
throw APIError(APIErrorType::Conflict, tr("Tracker not found"));
|
||||||
|
|
||||||
torrent->replaceTrackers(entries);
|
torrent->replaceTrackers(entries);
|
||||||
torrent->forceReannounce();
|
torrent->forceReannounce();
|
||||||
|
|
||||||
setResult(QString());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void TorrentsController::removeTrackersAction()
|
void TorrentsController::removeTrackersAction()
|
||||||
|
@ -1246,7 +1273,7 @@ void TorrentsController::addPeersAction()
|
||||||
}
|
}
|
||||||
|
|
||||||
if (peerList.isEmpty())
|
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;
|
QJsonObject results;
|
||||||
|
|
||||||
|
|
|
@ -26,9 +26,11 @@
|
||||||
|
|
||||||
const searchParams = new URLSearchParams(window.location.search);
|
const searchParams = new URLSearchParams(window.location.search);
|
||||||
const currentUrl = searchParams.get("url");
|
const currentUrl = searchParams.get("url");
|
||||||
if (currentUrl === null)
|
const currentTier = searchParams.get("tier");
|
||||||
|
if ((currentUrl === null) || (currentTier === null))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
document.getElementById("trackerTier").value = currentTier;
|
||||||
document.getElementById("trackerUrl").value = currentUrl;
|
document.getElementById("trackerUrl").value = currentUrl;
|
||||||
document.getElementById("trackerUrl").focus();
|
document.getElementById("trackerUrl").focus();
|
||||||
|
|
||||||
|
@ -40,8 +42,9 @@
|
||||||
method: "POST",
|
method: "POST",
|
||||||
body: new URLSearchParams({
|
body: new URLSearchParams({
|
||||||
hash: searchParams.get("hash"),
|
hash: searchParams.get("hash"),
|
||||||
origUrl: currentUrl,
|
url: currentUrl,
|
||||||
newUrl: document.getElementById("trackerUrl").value
|
newUrl: document.getElementById("trackerUrl").value,
|
||||||
|
tier: document.getElementById("trackerTier").value
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
.then((response) => {
|
.then((response) => {
|
||||||
|
@ -63,6 +66,11 @@
|
||||||
<input type="text" id="trackerUrl" style="width: 90%;">
|
<input type="text" id="trackerUrl" style="width: 90%;">
|
||||||
</div>
|
</div>
|
||||||
<br>
|
<br>
|
||||||
|
<label for="trackerTier">QBT_TR(Tier:)QBT_TR[CONTEXT=TrackerListWidget]</label>
|
||||||
|
<div style="text-align: center; padding-top: 10px;">
|
||||||
|
<input type="number" id="trackerTier" style="width: 90%; max-width: 100px;" min="0" max="255">
|
||||||
|
</div>
|
||||||
|
<br>
|
||||||
<input type="button" value="QBT_TR(Edit)QBT_TR[CONTEXT=HttpServer]" id="editTrackerButton">
|
<input type="button" value="QBT_TR(Edit)QBT_TR[CONTEXT=HttpServer]" id="editTrackerButton">
|
||||||
</div>
|
</div>
|
||||||
</body>
|
</body>
|
||||||
|
|
|
@ -255,13 +255,21 @@ window.qBittorrent.PropTrackers ??= (() => {
|
||||||
if (current_hash.length === 0)
|
if (current_hash.length === 0)
|
||||||
return;
|
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({
|
new MochaUI.Window({
|
||||||
id: "trackersPage",
|
id: "trackersPage",
|
||||||
icon: "images/qbittorrent-tray.svg",
|
icon: "images/qbittorrent-tray.svg",
|
||||||
title: "QBT_TR(Tracker editing)QBT_TR[CONTEXT=TrackerListWidget]",
|
title: "QBT_TR(Tracker editing)QBT_TR[CONTEXT=TrackerListWidget]",
|
||||||
loadMethod: "iframe",
|
loadMethod: "iframe",
|
||||||
contentURL: `edittracker.html?v=${CACHEID}&hash=${current_hash}&url=${trackerUrl}`,
|
contentURL: contentURL.toString(),
|
||||||
scrollbars: true,
|
scrollbars: true,
|
||||||
resizable: false,
|
resizable: false,
|
||||||
maximizable: false,
|
maximizable: false,
|
||||||
|
@ -269,7 +277,7 @@ window.qBittorrent.PropTrackers ??= (() => {
|
||||||
paddingVertical: 0,
|
paddingVertical: 0,
|
||||||
paddingHorizontal: 0,
|
paddingHorizontal: 0,
|
||||||
width: window.qBittorrent.Dialog.limitWidthToViewport(500),
|
width: window.qBittorrent.Dialog.limitWidthToViewport(500),
|
||||||
height: 150,
|
height: 200,
|
||||||
onCloseComplete: () => {
|
onCloseComplete: () => {
|
||||||
updateData();
|
updateData();
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue