mirror of
https://github.com/d47081/qBittorrent.git
synced 2025-01-22 20:44:15 +00:00
Merge pull request #10158 from Piccirello/webui-peers-table
Add ability to add and ban a peer from the Web UI
This commit is contained in:
commit
7d598b18ca
@ -40,6 +40,7 @@
|
|||||||
#include <QUrl>
|
#include <QUrl>
|
||||||
|
|
||||||
#include "base/bittorrent/downloadpriority.h"
|
#include "base/bittorrent/downloadpriority.h"
|
||||||
|
#include "base/bittorrent/peeraddress.h"
|
||||||
#include "base/bittorrent/peerinfo.h"
|
#include "base/bittorrent/peerinfo.h"
|
||||||
#include "base/bittorrent/session.h"
|
#include "base/bittorrent/session.h"
|
||||||
#include "base/bittorrent/torrenthandle.h"
|
#include "base/bittorrent/torrenthandle.h"
|
||||||
@ -681,6 +682,42 @@ void TorrentsController::removeTrackersAction()
|
|||||||
torrent->forceReannounce();
|
torrent->forceReannounce();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void TorrentsController::addPeersAction()
|
||||||
|
{
|
||||||
|
checkParams({"hashes", "peers"});
|
||||||
|
|
||||||
|
const QStringList hashes = params()["hashes"].split('|');
|
||||||
|
const QStringList peers = params()["peers"].split('|');
|
||||||
|
|
||||||
|
QVector<BitTorrent::PeerAddress> peerList;
|
||||||
|
peerList.reserve(peers.size());
|
||||||
|
for (const QString &peer : peers) {
|
||||||
|
const BitTorrent::PeerAddress addr = BitTorrent::PeerAddress::parse(peer.trimmed());
|
||||||
|
if (!addr.ip.isNull())
|
||||||
|
peerList.append(addr);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (peerList.isEmpty())
|
||||||
|
throw APIError(APIErrorType::BadParams, "No valid peers were specified");
|
||||||
|
|
||||||
|
QJsonObject results;
|
||||||
|
|
||||||
|
applyToTorrents(hashes, [peers, peerList, &results](BitTorrent::TorrentHandle *const torrent)
|
||||||
|
{
|
||||||
|
const int peersAdded = std::count_if(peerList.cbegin(), peerList.cend(), [torrent](const BitTorrent::PeerAddress &peer)
|
||||||
|
{
|
||||||
|
return torrent->connectPeer(peer);
|
||||||
|
});
|
||||||
|
|
||||||
|
results[torrent->hash()] = QJsonObject {
|
||||||
|
{"added", peersAdded},
|
||||||
|
{"failed", (peers.size() - peersAdded)}
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
|
setResult(results);
|
||||||
|
}
|
||||||
|
|
||||||
void TorrentsController::pauseAction()
|
void TorrentsController::pauseAction()
|
||||||
{
|
{
|
||||||
checkParams({"hashes"});
|
checkParams({"hashes"});
|
||||||
|
@ -66,6 +66,7 @@ private slots:
|
|||||||
void addTrackersAction();
|
void addTrackersAction();
|
||||||
void editTrackerAction();
|
void editTrackerAction();
|
||||||
void removeTrackersAction();
|
void removeTrackersAction();
|
||||||
|
void addPeersAction();
|
||||||
void filePrioAction();
|
void filePrioAction();
|
||||||
void uploadLimitAction();
|
void uploadLimitAction();
|
||||||
void downloadLimitAction();
|
void downloadLimitAction();
|
||||||
|
@ -29,8 +29,13 @@
|
|||||||
#include "transfercontroller.h"
|
#include "transfercontroller.h"
|
||||||
|
|
||||||
#include <QJsonObject>
|
#include <QJsonObject>
|
||||||
|
#include <QVector>
|
||||||
|
|
||||||
|
#include "base/bittorrent/peeraddress.h"
|
||||||
|
#include "base/bittorrent/peerinfo.h"
|
||||||
#include "base/bittorrent/session.h"
|
#include "base/bittorrent/session.h"
|
||||||
|
#include "base/global.h"
|
||||||
|
#include "apierror.h"
|
||||||
|
|
||||||
const char KEY_TRANSFER_DLSPEED[] = "dl_info_speed";
|
const char KEY_TRANSFER_DLSPEED[] = "dl_info_speed";
|
||||||
const char KEY_TRANSFER_DLDATA[] = "dl_info_data";
|
const char KEY_TRANSFER_DLDATA[] = "dl_info_data";
|
||||||
@ -111,3 +116,15 @@ void TransferController::speedLimitsModeAction()
|
|||||||
{
|
{
|
||||||
setResult(QString::number(BitTorrent::Session::instance()->isAltGlobalSpeedLimitEnabled()));
|
setResult(QString::number(BitTorrent::Session::instance()->isAltGlobalSpeedLimitEnabled()));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void TransferController::banPeersAction()
|
||||||
|
{
|
||||||
|
checkParams({"peers"});
|
||||||
|
|
||||||
|
const QStringList peers = params()["peers"].split('|');
|
||||||
|
for (const QString &peer : peers) {
|
||||||
|
const BitTorrent::PeerAddress addr = BitTorrent::PeerAddress::parse(peer.trimmed());
|
||||||
|
if (!addr.ip.isNull())
|
||||||
|
BitTorrent::Session::instance()->banIP(addr.ip.toString());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -46,4 +46,5 @@ private slots:
|
|||||||
void downloadLimitAction();
|
void downloadLimitAction();
|
||||||
void setUploadLimitAction();
|
void setUploadLimitAction();
|
||||||
void setDownloadLimitAction();
|
void setDownloadLimitAction();
|
||||||
|
void banPeersAction();
|
||||||
};
|
};
|
||||||
|
69
src/webui/www/private/addpeers.html
Normal file
69
src/webui/www/private/addpeers.html
Normal file
@ -0,0 +1,69 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="${LANG}">
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8" />
|
||||||
|
<title>QBT_TR(Add Peers)QBT_TR[CONTEXT=PeersAdditionDialog]</title>
|
||||||
|
<link rel="stylesheet" href="css/style.css?v=${CACHEID}" type="text/css" />
|
||||||
|
<script src="scripts/lib/mootools-1.2-core-yc.js"></script>
|
||||||
|
<script src="scripts/lib/mootools-1.2-more.js"></script>
|
||||||
|
<script>
|
||||||
|
'use strict';
|
||||||
|
|
||||||
|
new Keyboard({
|
||||||
|
defaultEventType: 'keydown',
|
||||||
|
events: {
|
||||||
|
'Escape': function(event) {
|
||||||
|
window.parent.closeWindows();
|
||||||
|
event.preventDefault();
|
||||||
|
},
|
||||||
|
'Esc': function(event) {
|
||||||
|
window.parent.closeWindows();
|
||||||
|
event.preventDefault();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}).activate();
|
||||||
|
|
||||||
|
window.addEvent('domready', function() {
|
||||||
|
const hash = new URI().getData('hash');
|
||||||
|
if (!hash)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
$('peers').focus();
|
||||||
|
|
||||||
|
$('addPeersOk').addEvent('click', function(e) {
|
||||||
|
new Event(e).stop();
|
||||||
|
|
||||||
|
const peers = $('peers').get('value').trim().split(/[\r\n]+/);
|
||||||
|
if (peers.length === 0)
|
||||||
|
return
|
||||||
|
|
||||||
|
new Request({
|
||||||
|
url: 'api/v2/torrents/addPeers',
|
||||||
|
method: 'post',
|
||||||
|
data: {
|
||||||
|
hashes: hash,
|
||||||
|
peers: peers.join(';')
|
||||||
|
},
|
||||||
|
onFailure: function() {
|
||||||
|
alert("QBT_TR(Unable to add peers. Please ensure you are adhering to the IP:port format.)QBT_TR[CONTEXT=HttpServer]");
|
||||||
|
},
|
||||||
|
onSuccess: function() {
|
||||||
|
window.parent.closeWindows();
|
||||||
|
}
|
||||||
|
}).send();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
</head>
|
||||||
|
|
||||||
|
<body>
|
||||||
|
<div style="padding: 10px 10px 0px 10px;">
|
||||||
|
<p>QBT_TR(List of peers to add (one IP per line):)QBT_TR[CONTEXT=PeersAdditionDialog]</p>
|
||||||
|
<textarea id="peers" rows="10" style="width: 100%;" placeholder="QBT_TR(Format: IPv4:port / [IPv6]:port)QBT_TR[CONTEXT=PeersAdditionDialog]"></textarea>
|
||||||
|
<div style="margin-top: 10px; text-align: center;">
|
||||||
|
<button onclick="window.parent.closeWindows();">QBT_TR(Cancel)QBT_TR[CONTEXT=PeersAdditionDialog]</button>
|
||||||
|
<button id="addPeersOk">QBT_TR(Ok)QBT_TR[CONTEXT=PeersAdditionDialog]</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</body>
|
||||||
|
</html>
|
@ -190,6 +190,11 @@
|
|||||||
<li><a href="#RemoveTracker"><img src="images/qbt-theme/list-remove.svg" alt="QBT_TR(Remove tracker)QBT_TR[CONTEXT=TrackerListWidget]"/> QBT_TR(Remove tracker)QBT_TR[CONTEXT=TrackerListWidget]</a></li>
|
<li><a href="#RemoveTracker"><img src="images/qbt-theme/list-remove.svg" alt="QBT_TR(Remove tracker)QBT_TR[CONTEXT=TrackerListWidget]"/> QBT_TR(Remove tracker)QBT_TR[CONTEXT=TrackerListWidget]</a></li>
|
||||||
<li><a href="#CopyTrackerUrl" id="CopyTrackerUrl"><img src="images/qbt-theme/edit-copy.svg" alt="QBT_TR(Copy tracker URL)QBT_TR[CONTEXT=TrackerListWidget]"/> QBT_TR(Copy tracker URL)QBT_TR[CONTEXT=TrackerListWidget]</a></li>
|
<li><a href="#CopyTrackerUrl" id="CopyTrackerUrl"><img src="images/qbt-theme/edit-copy.svg" alt="QBT_TR(Copy tracker URL)QBT_TR[CONTEXT=TrackerListWidget]"/> QBT_TR(Copy tracker URL)QBT_TR[CONTEXT=TrackerListWidget]</a></li>
|
||||||
</ul>
|
</ul>
|
||||||
|
<ul id="torrentPeersMenu" class="contextMenu">
|
||||||
|
<li><a href="#addPeer"><img src="images/qbt-theme/list-add.svg" alt="QBT_TR(Add a new peer...)QBT_TR[CONTEXT=PeerListWidget]"/> QBT_TR(Add a new peer...)QBT_TR[CONTEXT=PeerListWidget]</a></li>
|
||||||
|
<li><a href="#copyPeer" id="CopyPeerInfo"><img src="images/qbt-theme/edit-copy.svg" alt="QBT_TR(Copy IP:port)QBT_TR[CONTEXT=PeerListWidget]"/> QBT_TR(Copy IP:port)QBT_TR[CONTEXT=PeerListWidget]</a></li>
|
||||||
|
<li class="separator"><a href="#banPeer"><img src="images/qbt-theme/user-group-delete.svg" alt="QBT_TR(Ban peer permanently)QBT_TR[CONTEXT=PeerListWidget]"/> QBT_TR(Ban peer permanently)QBT_TR[CONTEXT=PeerListWidget]</a></li>
|
||||||
|
</ul>
|
||||||
<ul id="torrentFilesMenu" class="contextMenu">
|
<ul id="torrentFilesMenu" class="contextMenu">
|
||||||
<li>
|
<li>
|
||||||
<a href="#FilePrio" class="arrow-right"><span style="display: inline-block; width: 16px;"></span> QBT_TR(Priority)QBT_TR[CONTEXT=PropertiesWidget]</a>
|
<a href="#FilePrio" class="arrow-right"><span style="display: inline-block; width: 16px;"></span> QBT_TR(Priority)QBT_TR[CONTEXT=PropertiesWidget]</a>
|
||||||
|
@ -103,4 +103,69 @@ updateTorrentPeersData = function() {
|
|||||||
loadTorrentPeersData();
|
loadTorrentPeersData();
|
||||||
};
|
};
|
||||||
|
|
||||||
torrentPeersTable.setup('torrentPeersTableDiv', 'torrentPeersTableFixedHeaderDiv', null);
|
const torrentPeersContextMenu = new ContextMenu({
|
||||||
|
targets: '#torrentPeersTableDiv',
|
||||||
|
menu: 'torrentPeersMenu',
|
||||||
|
actions: {
|
||||||
|
addPeer: function(element, ref) {
|
||||||
|
const hash = torrentsTable.getCurrentTorrentHash();
|
||||||
|
if (!hash)
|
||||||
|
return;
|
||||||
|
|
||||||
|
new MochaUI.Window({
|
||||||
|
id: 'addPeersPage',
|
||||||
|
title: "QBT_TR(Add Peers)QBT_TR[CONTEXT=PeersAdditionDialog]",
|
||||||
|
loadMethod: 'iframe',
|
||||||
|
contentURL: 'addpeers.html?hash=' + hash,
|
||||||
|
scrollbars: false,
|
||||||
|
resizable: false,
|
||||||
|
maximizable: false,
|
||||||
|
paddingVertical: 0,
|
||||||
|
paddingHorizontal: 0,
|
||||||
|
width: 350,
|
||||||
|
height: 240
|
||||||
|
});
|
||||||
|
},
|
||||||
|
banPeer: function(element, ref) {
|
||||||
|
const selectedPeers = torrentPeersTable.selectedRowsIds();
|
||||||
|
if (selectedPeers.length === 0)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (confirm('QBT_TR(Are you sure you want to permanently ban the selected peers?)QBT_TR[CONTEXT=PeerListWidget]')) {
|
||||||
|
new Request({
|
||||||
|
url: 'api/v2/torrents/banPeers',
|
||||||
|
noCache: true,
|
||||||
|
method: 'post',
|
||||||
|
data: {
|
||||||
|
hash: torrentsTable.getCurrentTorrentHash(),
|
||||||
|
peers: selectedPeers.join('|')
|
||||||
|
}
|
||||||
|
}).send();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
offsets: {
|
||||||
|
x: -15,
|
||||||
|
y: 2
|
||||||
|
},
|
||||||
|
onShow: function() {
|
||||||
|
const selectedPeers = torrentPeersTable.selectedRowsIds();
|
||||||
|
|
||||||
|
if (selectedPeers.length >= 1) {
|
||||||
|
this.showItem('copyPeer');
|
||||||
|
this.showItem('banPeer');
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
this.hideItem('copyPeer');
|
||||||
|
this.hideItem('banPeer');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
new ClipboardJS('#CopyPeerInfo', {
|
||||||
|
text: function(trigger) {
|
||||||
|
return torrentPeersTable.selectedRowsIds().join("\n");
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
torrentPeersTable.setup('torrentPeersTableDiv', 'torrentPeersTableFixedHeaderDiv', torrentPeersContextMenu);
|
||||||
|
@ -2,6 +2,7 @@
|
|||||||
<qresource prefix="/www">
|
<qresource prefix="/www">
|
||||||
<file>private/about.html</file>
|
<file>private/about.html</file>
|
||||||
<file>private/aboutToolbar.html</file>
|
<file>private/aboutToolbar.html</file>
|
||||||
|
<file>private/addpeers.html</file>
|
||||||
<file>private/addtrackers.html</file>
|
<file>private/addtrackers.html</file>
|
||||||
<file>private/confirmdeletion.html</file>
|
<file>private/confirmdeletion.html</file>
|
||||||
<file>private/css/Core.css</file>
|
<file>private/css/Core.css</file>
|
||||||
|
Loading…
x
Reference in New Issue
Block a user