Skip to content

Commit 163f683

Browse files
authored
WebUI: Support reannouncing individual trackers
PR #22954.
1 parent 7c443b0 commit 163f683

File tree

5 files changed

+72
-3
lines changed

5 files changed

+72
-3
lines changed

WebAPI_Changelog.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@
44

55
* [#22932](https://github.com/qbittorrent/qBittorrent/pull/22932)
66
* `torrents/categories` and `sync/maindata` now serialize categories' `downloadPath` to `null`, rather than `undefined`
7+
* [#22954](https://github.com/qbittorrent/qBittorrent/pull/22954)
8+
* `torrents/reannounce` supports specifying individual trackers via `trackers` field
79

810
## 2.11.9
911

src/webui/api/torrentscontroller.cpp

Lines changed: 23 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1618,10 +1618,30 @@ void TorrentsController::reannounceAction()
16181618
requireParams({u"hashes"_s});
16191619

16201620
const QStringList hashes {params()[u"hashes"_s].split(u'|')};
1621-
applyToTorrents(hashes, [](BitTorrent::Torrent *const torrent)
1621+
const QStringList urlsParam {params()[u"urls"_s].split(u'|', Qt::SkipEmptyParts)};
1622+
1623+
QSet<QString> urls;
1624+
urls.reserve(urlsParam.size());
1625+
for (const QString &urlStr : urlsParam)
1626+
urls << QUrl::fromPercentEncoding(urlStr.toLatin1());
1627+
1628+
applyToTorrents(hashes, [&urls](BitTorrent::Torrent *const torrent)
16221629
{
1623-
torrent->forceReannounce();
1624-
torrent->forceDHTAnnounce();
1630+
if (urls.isEmpty())
1631+
{
1632+
torrent->forceReannounce();
1633+
torrent->forceDHTAnnounce();
1634+
}
1635+
else
1636+
{
1637+
const QList<BitTorrent::TrackerEntryStatus> &trackers = torrent->trackers();
1638+
for (qsizetype i = 0; i < trackers.size(); ++i)
1639+
{
1640+
const BitTorrent::TrackerEntryStatus &status = trackers.at(i);
1641+
if (urls.contains(status.url))
1642+
torrent->forceReannounce(i);
1643+
}
1644+
}
16251645
});
16261646

16271647
setResult(QString());

src/webui/www/private/index.html

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -248,6 +248,8 @@ <h1 class="applicationTitle">qBittorrent Web User Interface <span class="version
248248
<li class="separator"><a href="#EditTracker"><img src="images/edit-rename.svg" alt="QBT_TR(Edit tracker URL...)QBT_TR[CONTEXT=TrackerListWidget]"> QBT_TR(Edit tracker URL...)QBT_TR[CONTEXT=TrackerListWidget]</a></li>
249249
<li><a href="#RemoveTracker"><img src="images/list-remove.svg" alt="QBT_TR(Remove tracker)QBT_TR[CONTEXT=TrackerListWidget]"> QBT_TR(Remove tracker)QBT_TR[CONTEXT=TrackerListWidget]</a></li>
250250
<li><a href="#CopyTrackerUrl" id="CopyTrackerUrl"><img src="images/edit-copy.svg" alt="QBT_TR(Copy tracker URL)QBT_TR[CONTEXT=TrackerListWidget]"> QBT_TR(Copy tracker URL)QBT_TR[CONTEXT=TrackerListWidget]</a></li>
251+
<li><a href="#ReannounceTrackers" id="ReannounceTrackers"><img src="images/view-refresh.svg" alt="QBT_TR(Copy tracker URL)QBT_TR[CONTEXT=TrackerListWidget]"> QBT_TR(Force reannounce to selected tracker(s))QBT_TR[CONTEXT=TrackerListWidget]</a></li>
252+
<li class="separator"><a href="#ReannounceAllTrackers" id="ReannounceAllTrackers"><img src="images/view-refresh.svg" alt="QBT_TR(Copy tracker URL)QBT_TR[CONTEXT=TrackerListWidget]"> QBT_TR(Force reannounce to all trackers)QBT_TR[CONTEXT=TrackerListWidget]</a></li>
251253
</ul>
252254
<ul id="torrentPeersMenu" class="contextMenu">
253255
<li><a href="#addPeer"><img src="images/peers-add.svg" alt="QBT_TR(Add peers...)QBT_TR[CONTEXT=PeerListWidget]"> QBT_TR(Add peers...)QBT_TR[CONTEXT=PeerListWidget]</a></li>

src/webui/www/private/scripts/dynamicTable.js

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1818,6 +1818,11 @@ window.qBittorrent.DynamicTable ??= (() => {
18181818
onSelectedRowChanged() {
18191819
updatePropertiesPanel();
18201820
}
1821+
1822+
isStopped(hash) {
1823+
const row = this.getRow(hash);
1824+
return (row === undefined) ? true : row.full_data.state.includes("stopped");
1825+
}
18211826
}
18221827

18231828
class TorrentPeersTable extends DynamicTable {

src/webui/www/private/scripts/prop-trackers.js

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -148,6 +148,12 @@ window.qBittorrent.PropTrackers ??= (() => {
148148
},
149149
RemoveTracker: (element, ref) => {
150150
removeTrackerFN(element);
151+
},
152+
ReannounceTrackers: (element, ref) => {
153+
reannounceTrackersFN(element, torrentTrackersTable.selectedRowsIds());
154+
},
155+
ReannounceAllTrackers: (element, ref) => {
156+
reannounceTrackersFN(element, []);
151157
}
152158
},
153159
offsets: {
@@ -164,6 +170,8 @@ window.qBittorrent.PropTrackers ??= (() => {
164170
this.hideItem("EditTracker");
165171
this.hideItem("RemoveTracker");
166172
this.hideItem("CopyTrackerUrl");
173+
this.hideItem("ReannounceTrackers");
174+
this.hideItem("ReannounceAllTrackers");
167175
}
168176
else {
169177
if (selectedTrackers.length === 1)
@@ -173,6 +181,16 @@ window.qBittorrent.PropTrackers ??= (() => {
173181

174182
this.showItem("RemoveTracker");
175183
this.showItem("CopyTrackerUrl");
184+
185+
const torrentHash = torrentsTable.getCurrentTorrentID();
186+
if (torrentsTable.isStopped(torrentHash)) {
187+
this.hideItem("ReannounceTrackers");
188+
this.hideItem("ReannounceAllTrackers");
189+
}
190+
else {
191+
this.showItem("ReannounceTrackers");
192+
this.showItem("ReannounceAllTrackers");
193+
}
176194
}
177195
}
178196
});
@@ -253,6 +271,28 @@ window.qBittorrent.PropTrackers ??= (() => {
253271
});
254272
};
255273

274+
const reannounceTrackersFN = (element, trackers) => {
275+
if (current_hash.length === 0)
276+
return;
277+
278+
const body = new URLSearchParams({
279+
hashes: current_hash
280+
});
281+
if (trackers.length > 0)
282+
body.set("urls", trackers.map(encodeURIComponent).join("|"));
283+
284+
fetch("api/v2/torrents/reannounce", {
285+
method: "POST",
286+
body: body
287+
})
288+
.then((response) => {
289+
if (!response.ok)
290+
return;
291+
292+
updateData();
293+
});
294+
};
295+
256296
const clear = () => {
257297
torrentTrackersTable.clear();
258298
};

0 commit comments

Comments
 (0)