2 * Bittorrent Client using Qt and libtorrent.
3 * Copyright (C) 2009 Christophe Dumez <chris@qbittorrent.org>
5 * This program is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU General Public License
7 * as published by the Free Software Foundation; either version 2
8 * of the License, or (at your option) any later version.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
19 * In addition, as a special exception, the copyright holders give permission to
20 * link this program with the OpenSSL project's "OpenSSL" library (or with
21 * modified versions of it that use the same license as the "OpenSSL" library),
22 * and distribute the linked executables. You must obey the GNU General Public
23 * License in all respects for all of the code used other than "OpenSSL". If you
24 * modify file(s), you may extend this exception to your version of the file(s),
25 * but you are not obligated to do so. If you do not wish to do so, delete this
26 * exception statement from your version.
31 window.qBittorrent ??= {};
32 window.qBittorrent.PropTrackers ??= (() => {
33 const exports = () => {
35 updateData: updateData,
40 let current_hash = "";
42 const torrentTrackersTable = new window.qBittorrent.DynamicTable.TorrentTrackersTable();
43 let loadTrackersDataTimer = -1;
45 const loadTrackersData = () => {
46 if ($("propTrackers").classList.contains("invisible")
47 || $("propertiesPanel_collapseToggle").classList.contains("panel-expand")) {
48 // Tab changed, don't do anything
51 const new_hash = torrentsTable.getCurrentTorrentID();
52 if (new_hash === "") {
53 torrentTrackersTable.clear();
54 clearTimeout(loadTrackersDataTimer);
57 if (new_hash !== current_hash) {
58 torrentTrackersTable.clear();
59 current_hash = new_hash;
61 const url = new URI("api/v2/torrents/trackers?hash=" + current_hash);
67 clearTimeout(loadTrackersDataTimer);
68 loadTrackersDataTimer = loadTrackersData.delay(10000);
70 onSuccess: (trackers) => {
71 const selectedTrackers = torrentTrackersTable.selectedRowsIds();
72 torrentTrackersTable.clear();
75 trackers.each((tracker) => {
77 switch (tracker.status) {
79 status = "QBT_TR(Disabled)QBT_TR[CONTEXT=TrackerListWidget]";
82 status = "QBT_TR(Not contacted yet)QBT_TR[CONTEXT=TrackerListWidget]";
85 status = "QBT_TR(Working)QBT_TR[CONTEXT=TrackerListWidget]";
88 status = "QBT_TR(Updating...)QBT_TR[CONTEXT=TrackerListWidget]";
91 status = "QBT_TR(Not working)QBT_TR[CONTEXT=TrackerListWidget]";
97 tier: (tracker.tier >= 0) ? tracker.tier : "",
100 peers: (tracker.num_peers >= 0) ? tracker.num_peers : "QBT_TR(N/A)QBT_TR[CONTEXT=TrackerListWidget]",
101 seeds: (tracker.num_seeds >= 0) ? tracker.num_seeds : "QBT_TR(N/A)QBT_TR[CONTEXT=TrackerListWidget]",
102 leeches: (tracker.num_leeches >= 0) ? tracker.num_leeches : "QBT_TR(N/A)QBT_TR[CONTEXT=TrackerListWidget]",
103 downloaded: (tracker.num_downloaded >= 0) ? tracker.num_downloaded : "QBT_TR(N/A)QBT_TR[CONTEXT=TrackerListWidget]",
104 message: tracker.msg,
105 _sortable: !tracker.url.startsWith("** [")
108 torrentTrackersTable.updateRowData(row);
111 torrentTrackersTable.updateTable(false);
113 if (selectedTrackers.length > 0)
114 torrentTrackersTable.reselectRows(selectedTrackers);
120 const updateData = () => {
121 clearTimeout(loadTrackersDataTimer);
122 loadTrackersDataTimer = -1;
126 const torrentTrackersContextMenu = new window.qBittorrent.ContextMenu.ContextMenu({
127 targets: "#torrentTrackersTableDiv",
128 menu: "torrentTrackersMenu",
130 AddTracker: (element, ref) => {
133 EditTracker: (element, ref) => {
134 // only allow editing of one row
135 element.firstElementChild.click();
136 editTrackerFN(element);
138 RemoveTracker: (element, ref) => {
139 removeTrackerFN(element);
147 const selectedTrackers = torrentTrackersTable.selectedRowsIds();
148 const containsStaticTracker = selectedTrackers.some((tracker) => {
149 return tracker.startsWith("** [");
152 if (containsStaticTracker || (selectedTrackers.length === 0)) {
153 this.hideItem("EditTracker");
154 this.hideItem("RemoveTracker");
155 this.hideItem("CopyTrackerUrl");
158 this.showItem("EditTracker");
159 this.showItem("RemoveTracker");
160 this.showItem("CopyTrackerUrl");
165 const addTrackerFN = () => {
166 if (current_hash.length === 0)
170 icon: "images/qbittorrent-tray.svg",
171 title: "QBT_TR(Add trackers)QBT_TR[CONTEXT=TrackersAdditionDialog]",
172 loadMethod: "iframe",
173 contentURL: "addtrackers.html?hash=" + current_hash,
179 paddingHorizontal: 0,
182 onCloseComplete: () => {
188 const editTrackerFN = (element) => {
189 if (current_hash.length === 0)
192 const trackerUrl = encodeURIComponent(element.childNodes[1].textContent);
195 icon: "images/qbittorrent-tray.svg",
196 title: "QBT_TR(Tracker editing)QBT_TR[CONTEXT=TrackerListWidget]",
197 loadMethod: "iframe",
198 contentURL: "edittracker.html?hash=" + current_hash + "&url=" + trackerUrl,
204 paddingHorizontal: 0,
207 onCloseComplete: () => {
213 const removeTrackerFN = (element) => {
214 if (current_hash.length === 0)
217 const selectedTrackers = torrentTrackersTable.selectedRowsIds();
219 url: "api/v2/torrents/removeTrackers",
223 urls: selectedTrackers.map(encodeURIComponent).join("|")
231 const clear = () => {
232 torrentTrackersTable.clear();
235 new ClipboardJS("#CopyTrackerUrl", {
237 return torrentTrackersTable.selectedRowsIds().join("\n");
241 torrentTrackersTable.setup("torrentTrackersTableDiv", "torrentTrackersTableFixedHeaderDiv", torrentTrackersContextMenu);
245 Object.freeze(window.qBittorrent.PropTrackers);